From patchwork Sun Mar 17 23:37:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bram Yvakh X-Patchwork-Id: 1057626 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mail.wizbit.be Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44MwzN2w7Wz9s7T for ; Mon, 18 Mar 2019 10:50:08 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727576AbfCQXpT (ORCPT ); Sun, 17 Mar 2019 19:45:19 -0400 Received: from 87-237-14-1.powered-by.benesol.be ([87.237.14.1]:40849 "EHLO wizbit.localdomain" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727171AbfCQXpS (ORCPT ); Sun, 17 Mar 2019 19:45:18 -0400 Received: from mx.wizbit.be (localhost [127.0.0.1]) by wizbit.localdomain (Postfix) with ESMTP id 45EC96004; Mon, 18 Mar 2019 00:37:57 +0100 (CET) From: Bram Yvahk To: steffen.klassert@secunet.com, herbert@gondor.apana.org.au, davem@davemloft.net Cc: netdev@vger.kernel.org Subject: [PATCH ipsec/vti 1/2] vti: fragment IPv4 packets when DF bit is not set Date: Sun, 17 Mar 2019 23:37:56 +0000 Message-Id: <1552865877-13401-2-git-send-email-bram-yvahk@mail.wizbit.be> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1552865877-13401-1-git-send-email-bram-yvahk@mail.wizbit.be> References: <1552865877-13401-1-git-send-email-bram-yvahk@mail.wizbit.be> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Only send a 'need to frag' ICMP message when the "Don't Fragment" bit is set. If it's not set then the packet can/will be fragmented. This fixes sending an 'need to frag' message on a client that did not set the DF bit, i.e.: $ ping -s 1300 -M dont -c5 192.168.235.2 PING 192.168.235.3 (192.168.235.3) 1300(1328) bytes of data. From 192.168.236.254 icmp_seq=1 Frag needed and DF set (mtu = 1214) Signed-off-by: Bram Yvahk --- net/ipv4/ip_vti.c | 43 +++++++++++++++++++++++++++-------------- net/ipv6/ip6_vti.c | 56 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 68a21bf..5738e44 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -196,6 +196,34 @@ static bool vti_state_check(const struct xfrm_state *x, __be32 dst, __be32 src) return true; } +static bool vti_tunnel_check_size(struct sk_buff *skb) +{ + int mtu; + + if (skb->protocol == htons(ETH_P_IP)) { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->ignore_df) + return true; + } + + mtu = dst_mtu(skb_dst(skb)); + if (skb->len > mtu) { + skb_dst_update_pmtu(skb, mtu); + if (skb->protocol == htons(ETH_P_IP)) { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + } else { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + } + + return false; + } + + return true; +} + static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) { @@ -205,7 +233,6 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, struct net_device *tdev; /* Device to other host */ int pkt_len = skb->len; int err; - int mtu; if (!dst) { dev->stats.tx_carrier_errors++; @@ -233,19 +260,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - mtu = dst_mtu(dst); - if (skb->len > mtu) { - skb_dst_update_pmtu(skb, mtu); - if (skb->protocol == htons(ETH_P_IP)) { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); - } else { - if (mtu < IPV6_MIN_MTU) - mtu = IPV6_MIN_MTU; - - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - } - + if (!vti_tunnel_check_size(skb)) { dst_release(dst); goto tx_error; } diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 8b6eeff..47f178c 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -436,6 +436,46 @@ static bool vti6_state_check(const struct xfrm_state *x, } /** + * vti6_tunnel_check_size - check size of packet + * @skb: the outgoing socket buffer + * + * Description: + * Check if packet is too large (> pmtu) + * + * Return: + * true if size of packet is ok + * false if packet is too large + **/ +static bool vti6_tunnel_check_size(struct sk_buff *skb) +{ + int mtu; + + if (skb->protocol == htons(ETH_P_IP)) { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->ignore_df) + return true; + } + + mtu = dst_mtu(skb_dst(skb)); + if (skb->len > mtu) { + skb_dst_update_pmtu(skb, mtu); + + if (skb->protocol == htons(ETH_P_IPV6)) { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + } else { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + } + + return false; + } + + return true; +} + +/** * vti6_xmit - send a packet * @skb: the outgoing socket buffer * @dev: the outgoing tunnel device @@ -451,7 +491,6 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) struct xfrm_state *x; int pkt_len = skb->len; int err = -1; - int mtu; if (!dst) goto tx_err_link_failure; @@ -481,20 +520,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) goto tx_err_dst_release; } - mtu = dst_mtu(dst); - if (skb->len > mtu) { - skb_dst_update_pmtu(skb, mtu); - - if (skb->protocol == htons(ETH_P_IPV6)) { - if (mtu < IPV6_MIN_MTU) - mtu = IPV6_MIN_MTU; - - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - } else { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); - } - + if (!vti6_tunnel_check_size(skb)) { err = -EMSGSIZE; goto tx_err_dst_release; } From patchwork Sun Mar 17 23:37:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bram Yvakh X-Patchwork-Id: 1057624 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mail.wizbit.be Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44MwzK5Xl4z9s71 for ; Mon, 18 Mar 2019 10:50:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727562AbfCQXpS (ORCPT ); Sun, 17 Mar 2019 19:45:18 -0400 Received: from 87-237-14-1.powered-by.benesol.be ([87.237.14.1]:40852 "EHLO wizbit.localdomain" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727467AbfCQXpR (ORCPT ); Sun, 17 Mar 2019 19:45:17 -0400 Received: from mx.wizbit.be (localhost [127.0.0.1]) by wizbit.localdomain (Postfix) with ESMTP id 60DD16005; Mon, 18 Mar 2019 00:37:57 +0100 (CET) From: Bram Yvahk To: steffen.klassert@secunet.com, herbert@gondor.apana.org.au, davem@davemloft.net Cc: netdev@vger.kernel.org Subject: [PATCH ipsec/vti 2/2] vti6: process icmp msg when IPv6 is fragmented Date: Sun, 17 Mar 2019 23:37:57 +0000 Message-Id: <1552865877-13401-3-git-send-email-bram-yvahk@mail.wizbit.be> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1552865877-13401-1-git-send-email-bram-yvahk@mail.wizbit.be> References: <1552865877-13401-1-git-send-email-bram-yvahk@mail.wizbit.be> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In the error function the 'nexthdr' of the (original) IPv6 header was used to check for which protocol it was. When the (original) IPv6 packet is fragmented however then nexthdr is set to 'NEXTHDR_FRAGMENT' and this causes the code to return early and not process the ICMP error. Signed-off-by: Bram Yvahk --- net/ipv6/ip6_vti.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 47f178c..9582ffd 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -590,7 +590,7 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) } static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - u8 type, u8 code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info, int protocol) { __be32 spi; __u32 mark; @@ -601,7 +601,6 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct ip_comp_hdr *ipch; struct net *net = dev_net(skb->dev); const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; - int protocol = iph->nexthdr; t = vti6_tnl_lookup(dev_net(skb->dev), &iph->daddr, &iph->saddr); if (!t) @@ -645,6 +644,24 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return 0; } +static int vti6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return vti6_err(skb, opt, type, code, offset, info, IPPROTO_ESP); +} + +static int vti6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return vti6_err(skb, opt, type, code, offset, info, IPPROTO_AH); +} + +static int vti6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + return vti6_err(skb, opt, type, code, offset, info, IPPROTO_COMP); +} + static void vti6_link_config(struct ip6_tnl *t, bool keep_mtu) { struct net_device *dev = t->dev; @@ -1189,21 +1206,21 @@ static struct pernet_operations vti6_net_ops = { static struct xfrm6_protocol vti_esp6_protocol __read_mostly = { .handler = vti6_rcv, .cb_handler = vti6_rcv_cb, - .err_handler = vti6_err, + .err_handler = vti6_esp_err, .priority = 100, }; static struct xfrm6_protocol vti_ah6_protocol __read_mostly = { .handler = vti6_rcv, .cb_handler = vti6_rcv_cb, - .err_handler = vti6_err, + .err_handler = vti6_ah_err, .priority = 100, }; static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = { .handler = vti6_rcv, .cb_handler = vti6_rcv_cb, - .err_handler = vti6_err, + .err_handler = vti6_ipcomp_err, .priority = 100, };