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 */
#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>
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 */
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)
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;
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);
{
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);