From patchwork Wed Nov 11 02:16:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Justin Pettit X-Patchwork-Id: 542755 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id 4A1C9141412 for ; Wed, 11 Nov 2015 13:17:11 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 6A81F22C39F; Tue, 10 Nov 2015 18:16:55 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e4.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id DB29110AC2 for ; Tue, 10 Nov 2015 18:16:53 -0800 (PST) Received: from bar5.cudamail.com (unknown [192.168.21.12]) by mx1e4.cudamail.com (Postfix) with ESMTPS id 5C2C91E004A for ; Tue, 10 Nov 2015 19:16:53 -0700 (MST) X-ASG-Debug-ID: 1447208211-09eadd0367255890001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar5.cudamail.com with ESMTP id Gp7IWbEvCGBMplj9 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 10 Nov 2015 19:16:51 -0700 (MST) X-Barracuda-Envelope-From: jpettit@ovn.org X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO relay5-d.mail.gandi.net) (217.70.183.197) by mx1-pf1.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 11 Nov 2015 02:16:51 -0000 Received-SPF: pass (mx1-pf1.cudamail.com: SPF record at ovn.org designates 217.70.183.197 as permitted sender) X-Barracuda-Apparent-Source-IP: 217.70.183.197 X-Barracuda-RBL-IP: 217.70.183.197 Received: from mfilter34-d.gandi.net (mfilter34-d.gandi.net [217.70.178.165]) by relay5-d.mail.gandi.net (Postfix) with ESMTP id C548741C07B; Wed, 11 Nov 2015 03:16:48 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mfilter34-d.gandi.net Received: from relay5-d.mail.gandi.net ([IPv6:::ffff:217.70.183.197]) by mfilter34-d.gandi.net (mfilter34-d.gandi.net [::ffff:10.0.15.180]) (amavisd-new, port 10024) with ESMTP id oJjg8NtKhhlO; Wed, 11 Nov 2015 03:16:47 +0100 (CET) X-Originating-IP: 208.91.2.4 Received: from localhost.localdomain (unknown [208.91.2.4]) (Authenticated sender: jpettit@ovn.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id AB36F41C07F; Wed, 11 Nov 2015 03:16:46 +0100 (CET) X-CudaMail-Envelope-Sender: jpettit@ovn.org From: Justin Pettit To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E1-1109110693 X-CudaMail-DTE: 111015 X-CudaMail-Originating-IP: 217.70.183.197 Date: Tue, 10 Nov 2015 18:16:20 -0800 X-ASG-Orig-Subj: [##CM-E1-1109110693##][PATCH 2/6] packets: Add ipv6_parse_masked() function. Message-Id: <1447208184-66714-2-git-send-email-jpettit@ovn.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1447208184-66714-1-git-send-email-jpettit@ovn.org> References: <1447208184-66714-1-git-send-email-jpettit@ovn.org> X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1447208211 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Cc: Justin Pettit Subject: [ovs-dev] [PATCH 2/6] packets: Add ipv6_parse_masked() function. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" From: Justin Pettit Signed-off-by: Justin Pettit Acked-by: Ben Pfaff --- lib/packets.c | 37 +++++++++++++++++++++++++++++++++++++ lib/packets.h | 2 ++ tests/test-packets.c | 23 +++++++++++++++++++++++ 3 files changed, 62 insertions(+), 0 deletions(-) diff --git a/lib/packets.c b/lib/packets.c index 866d782..f6fd480 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -570,6 +570,43 @@ ipv6_is_cidr(const struct in6_addr *netmask) return true; } +/* Parses string 's', which must be an IPv6 address with an optional + * CIDR prefix length. Stores the IP address into '*ipv6' and the CIDR + * prefix in '*prefix'. (If 's' does not contain a CIDR length, all-ones + * is assumed.) + * + * Returns NULL if successful, otherwise an error message that the caller must + * free(). */ +char * OVS_WARN_UNUSED_RESULT +ipv6_parse_masked(const char *s, struct in6_addr *ipv6, struct in6_addr *mask) +{ + char ipv6_s[IPV6_SCAN_LEN + 1]; + char mask_s[IPV6_SCAN_LEN + 1]; + int prefix; + int n; + + if (ovs_scan(s, IPV6_SCAN_FMT"/"IPV6_SCAN_FMT"%n", ipv6_s, mask_s, &n) + && inet_pton(AF_INET6, ipv6_s, ipv6) == 1 + && inet_pton(AF_INET6, mask_s, mask) == 1 + && !s[n]) { + /* OK. */ + } else if (ovs_scan(s, IPV6_SCAN_FMT"/%d%n", ipv6_s, &prefix, &n) + && inet_pton(AF_INET6, ipv6_s, ipv6) == 1 + && !s[n]) { + if (prefix <= 0 || prefix > 128) { + return xasprintf("%s: prefix bits not between 0 and 128", s); + } + *mask = ipv6_create_mask(prefix); + } else if (ovs_scan(s, IPV6_SCAN_FMT"%n", ipv6_s, &n) + && inet_pton(AF_INET6, ipv6_s, ipv6) == 1 + && !s[n]) { + *mask = in6addr_exact; + } else { + return xasprintf("%s: invalid IP address", s); + } + return NULL; +} + /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst', * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated * in 'b' and returned. This payload may be populated with appropriate diff --git a/lib/packets.h b/lib/packets.h index 6a52b32..188cf84 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -959,6 +959,8 @@ struct in6_addr ipv6_addr_bitand(const struct in6_addr *src, struct in6_addr ipv6_create_mask(int mask); int ipv6_count_cidr_bits(const struct in6_addr *netmask); bool ipv6_is_cidr(const struct in6_addr *netmask); +char *ipv6_parse_masked(const char *s, struct in6_addr *ipv6, + struct in6_addr *mask); void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst, const struct eth_addr eth_src, uint16_t eth_type, diff --git a/tests/test-packets.c b/tests/test-packets.c index 88b69c9..c4494cf 100644 --- a/tests/test-packets.c +++ b/tests/test-packets.c @@ -152,12 +152,35 @@ test_ipv6_masking(void) } static void +test_ipv6_parsing(void) +{ + struct in6_addr o_ipv6, p_ipv6; + struct in6_addr mask; + + inet_pton(AF_INET6, "2001:db8:0:0:0:0:2:1", &o_ipv6); + + ipv6_parse_masked("2001:db8:0:0:0:0:2:1/64", &p_ipv6, &mask); + assert(ipv6_addr_equals(&o_ipv6, &p_ipv6)); + assert(ipv6_count_cidr_bits(&mask) == 64); + + ipv6_parse_masked("2001:db8:0:0:0:0:2:1/ffff:ffff:ffff:ffff::", + &p_ipv6, &mask); + assert(ipv6_addr_equals(&o_ipv6, &p_ipv6)); + assert(ipv6_count_cidr_bits(&mask) == 64); + + ipv6_parse_masked("2001:db8:0:0:0:0:2:1", &p_ipv6, &mask); + assert(ipv6_addr_equals(&o_ipv6, &p_ipv6)); + assert(ipv6_count_cidr_bits(&mask) == 128); +} + +static void test_packets_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { test_ipv4_cidr(); test_ipv6_static_masks(); test_ipv6_cidr(); test_ipv6_masking(); + test_ipv6_parsing(); } OVSTEST_REGISTER("test-packets", test_packets_main);