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 387030d2483..bd121f9ae0a 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;  |