summaryrefslogtreecommitdiff
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-01-11 19:15:08 -0800
committerDavid S. Miller <davem@davemloft.net>2008-01-28 14:53:47 -0800
commitef76bc23ef2acf20c8f7f841a542d8ab74c827c6 (patch)
tree11ae8004f4c25ac91339f13a86fdd9f170faeb2e /net/ipv6/ip6_output.c
parentc439cb2e4b13cf1cb2abcd006b906315a3381323 (diff)
downloadlwn-ef76bc23ef2acf20c8f7f841a542d8ab74c827c6.tar.gz
lwn-ef76bc23ef2acf20c8f7f841a542d8ab74c827c6.zip
[IPV6]: Add ip6_local_out
Most callers of the LOCAL_OUT chain will set the IP packet length before doing so. They also share the same output function dst_output. This patch creates a new function called ip6_local_out which does all of that and converts the appropriate users over to it. Apart from removing duplicate code, it will also help in merging the IPsec output path. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 387030d2483c..bd121f9ae0a7 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -29,7 +29,7 @@
*/
#include <linux/errno.h>
-#include <linux/types.h>
+#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/net.h>
@@ -70,6 +70,31 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f
spin_unlock_bh(&ip6_id_lock);
}
+int __ip6_local_out(struct sk_buff *skb)
+{
+ int len;
+
+ len = skb->len - sizeof(struct ipv6hdr);
+ if (len > IPV6_MAXPLEN)
+ len = 0;
+ ipv6_hdr(skb)->payload_len = htons(len);
+
+ return nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev,
+ dst_output);
+}
+
+int ip6_local_out(struct sk_buff *skb)
+{
+ int err;
+
+ err = __ip6_local_out(skb);
+ if (likely(err == 1))
+ err = dst_output(skb);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(ip6_local_out);
+
static int ip6_output_finish(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
@@ -1403,10 +1428,6 @@ int ip6_push_pending_frames(struct sock *sk)
*(__be32*)hdr = fl->fl6_flowlabel |
htonl(0x60000000 | ((int)np->cork.tclass << 20));
- if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
- hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
- else
- hdr->payload_len = 0;
hdr->hop_limit = np->cork.hop_limit;
hdr->nexthdr = proto;
ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
@@ -1423,7 +1444,7 @@ int ip6_push_pending_frames(struct sock *sk)
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
}
- err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
+ err = ip6_local_out(skb);
if (err) {
if (err > 0)
err = np->recverr ? net_xmit_errno(err) : 0;