ipv6: support IPV6_PMTU_INTERFACE on sockets
IPV6_PMTU_INTERFACE is the same as IPV6_PMTU_PROBE for ipv6. Add it nontheless for symmetry with IPv4 sockets. Also drop incoming MTU information if this mode is enabled. The additional bit in ipv6_pinfo just eats in the padding behind the bitfield. There are no changes to the layout of the struct at all. Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									cd174e67a6
								
							
						
					
					
						commit
						93b36cf342
					
				| @ -191,7 +191,7 @@ struct ipv6_pinfo { | ||||
| 	/* sockopt flags */ | ||||
| 	__u16			recverr:1, | ||||
| 	                        sndflow:1, | ||||
| 				pmtudisc:2, | ||||
| 				pmtudisc:3, | ||||
| 				ipv6only:1, | ||||
| 				srcprefs:3,	/* 001: prefer temporary address
 | ||||
| 						 * 010: prefer public address | ||||
|  | ||||
| @ -178,10 +178,15 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | ||||
| { | ||||
| 	struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; | ||||
| 
 | ||||
| 	return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ? | ||||
| 	return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ? | ||||
| 	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | ||||
| } | ||||
| 
 | ||||
| static inline bool ip6_sk_accept_pmtu(const struct sock *sk) | ||||
| { | ||||
| 	return inet6_sk(sk)->pmtudisc != IPV6_PMTUDISC_INTERFACE; | ||||
| } | ||||
| 
 | ||||
| static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt) | ||||
| { | ||||
| 	return &rt->rt6i_gateway; | ||||
|  | ||||
| @ -188,6 +188,10 @@ enum { | ||||
| #define IPV6_PMTUDISC_WANT		1 | ||||
| #define IPV6_PMTUDISC_DO		2 | ||||
| #define IPV6_PMTUDISC_PROBE		3 | ||||
| /* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4
 | ||||
|  * also see comments on IP_PMTUDISC_INTERFACE | ||||
|  */ | ||||
| #define IPV6_PMTUDISC_INTERFACE		4 | ||||
| 
 | ||||
| /* Flowlabel */ | ||||
| #define IPV6_FLOWLABEL_MGR	32 | ||||
|  | ||||
| @ -141,6 +141,9 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||||
| 	if (type == ICMPV6_PKT_TOOBIG) { | ||||
| 		struct dst_entry *dst = NULL; | ||||
| 
 | ||||
| 		if (!ip6_sk_accept_pmtu(sk)) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		if (sock_owned_by_user(sk)) | ||||
| 			goto out; | ||||
| 		if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED)) | ||||
|  | ||||
| @ -1165,10 +1165,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | ||||
| 		np->cork.hop_limit = hlimit; | ||||
| 		np->cork.tclass = tclass; | ||||
| 		if (rt->dst.flags & DST_XFRM_TUNNEL) | ||||
| 			mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | ||||
| 			mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? | ||||
| 			      rt->dst.dev->mtu : dst_mtu(&rt->dst); | ||||
| 		else | ||||
| 			mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | ||||
| 			mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? | ||||
| 			      rt->dst.dev->mtu : dst_mtu(rt->dst.path); | ||||
| 		if (np->frag_size < mtu) { | ||||
| 			if (np->frag_size) | ||||
| @ -1270,7 +1270,7 @@ alloc_new_skb: | ||||
| 			if (skb == NULL || skb_prev == NULL) | ||||
| 				ip6_append_data_mtu(&mtu, &maxfraglen, | ||||
| 						    fragheaderlen, skb, rt, | ||||
| 						    np->pmtudisc == | ||||
| 						    np->pmtudisc >= | ||||
| 						    IPV6_PMTUDISC_PROBE); | ||||
| 
 | ||||
| 			skb_prev = skb; | ||||
|  | ||||
| @ -722,7 +722,7 @@ done: | ||||
| 	case IPV6_MTU_DISCOVER: | ||||
| 		if (optlen < sizeof(int)) | ||||
| 			goto e_inval; | ||||
| 		if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_PROBE) | ||||
| 		if (val < IPV6_PMTUDISC_DONT || val > IPV6_PMTUDISC_INTERFACE) | ||||
| 			goto e_inval; | ||||
| 		np->pmtudisc = val; | ||||
| 		retv = 0; | ||||
|  | ||||
| @ -397,6 +397,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||||
| 		if (sk->sk_state == TCP_LISTEN) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		if (!ip6_sk_accept_pmtu(sk)) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		tp->mtu_info = ntohl(info); | ||||
| 		if (!sock_owned_by_user(sk)) | ||||
| 			tcp_v6_mtu_reduced(sk); | ||||
|  | ||||
| @ -538,8 +538,11 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||||
| 	if (sk == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (type == ICMPV6_PKT_TOOBIG) | ||||
| 	if (type == ICMPV6_PKT_TOOBIG) { | ||||
| 		if (!ip6_sk_accept_pmtu(sk)) | ||||
| 			goto out; | ||||
| 		ip6_sk_update_pmtu(skb, sk, info); | ||||
| 	} | ||||
| 	if (type == NDISC_REDIRECT) { | ||||
| 		ip6_sk_redirect(skb, sk); | ||||
| 		goto out; | ||||
|  | ||||
| @ -389,6 +389,9 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | ||||
| 	if (!t || (t->pathmtu <= pmtu)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (!ip6_sk_accept_pmtu(sk)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (sock_owned_by_user(sk)) { | ||||
| 		asoc->pmtu_pending = 1; | ||||
| 		t->pmtu_pending = 1; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user