diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
| -rw-r--r-- | net/ipv6/ip6_output.c | 33 |
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 @@ | |||
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
| 32 | #include <linux/types.h> | 32 | #include <linux/kernel.h> |
| 33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
| 34 | #include <linux/socket.h> | 34 | #include <linux/socket.h> |
| 35 | #include <linux/net.h> | 35 | #include <linux/net.h> |
| @@ -70,6 +70,31 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f | |||
| 70 | spin_unlock_bh(&ip6_id_lock); | 70 | spin_unlock_bh(&ip6_id_lock); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | int __ip6_local_out(struct sk_buff *skb) | ||
| 74 | { | ||
| 75 | int len; | ||
| 76 | |||
| 77 | len = skb->len - sizeof(struct ipv6hdr); | ||
| 78 | if (len > IPV6_MAXPLEN) | ||
| 79 | len = 0; | ||
| 80 | ipv6_hdr(skb)->payload_len = htons(len); | ||
| 81 | |||
| 82 | return nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, | ||
| 83 | dst_output); | ||
| 84 | } | ||
| 85 | |||
| 86 | int ip6_local_out(struct sk_buff *skb) | ||
| 87 | { | ||
| 88 | int err; | ||
| 89 | |||
| 90 | err = __ip6_local_out(skb); | ||
| 91 | if (likely(err == 1)) | ||
| 92 | err = dst_output(skb); | ||
| 93 | |||
| 94 | return err; | ||
| 95 | } | ||
| 96 | EXPORT_SYMBOL_GPL(ip6_local_out); | ||
| 97 | |||
| 73 | static int ip6_output_finish(struct sk_buff *skb) | 98 | static int ip6_output_finish(struct sk_buff *skb) |
| 74 | { | 99 | { |
| 75 | struct dst_entry *dst = skb->dst; | 100 | struct dst_entry *dst = skb->dst; |
| @@ -1403,10 +1428,6 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1403 | *(__be32*)hdr = fl->fl6_flowlabel | | 1428 | *(__be32*)hdr = fl->fl6_flowlabel | |
| 1404 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | 1429 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); |
| 1405 | 1430 | ||
| 1406 | if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) | ||
| 1407 | hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | ||
| 1408 | else | ||
| 1409 | hdr->payload_len = 0; | ||
| 1410 | hdr->hop_limit = np->cork.hop_limit; | 1431 | hdr->hop_limit = np->cork.hop_limit; |
| 1411 | hdr->nexthdr = proto; | 1432 | hdr->nexthdr = proto; |
| 1412 | ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); | 1433 | ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); |
| @@ -1423,7 +1444,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1423 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); | 1444 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); |
| 1424 | } | 1445 | } |
| 1425 | 1446 | ||
| 1426 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); | 1447 | err = ip6_local_out(skb); |
| 1427 | if (err) { | 1448 | if (err) { |
| 1428 | if (err > 0) | 1449 | if (err > 0) |
| 1429 | err = np->recverr ? net_xmit_errno(err) : 0; | 1450 | err = np->recverr ? net_xmit_errno(err) : 0; |
