From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202606 header.b=QD8os7WT; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 738A45A0652 for ; Fri, 26 Jun 2026 09:10:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202606; t=1782457808; bh=9WjhH6Ta1x2Jmdzaq/O3sAmQVSgpnLYl9BC9bRI+mzQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QD8os7WTAV9X0qZJoe0FUgMhUBwbADwO4yUoR//TTA5bZgESuPsa0a03RPkZGFnQ7 ALEHpniYLo5vpQt65QSpMfso/boHtka/ieFGWgTSekg9RN8rEInpmzQEqkGXCFuBxH Vsccs+CKCN2jKY5XSbvrmIO49283AzaSOb5mNmJfRibdFfl3DyhWvKEX3AmpXD3vYk 05eT7rIpZVkjYbv91fIXi/GL80aAiuUU5wN1b+tlIWsEJ4KUNwK3x8KBMG006lG9aN M5f+xiCbZJLMmq4q2qjQCJADxE3ucB8+dGgOqLxbETBNmYdf0j5wVN9MA9foXSlwOz APbgHK/YJL6aA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4gmmym4q82z4wj5; Fri, 26 Jun 2026 17:10:08 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 07/12] parse: Move parse_port_range() to new parsing framework Date: Fri, 26 Jun 2026 17:09:58 +1000 Message-ID: <20260626071003.3472194-8-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260626071003.3472194-1-david@gibson.dropbear.id.au> References: <20260626071003.3472194-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: CEMJNG5EEFLKXYSSJDPHYXYXR5BRYI5N X-Message-ID-Hash: CEMJNG5EEFLKXYSSJDPHYXYXR5BRYI5N X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: parse_port_range() in fwd_rule.c takes an approach similar to that used by the new parsing helpers in parse.c (and is partially inspiration for it), but isn't quite the same. Move it into parse.c, and bring it into line with that file's conventions. Signed-off-by: David Gibson --- common.h | 3 +++ fwd_rule.c | 53 +++-------------------------------------------------- fwd_rule.h | 2 -- parse.c | 28 ++++++++++++++++++++++++++++ parse.h | 13 +++++++++++++ 5 files changed, 47 insertions(+), 52 deletions(-) diff --git a/common.h b/common.h index f2518f66..16b9dc8c 100644 --- a/common.h +++ b/common.h @@ -113,4 +113,7 @@ static inline const char *strerror_(int errnum) #define ntohll(x) (be64toh((x))) #define htonll(x) (htobe64((x))) +/* Number of ports for both TCP and UDP */ +#define NUM_PORTS (1U << 16) + #endif /* COMMON_H */ diff --git a/fwd_rule.c b/fwd_rule.c index d4b422d7..0b85b17e 100644 --- a/fwd_rule.c +++ b/fwd_rule.c @@ -367,53 +367,6 @@ int fwd_rule_add(struct fwd_table *fwd, const struct fwd_rule *new) return 0; } -/** - * port_range() - Represents a non-empty range of ports - * @first: First port number in the range - * @last: Last port number in the range (inclusive) - * - * Invariant: @last >= @first - */ -struct port_range { - in_port_t first, last; -}; - -/** - * parse_port_range() - Parse a range of port numbers '[-]' - * @s: String to parse - * @endptr: Update to the character after the parsed range (similar to - * strtol() etc.) - * @range: Update with the parsed values on success - * - * Return: -EINVAL on parsing error, -ERANGE on out of range port - * numbers, 0 on success - */ -static int parse_port_range(const char *s, const char **endptr, - struct port_range *range) -{ - unsigned long first, last; - char *ep; - - last = first = strtoul(s, &ep, 10); - if (ep == s) /* Parsed nothing */ - return -EINVAL; - if (*ep == '-') { /* we have a last value too */ - const char *lasts = ep + 1; - last = strtoul(lasts, &ep, 10); - if (ep == lasts) /* Parsed nothing */ - return -EINVAL; - } - - if ((last < first) || (last >= NUM_PORTS)) - return -ERANGE; - - range->first = first; - range->last = last; - *endptr = ep; - - return 0; -} - /** * fwd_rule_range_except() - Set up forwarding for a range of ports minus a * bitmap of exclusions @@ -550,7 +503,7 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto, if (!parse_literal(&p, "~")) goto bad; - if (parse_port_range(p, &p, &xrange)) + if (!parse_port_range(&p, &xrange)) goto bad; if (p != ep) /* Garbage after the range */ goto bad; @@ -577,12 +530,12 @@ static void fwd_rule_parse_ports(struct fwd_table *fwd, bool del, uint8_t proto, /* Already parsed */ continue; - if (parse_port_range(p, &p, &orig_range)) + if (!parse_port_range(&p, &orig_range)) goto bad; if (parse_literal(&p, ":")) { /* There's a range to map to as well */ - if (parse_port_range(p, &p, &mapped_range)) + if (!parse_port_range(&p, &mapped_range)) goto bad; if ((mapped_range.last - mapped_range.first) != (orig_range.last - orig_range.first)) diff --git a/fwd_rule.h b/fwd_rule.h index ae9a3cb0..435be5bd 100644 --- a/fwd_rule.h +++ b/fwd_rule.h @@ -18,8 +18,6 @@ #include "inany.h" #include "bitmap.h" -/* Number of ports for both TCP and UDP */ -#define NUM_PORTS (1U << 16) #define PORT_BITMAP_SIZE DIV_ROUND_UP(NUM_PORTS, 8) /* Forwarding capability bits */ diff --git a/parse.c b/parse.c index 8abfd4dd..bd091fde 100644 --- a/parse.c +++ b/parse.c @@ -17,6 +17,7 @@ #include #include +#include "common.h" #include "parse.h" /** @@ -82,3 +83,30 @@ bool parse_unsigned(const char **cursor, int base, unsigned long *valp) *cursor = p; return true; } + +/** + * parse_port_range() - Parse a range of port numbers '[-]' + * @range: Update with the parsed values on success + */ +bool parse_port_range(const char **cursor, struct port_range *range) +{ + unsigned long first, last; + const char *p = *cursor; + + if (!parse_unsigned(&p, 10, &first)) + return false; + + last = first; + + if (parse_literal(&p, "-")) + if (!parse_unsigned(&p, 10, &last)) + return false; + + if ((last < first) || (last >= NUM_PORTS)) + return false; + + range->first = first; + range->last = last; + *cursor = p; + return true; +} diff --git a/parse.h b/parse.h index 4f38c28b..155b3995 100644 --- a/parse.h +++ b/parse.h @@ -7,9 +7,22 @@ #define PARSE_H #include +#include + +/** + * port_range() - Represents a non-empty range of ports + * @first: First port number in the range + * @last: Last port number in the range (inclusive) + * + * Invariant: @last >= @first + */ +struct port_range { + in_port_t first, last; +}; bool parse_literal(const char **cursor, const char *lit); bool parse_eoi(const char *cursor); bool parse_unsigned(const char **cursor, int base, unsigned long *valp); +bool parse_port_range(const char **cursor, struct port_range *range); #endif /* _PARSE_H */ -- 2.54.0