xfrm: introduce helper for safe determination of mtu
skb->sk socket can be of AF_INET or AF_INET6 address family. Thus we always have to make sure we a referring to the correct interpretation of skb->sk. We only depend on header defines to query the mtu, so we don't introduce a new dependency to ipv6 by this change. Cc: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
		
							parent
							
								
									628e341f31
								
							
						
					
					
						commit
						0ea9d5e3e0
					
				| @ -317,4 +317,12 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst) | ||||
| 	return hoplimit; | ||||
| } | ||||
| 
 | ||||
| static inline int ip_skb_dst_mtu(struct sk_buff *skb) | ||||
| { | ||||
| 	struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL; | ||||
| 
 | ||||
| 	return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ? | ||||
| 	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | ||||
| } | ||||
| 
 | ||||
| #endif	/* _ROUTE_H */ | ||||
|  | ||||
| @ -20,6 +20,7 @@ | ||||
| #include <net/route.h> | ||||
| #include <net/ipv6.h> | ||||
| #include <net/ip6_fib.h> | ||||
| #include <net/ip6_route.h> | ||||
| #include <net/flow.h> | ||||
| 
 | ||||
| #include <linux/interrupt.h> | ||||
| @ -1723,4 +1724,15 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m) | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static inline int xfrm_skb_dst_mtu(struct sk_buff *skb) | ||||
| { | ||||
| 	struct sock *sk = skb->sk; | ||||
| 
 | ||||
| 	if (sk && sk->sk_family == AF_INET6) | ||||
| 		return ip6_skb_dst_mtu(skb); | ||||
| 	else if (sk && sk->sk_family == AF_INET) | ||||
| 		return ip_skb_dst_mtu(skb); | ||||
| 	return dst_mtu(skb_dst(skb)); | ||||
| } | ||||
| 
 | ||||
| #endif	/* _NET_XFRM_H */ | ||||
|  | ||||
| @ -211,14 +211,6 @@ static inline int ip_finish_output2(struct sk_buff *skb) | ||||
| 	return -EINVAL; | ||||
| } | ||||
| 
 | ||||
| static inline int ip_skb_dst_mtu(struct sk_buff *skb) | ||||
| { | ||||
| 	struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL; | ||||
| 
 | ||||
| 	return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ? | ||||
| 	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | ||||
| } | ||||
| 
 | ||||
| static int ip_finish_output(struct sk_buff *skb) | ||||
| { | ||||
| #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | ||||
|  | ||||
| @ -21,7 +21,6 @@ | ||||
| static int xfrm4_tunnel_check_size(struct sk_buff *skb) | ||||
| { | ||||
| 	int mtu, ret = 0; | ||||
| 	struct dst_entry *dst; | ||||
| 
 | ||||
| 	if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE) | ||||
| 		goto out; | ||||
| @ -29,8 +28,7 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb) | ||||
| 	if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	dst = skb_dst(skb); | ||||
| 	mtu = dst_mtu(dst); | ||||
| 	mtu = xfrm_skb_dst_mtu(skb); | ||||
| 	if (skb->len > mtu) { | ||||
| 		if (skb->sk) | ||||
| 			xfrm_local_error(skb, mtu); | ||||
|  | ||||
| @ -138,7 +138,10 @@ static int __xfrm6_output(struct sk_buff *skb) | ||||
| { | ||||
| 	struct dst_entry *dst = skb_dst(skb); | ||||
| 	struct xfrm_state *x = dst->xfrm; | ||||
| 	int mtu = ip6_skb_dst_mtu(skb); | ||||
| 	int mtu = xfrm_skb_dst_mtu(skb); | ||||
| 
 | ||||
| 	if (mtu < IPV6_MIN_MTU) | ||||
| 		mtu = IPV6_MIN_MTU; | ||||
| 
 | ||||
| 	if (skb->len > mtu && xfrm6_local_dontfrag(skb)) { | ||||
| 		xfrm6_local_rxpmtu(skb, mtu); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user