From patchwork Mon Aug 19 22:44:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 1149672 X-Patchwork-Delegate: jeffrey.t.kirsher@intel.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=osuosl.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=herbertland.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=herbertland-com.20150623.gappssmtp.com header.i=@herbertland-com.20150623.gappssmtp.com header.b="G+NOiwKQ"; dkim-atps=neutral Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46C8Bb3Yyxz9sN1 for ; Tue, 20 Aug 2019 08:44:54 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 9DCB587FDE; Mon, 19 Aug 2019 22:44:52 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gaORjcz28Rw5; Mon, 19 Aug 2019 22:44:51 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by hemlock.osuosl.org (Postfix) with ESMTP id 1919487FE3; Mon, 19 Aug 2019 22:44:51 +0000 (UTC) X-Original-To: Intel-wired-lan@lists.osuosl.org Delivered-To: Intel-wired-lan@lists.osuosl.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by ash.osuosl.org (Postfix) with ESMTP id C76751BF2AB for ; Mon, 19 Aug 2019 22:44:49 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id C09AA86457 for ; Mon, 19 Aug 2019 22:44:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IcIS4vsTEIrm for ; Mon, 19 Aug 2019 22:44:48 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by whitealder.osuosl.org (Postfix) with ESMTPS id 71E128642E for ; Mon, 19 Aug 2019 22:44:48 +0000 (UTC) Received: by mail-pg1-f194.google.com with SMTP id n9so2022718pgc.1 for ; Mon, 19 Aug 2019 15:44:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=herbertland-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3MC7MfjmHAobcgVJcsrKJPgmxz70rgP3fOTy0lPNUDs=; b=G+NOiwKQjGlfM0S2Nw8TGpumDnf/3C601qL4+fvTvrI0lcm9slRQiFdFLpfNCwPkdc c9yjcXRQnwnVWG8fOWQjH5D/NDmiIZEZXgFBVgYg0BwL2mjOd3osPehy9RTBqXvPgDPv OVd8SeIU9hgXOgsYPkTjOwS7v9as6OVpS++OaMsxZVGqX5N7iyBnl6kPY2gjxF6EoA3X DL+uguxJyL87PNX0lu6sbn/lCodXfNp82u1NqmMiwqzN4PhlLLiJKflGEJfoy7c1OwC3 kFYPLA+WNXerUYu4K7YjPHc9HlHd7LwSZ1fB4cqFt5dGr7IUvp0opi6cCbgnfRpR8gdw mk0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3MC7MfjmHAobcgVJcsrKJPgmxz70rgP3fOTy0lPNUDs=; b=rsTuKeQR9txLVTskO8jzy3CEYhTCCpYILwQmLv9ZEQlKc+/EA7VnZrAT2uEAa0KjYM dRugPVj5Uis/hvjSSY8Abz5MdGNlV7REquvfnZxVvlxYp1+s8hWl1jAYGKC6rc5IP9Jf HsTndkA9NugLKjypPC+d28Zk+tg8azlpeNjf7LJrxO6WIDI0LYRAz75WRw3IaALseiE1 3ZOZqdHWpHcowLeM5dIVrslRvNwDvowQ9kjr0LTbh/CQ06O/nULumr3LIjQ6ts4MijTy LL06rJyKD/E5UDcn1JTUPdbqth5TWr5M4pZGrhfAUoyllh3uS6SGlIlK4SVJH9qASE71 H0Jg== X-Gm-Message-State: APjAAAUb5BziZRICcV4nXSg8qhoah5CmfLKsbB7MhNI8x5lJa/ce3cYX 4e9qCNLUk8FAXgKgVZyvY0sd8F/Ta4I= X-Google-Smtp-Source: APXvYqzXzIvAcBiGMk2BFqy4Ulg/MJpTcvzi0c8Qx00COaGg+k7HUQyE7WgIVDmyiVATVh7Zvi1IoA== X-Received: by 2002:a17:90a:d793:: with SMTP id z19mr22721184pju.36.1566254687236; Mon, 19 Aug 2019 15:44:47 -0700 (PDT) Received: from localhost.localdomain (c-73-202-182-113.hsd1.ca.comcast.net. [73.202.182.113]) by smtp.gmail.com with ESMTPSA id x10sm14676947pjo.4.2019.08.19.15.44.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 19 Aug 2019 15:44:46 -0700 (PDT) From: Tom Herbert To: Intel-wired-lan@lists.osuosl.org Date: Mon, 19 Aug 2019 15:44:19 -0700 Message-Id: <1566254665-5200-2-git-send-email-tom@herbertland.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1566254665-5200-1-git-send-email-tom@herbertland.com> References: <1566254665-5200-1-git-send-email-tom@herbertland.com> Subject: [Intel-wired-lan] [PATCH v3 net-next 1/7] ipeh: Create exthdrs_options.c and ipeh.h X-BeenThere: intel-wired-lan@osuosl.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel Wired Ethernet Linux Kernel Driver Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Herbert , Tom Herbert MIME-Version: 1.0 Errors-To: intel-wired-lan-bounces@osuosl.org Sender: "Intel-wired-lan" From: Tom Herbert Create exthdrs_options.c to hold code related to specific Hop-by-Hop and Destination extension header options. Move related functions in exthdrs.c to the new file. Create include net/ipeh.h to contain common definitions for IP extension headers. Signed-off-by: Tom Herbert Tested-by: Andrew Bowers --- include/net/ipeh.h | 22 +++++ include/net/ipv6.h | 1 + net/ipv6/Makefile | 2 +- net/ipv6/exthdrs.c | 204 --------------------------------------------- net/ipv6/exthdrs_options.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 205 deletions(-) create mode 100644 include/net/ipeh.h create mode 100644 net/ipv6/exthdrs_options.c diff --git a/include/net/ipeh.h b/include/net/ipeh.h new file mode 100644 index 0000000..ec2d186 --- /dev/null +++ b/include/net/ipeh.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _NET_IPEH_H +#define _NET_IPEH_H + +#include + +/* + * Parsing tlv encoded headers. + * + * Parsing function "func" returns true, if parsing succeed + * and false, if it failed. + * It MUST NOT touch skb->h. + */ +struct tlvtype_proc { + int type; + bool (*func)(struct sk_buff *skb, int offset); +}; + +extern const struct tlvtype_proc tlvprocdestopt_lst[]; +extern const struct tlvtype_proc tlvprochopopt_lst[]; + +#endif /* _NET_IPEH_H */ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 8dfc656..ec10fca 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -20,6 +20,7 @@ #include #include #include +#include #define SIN6_LEN_RFC2133 24 diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 8ccf355..df3919b 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -10,7 +10,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \ - udp_offload.o seg6.o fib6_notifier.o + udp_offload.o seg6.o fib6_notifier.o exthdrs_options.o ipv6-offload := ip6_offload.o tcpv6_offload.o exthdrs_offload.o diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index ab5add0..664491e 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -39,7 +39,6 @@ #include #include #include -#include #if IS_ENABLED(CONFIG_IPV6_MIP6) #include #endif @@ -51,19 +50,6 @@ #include -/* - * Parsing tlv encoded headers. - * - * Parsing function "func" returns true, if parsing succeed - * and false, if it failed. - * It MUST NOT touch skb->h. - */ - -struct tlvtype_proc { - int type; - bool (*func)(struct sk_buff *skb, int offset); -}; - /********************* Generic functions *********************/ @@ -200,80 +186,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, return false; } -/***************************** - Destination options header. - *****************************/ - -#if IS_ENABLED(CONFIG_IPV6_MIP6) -static bool ipv6_dest_hao(struct sk_buff *skb, int optoff) -{ - struct ipv6_destopt_hao *hao; - struct inet6_skb_parm *opt = IP6CB(skb); - struct ipv6hdr *ipv6h = ipv6_hdr(skb); - int ret; - - if (opt->dsthao) { - net_dbg_ratelimited("hao duplicated\n"); - goto discard; - } - opt->dsthao = opt->dst1; - opt->dst1 = 0; - - hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff); - - if (hao->length != 16) { - net_dbg_ratelimited("hao invalid option length = %d\n", - hao->length); - goto discard; - } - - if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) { - net_dbg_ratelimited("hao is not an unicast addr: %pI6\n", - &hao->addr); - goto discard; - } - - ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr, - (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS); - if (unlikely(ret < 0)) - goto discard; - - if (skb_cloned(skb)) { - if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - goto discard; - - /* update all variable using below by copied skbuff */ - hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + - optoff); - ipv6h = ipv6_hdr(skb); - } - - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->ip_summed = CHECKSUM_NONE; - - swap(ipv6h->saddr, hao->addr); - - if (skb->tstamp == 0) - __net_timestamp(skb); - - return true; - - discard: - kfree_skb(skb); - return false; -} -#endif - -static const struct tlvtype_proc tlvprocdestopt_lst[] = { -#if IS_ENABLED(CONFIG_IPV6_MIP6) - { - .type = IPV6_TLV_HAO, - .func = ipv6_dest_hao, - }, -#endif - {-1, NULL} -}; - static int ipv6_destopt_rcv(struct sk_buff *skb) { struct inet6_dev *idev = __in6_dev_get(skb->dev); @@ -702,122 +614,6 @@ void ipv6_exthdrs_exit(void) inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING); } -/********************************** - Hop-by-hop options. - **********************************/ - -/* - * Note: we cannot rely on skb_dst(skb) before we assign it in ip6_route_input(). - */ -static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) -{ - return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev); -} - -static inline struct net *ipv6_skb_net(struct sk_buff *skb) -{ - return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev); -} - -/* Router Alert as of RFC 2711 */ - -static bool ipv6_hop_ra(struct sk_buff *skb, int optoff) -{ - const unsigned char *nh = skb_network_header(skb); - - if (nh[optoff + 1] == 2) { - IP6CB(skb)->flags |= IP6SKB_ROUTERALERT; - memcpy(&IP6CB(skb)->ra, nh + optoff + 2, sizeof(IP6CB(skb)->ra)); - return true; - } - net_dbg_ratelimited("ipv6_hop_ra: wrong RA length %d\n", - nh[optoff + 1]); - kfree_skb(skb); - return false; -} - -/* Jumbo payload */ - -static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff) -{ - const unsigned char *nh = skb_network_header(skb); - struct inet6_dev *idev = __in6_dev_get_safely(skb->dev); - struct net *net = ipv6_skb_net(skb); - u32 pkt_len; - - if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { - net_dbg_ratelimited("ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", - nh[optoff+1]); - __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); - goto drop; - } - - pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); - if (pkt_len <= IPV6_MAXPLEN) { - __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); - return false; - } - if (ipv6_hdr(skb)->payload_len) { - __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); - return false; - } - - if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { - __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTRUNCATEDPKTS); - goto drop; - } - - if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) - goto drop; - - IP6CB(skb)->flags |= IP6SKB_JUMBOGRAM; - return true; - -drop: - kfree_skb(skb); - return false; -} - -/* CALIPSO RFC 5570 */ - -static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff) -{ - const unsigned char *nh = skb_network_header(skb); - - if (nh[optoff + 1] < 8) - goto drop; - - if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1]) - goto drop; - - if (!calipso_validate(skb, nh + optoff)) - goto drop; - - return true; - -drop: - kfree_skb(skb); - return false; -} - -static const struct tlvtype_proc tlvprochopopt_lst[] = { - { - .type = IPV6_TLV_ROUTERALERT, - .func = ipv6_hop_ra, - }, - { - .type = IPV6_TLV_JUMBO, - .func = ipv6_hop_jumbo, - }, - { - .type = IPV6_TLV_CALIPSO, - .func = ipv6_hop_calipso, - }, - { -1, } -}; - int ipv6_parse_hopopts(struct sk_buff *skb) { struct inet6_skb_parm *opt = IP6CB(skb); diff --git a/net/ipv6/exthdrs_options.c b/net/ipv6/exthdrs_options.c new file mode 100644 index 0000000..032e072 --- /dev/null +++ b/net/ipv6/exthdrs_options.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if IS_ENABLED(CONFIG_IPV6_MIP6) +#include +#endif + +/* Destination options header */ + +#if IS_ENABLED(CONFIG_IPV6_MIP6) +static bool ipv6_dest_hao(struct sk_buff *skb, int optoff) +{ + struct ipv6_destopt_hao *hao; + struct inet6_skb_parm *opt = IP6CB(skb); + struct ipv6hdr *ipv6h = ipv6_hdr(skb); + int ret; + + if (opt->dsthao) { + net_dbg_ratelimited("hao duplicated\n"); + goto discard; + } + opt->dsthao = opt->dst1; + opt->dst1 = 0; + + hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff); + + if (hao->length != 16) { + net_dbg_ratelimited("hao invalid option length = %d\n", + hao->length); + goto discard; + } + + if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) { + net_dbg_ratelimited("hao is not an unicast addr: %pI6\n", + &hao->addr); + goto discard; + } + + ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr, + (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS); + if (unlikely(ret < 0)) + goto discard; + + if (skb_cloned(skb)) { + if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto discard; + + /* update all variable using below by copied skbuff */ + hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + + optoff); + ipv6h = ipv6_hdr(skb); + } + + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->ip_summed = CHECKSUM_NONE; + + swap(ipv6h->saddr, hao->addr); + + if (skb->tstamp == 0) + __net_timestamp(skb); + + return true; + + discard: + kfree_skb(skb); + return false; +} +#endif + +const struct tlvtype_proc tlvprocdestopt_lst[] = { +#if IS_ENABLED(CONFIG_IPV6_MIP6) + { + .type = IPV6_TLV_HAO, + .func = ipv6_dest_hao, + }, +#endif + {-1, NULL} +}; + +/* Hop-by-hop options */ + +/* Note: we cannot rely on skb_dst(skb) before we assign it in + * ip6_route_input(). + */ +static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) +{ + return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : + __in6_dev_get(skb->dev); +} + +static inline struct net *ipv6_skb_net(struct sk_buff *skb) +{ + return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev); +} + +/* Router Alert as of RFC 2711 */ + +static bool ipv6_hop_ra(struct sk_buff *skb, int optoff) +{ + const unsigned char *nh = skb_network_header(skb); + + if (nh[optoff + 1] == 2) { + IP6CB(skb)->flags |= IP6SKB_ROUTERALERT; + memcpy(&IP6CB(skb)->ra, nh + optoff + 2, + sizeof(IP6CB(skb)->ra)); + return true; + } + net_dbg_ratelimited("%s: wrong RA length %d\n", + __func__, nh[optoff + 1]); + kfree_skb(skb); + return false; +} + +/* Jumbo payload */ + +static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff) +{ + const unsigned char *nh = skb_network_header(skb); + struct inet6_dev *idev = __in6_dev_get_safely(skb->dev); + struct net *net = ipv6_skb_net(skb); + u32 pkt_len; + + if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { + net_dbg_ratelimited("%s: wrong jumbo opt length/alignment %d\n", + __func__, nh[optoff + 1]); + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); + goto drop; + } + + pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); + if (pkt_len <= IPV6_MAXPLEN) { + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff + 2); + return false; + } + if (ipv6_hdr(skb)->payload_len) { + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS); + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); + return false; + } + + if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { + __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTRUNCATEDPKTS); + goto drop; + } + + if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) + goto drop; + + IP6CB(skb)->flags |= IP6SKB_JUMBOGRAM; + return true; + +drop: + kfree_skb(skb); + return false; +} + +/* CALIPSO RFC 5570 */ + +static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff) +{ + const unsigned char *nh = skb_network_header(skb); + + if (nh[optoff + 1] < 8) + goto drop; + + if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1]) + goto drop; + + if (!calipso_validate(skb, nh + optoff)) + goto drop; + + return true; + +drop: + kfree_skb(skb); + return false; +} + +const struct tlvtype_proc tlvprochopopt_lst[] = { + { + .type = IPV6_TLV_ROUTERALERT, + .func = ipv6_hop_ra, + }, + { + .type = IPV6_TLV_JUMBO, + .func = ipv6_hop_jumbo, + }, + { + .type = IPV6_TLV_CALIPSO, + .func = ipv6_hop_calipso, + }, + { -1, } +};