diff options
| -rw-r--r-- | include/net/ip.h | 1 | ||||
| -rw-r--r-- | include/net/xfrm.h | 1 | ||||
| -rw-r--r-- | net/ipv4/ah.c | 3 | ||||
| -rw-r--r-- | net/ipv4/esp.c | 3 | ||||
| -rw-r--r-- | net/ipv4/ipcomp.c | 3 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_tunnel.c | 36 | ||||
| -rw-r--r-- | net/netsyms.c | 1 |
7 files changed, 46 insertions, 2 deletions
diff --git a/include/net/ip.h b/include/net/ip.h index da0dab10f4f0..25e95ec9b4fb 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -47,6 +47,7 @@ struct inet_skb_parm #define IPSKB_MASQUERADED 1 #define IPSKB_TRANSLATED 2 #define IPSKB_FORWARDED 4 +#define IPSKB_XFRM_TUNNEL_SIZE 8 }; struct ipcm_cookie diff --git a/include/net/xfrm.h b/include/net/xfrm.h index b3a67d100b4d..f478323f39b0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -760,6 +760,7 @@ extern int xfrm4_rcv(struct sk_buff *skb); extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); +extern int xfrm4_tunnel_check_size(struct sk_buff *skb); extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir); extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen); diff --git a/net/ipv4/ah.c b/net/ipv4/ah.c index 02f08aa24437..b8388d112bbb 100644 --- a/net/ipv4/ah.c +++ b/net/ipv4/ah.c @@ -74,6 +74,9 @@ static int ah_output(struct sk_buff *skb) spin_lock_bh(&x->lock); if ((err = xfrm_state_check_expire(x)) != 0) goto error; + if (x->props.mode) + if ((err = xfrm4_tunnel_check_size(skb)) != 0) + goto error; if ((err = xfrm_state_check_space(x, skb)) != 0) goto error; diff --git a/net/ipv4/esp.c b/net/ipv4/esp.c index db29b32b118e..e7736ecac34b 100644 --- a/net/ipv4/esp.c +++ b/net/ipv4/esp.c @@ -49,6 +49,9 @@ int esp_output(struct sk_buff *skb) spin_lock_bh(&x->lock); if ((err = xfrm_state_check_expire(x)) != 0) goto error; + if (x->props.mode) + if ((err = xfrm4_tunnel_check_size(skb)) != 0) + goto error; if ((err = xfrm_state_check_space(x, skb)) != 0) goto error; diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 9b59d2bc13f8..fd96657645ab 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -176,6 +176,9 @@ static int ipcomp_output(struct sk_buff *skb) if ((err = xfrm_state_check_expire(x)) != 0) goto error; + if (x->props.mode) + if ((err = xfrm4_tunnel_check_size(skb)) != 0) + goto error; if ((err = xfrm_state_check_space(x, skb)) != 0) goto error; diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 94823a21c09a..d6bfc1e061bd 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -9,13 +9,40 @@ #include <net/icmp.h> #include <net/inet_ecn.h> +int xfrm4_tunnel_check_size(struct sk_buff *skb) +{ + int mtu, ret = 0; + struct dst_entry *dst; + struct iphdr *iph = skb->nh.iph; + + if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE) + goto out; + + IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE; + + if (!(iph->frag_off & htons(IP_DF))) + goto out; + + dst = skb->dst; + mtu = dst_pmtu(dst) - dst->header_len - dst->trailer_len; + if (skb->len > mtu) { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + ret = -EMSGSIZE; + } +out: + return ret; +} + static int ipip_output(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; struct iphdr *iph, *top_iph; - int tos; + int tos, err; + if ((err = xfrm4_tunnel_check_size(skb)) != 0) + goto error_nolock; + iph = skb->nh.iph; spin_lock_bh(&x->lock); @@ -46,9 +73,14 @@ static int ipip_output(struct sk_buff *skb) if ((skb->dst = dst_pop(dst)) == NULL) { kfree_skb(skb); - return -EHOSTUNREACH; + err = -EHOSTUNREACH; + goto error_nolock; } return NET_XMIT_BYPASS; + +error_nolock: + kfree_skb(skb); + return err; } static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) diff --git a/net/netsyms.c b/net/netsyms.c index 881e6ca32902..7859d0f96c51 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -320,6 +320,7 @@ EXPORT_SYMBOL(xfrm_parse_spi); EXPORT_SYMBOL(xfrm4_rcv); EXPORT_SYMBOL(xfrm4_tunnel_register); EXPORT_SYMBOL(xfrm4_tunnel_deregister); +EXPORT_SYMBOL(xfrm4_tunnel_check_size); EXPORT_SYMBOL(xfrm_register_type); EXPORT_SYMBOL(xfrm_unregister_type); EXPORT_SYMBOL(xfrm_get_type); |
