Skip to content

Commit 0ea9d5e

Browse files
strssndktnklassert
authored andcommitted
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>
1 parent 628e341 commit 0ea9d5e

File tree

5 files changed

+25
-12
lines changed

5 files changed

+25
-12
lines changed

include/net/route.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,4 +317,12 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
317317
return hoplimit;
318318
}
319319

320+
static inline int ip_skb_dst_mtu(struct sk_buff *skb)
321+
{
322+
struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
323+
324+
return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
325+
skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
326+
}
327+
320328
#endif /* _ROUTE_H */

include/net/xfrm.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <net/route.h>
2121
#include <net/ipv6.h>
2222
#include <net/ip6_fib.h>
23+
#include <net/ip6_route.h>
2324
#include <net/flow.h>
2425

2526
#include <linux/interrupt.h>
@@ -1723,4 +1724,15 @@ static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
17231724
return ret;
17241725
}
17251726

1727+
static inline int xfrm_skb_dst_mtu(struct sk_buff *skb)
1728+
{
1729+
struct sock *sk = skb->sk;
1730+
1731+
if (sk && sk->sk_family == AF_INET6)
1732+
return ip6_skb_dst_mtu(skb);
1733+
else if (sk && sk->sk_family == AF_INET)
1734+
return ip_skb_dst_mtu(skb);
1735+
return dst_mtu(skb_dst(skb));
1736+
}
1737+
17261738
#endif /* _NET_XFRM_H */

net/ipv4/ip_output.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,6 @@ static inline int ip_finish_output2(struct sk_buff *skb)
211211
return -EINVAL;
212212
}
213213

214-
static inline int ip_skb_dst_mtu(struct sk_buff *skb)
215-
{
216-
struct inet_sock *inet = skb->sk ? inet_sk(skb->sk) : NULL;
217-
218-
return (inet && inet->pmtudisc == IP_PMTUDISC_PROBE) ?
219-
skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
220-
}
221-
222214
static int ip_finish_output(struct sk_buff *skb)
223215
{
224216
#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)

net/ipv4/xfrm4_output.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@
2121
static int xfrm4_tunnel_check_size(struct sk_buff *skb)
2222
{
2323
int mtu, ret = 0;
24-
struct dst_entry *dst;
2524

2625
if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
2726
goto out;
2827

2928
if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
3029
goto out;
3130

32-
dst = skb_dst(skb);
33-
mtu = dst_mtu(dst);
31+
mtu = xfrm_skb_dst_mtu(skb);
3432
if (skb->len > mtu) {
3533
if (skb->sk)
3634
xfrm_local_error(skb, mtu);

net/ipv6/xfrm6_output.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,10 @@ static int __xfrm6_output(struct sk_buff *skb)
138138
{
139139
struct dst_entry *dst = skb_dst(skb);
140140
struct xfrm_state *x = dst->xfrm;
141-
int mtu = ip6_skb_dst_mtu(skb);
141+
int mtu = xfrm_skb_dst_mtu(skb);
142+
143+
if (mtu < IPV6_MIN_MTU)
144+
mtu = IPV6_MIN_MTU;
142145

143146
if (skb->len > mtu && xfrm6_local_dontfrag(skb)) {
144147
xfrm6_local_rxpmtu(skb, mtu);

0 commit comments

Comments
 (0)