diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/ah6.c | 11 | ||||
| -rw-r--r-- | net/ipv6/esp6.c | 5 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 12 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 3 | 
5 files changed, 30 insertions, 5 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index ecc35b93314..384233188ac 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -472,7 +472,10 @@ static void ah6_input_done(struct crypto_async_request *base, int err)  	skb->network_header += ah_hlen;  	memcpy(skb_network_header(skb), work_iph, hdr_len);  	__skb_pull(skb, ah_hlen + hdr_len); -	skb_set_transport_header(skb, -hdr_len); +	if (x->props.mode == XFRM_MODE_TUNNEL) +		skb_reset_transport_header(skb); +	else +		skb_set_transport_header(skb, -hdr_len);  out:  	kfree(AH_SKB_CB(skb)->tmp);  	xfrm_input_resume(skb, err); @@ -593,9 +596,13 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)  	skb->network_header += ah_hlen;  	memcpy(skb_network_header(skb), work_iph, hdr_len); -	skb->transport_header = skb->network_header;  	__skb_pull(skb, ah_hlen + hdr_len); +	if (x->props.mode == XFRM_MODE_TUNNEL) +		skb_reset_transport_header(skb); +	else +		skb_set_transport_header(skb, -hdr_len); +  	err = nexthdr;  out_free: diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 282f3723ee1..40ffd72243a 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -300,7 +300,10 @@ static int esp_input_done2(struct sk_buff *skb, int err)  	pskb_trim(skb, skb->len - alen - padlen - 2);  	__skb_pull(skb, hlen); -	skb_set_transport_header(skb, -hdr_len); +	if (x->props.mode == XFRM_MODE_TUNNEL) +		skb_reset_transport_header(skb); +	else +		skb_set_transport_header(skb, -hdr_len);  	err = nexthdr[1]; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b4a9fd51dae..fff5bdd8b68 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -81,10 +81,22 @@ static inline struct sock *icmpv6_sk(struct net *net)  	return net->ipv6.icmp_sk[smp_processor_id()];  } +static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, +		       u8 type, u8 code, int offset, __be32 info) +{ +	struct net *net = dev_net(skb->dev); + +	if (type == ICMPV6_PKT_TOOBIG) +		ip6_update_pmtu(skb, net, info, 0, 0); +	else if (type == NDISC_REDIRECT) +		ip6_redirect(skb, net, 0, 0); +} +  static int icmpv6_rcv(struct sk_buff *skb);  static const struct inet6_protocol icmpv6_protocol = {  	.handler	=	icmpv6_rcv, +	.err_handler	=	icmpv6_err,  	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,  }; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7dea45af66d..906b7e6dd7f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1190,10 +1190,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,  		if (dst_allfrag(rt->dst.path))  			cork->flags |= IPCORK_ALLFRAG;  		cork->length = 0; -		exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; +		exthdrlen = (opt ? opt->opt_flen : 0);  		length += exthdrlen;  		transhdrlen += exthdrlen; -		dst_exthdrlen = rt->dst.header_len; +		dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len;  	} else {  		rt = (struct rt6_info *)cork->dst;  		fl6 = &inet->cork.fl.u.ip6; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index acc32494006..351ce98e90d 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1766,6 +1766,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns  			return -EINVAL;  		if (get_user(v, (u32 __user *)optval))  			return -EFAULT; +		/* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */ +		if (v != RT_TABLE_DEFAULT && v >= 100000000) +			return -EINVAL;  		if (sk == mrt->mroute6_sk)  			return -EBUSY;  |