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=202602 header.b=bShbZjAA; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id D87695A06E2 for ; Fri, 10 Apr 2026 03:03:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1775782993; bh=R+auiy2gLN46c2NmY0CmO+HjVUqj2jKx+9fiiHkLL94=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bShbZjAA2Xj3morHsg0S2eBgJpI1P/flI0dF70hmxJ2bHHtetqVXLkeyjy8mK7pVb T2p6/R3UNFxgwwOXpSh2KJOquY1icZQBgF3D57qjk+SWiSdovPeMCAXIZeE0k8ZGCz +4myA16Fl/pbWcPWA9HH0/IVX8ANmspg6WtwIn6WuXRYMHv80XYYWmNYWc97Gnk4PM P1U6iveJMmj/Mq2BV1U596H/U07bpxDfMnaKK6pDXWLiB4Lm1j4R0wsyGB+NoZ1E7W od0mzoXWPrx83QB7XIa8ulteGsR0ocG07Z1M5AuwXKdFaLKyi7teh2VRT4gmxcwjUh jw4BTohpADivg== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fsJSx0fGNz4wTy; Fri, 10 Apr 2026 11:03:13 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH v2 13/23] conf: Rework stepping through chunks of port specifiers Date: Fri, 10 Apr 2026 11:02:59 +1000 Message-ID: <20260410010309.736855-14-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260410010309.736855-1-david@gibson.dropbear.id.au> References: <20260410010309.736855-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: KVNF3KGF7NBL4SK65X3WGNVBI5GW74YA X-Message-ID-Hash: KVNF3KGF7NBL4SK65X3WGNVBI5GW74YA 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: Port specifier strings are made up of ',' separated chunks. Rework the logic we use to step through the chunks. Specifically, maintain a pointer to the end of each chunk as well as the start. This is not really used yet, but will be useful in future. This also has side effect on semantics. Previously an empty specifier (0 chunks) was not accepted. Now it is, and will be treated as an "exclude only" spec which excludes only ephemeral ports. This seems a bit odd, and I don't expect it to be (directly) used in practice. However, it falls naturally out of the existing semantics, and will combine well with some upcoming changes. Signed-off-by: David Gibson --- conf.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/conf.c b/conf.c index 67d88ee2..0bc74e95 100644 --- a/conf.c +++ b/conf.c @@ -65,21 +65,6 @@ const char *pasta_default_ifn = "tap0"; -/** - * next_chunk() - Return the next piece of a string delimited by a character - * @s: String to search - * @c: Delimiter character - * - * Return: if another @c is found in @s, returns a pointer to the - * character *after* the delimiter, if no further @c is in @s, - * return NULL - */ -static const char *next_chunk(const char *s, char c) -{ - char *sep = strchr(s, c); - return sep ? sep + 1 : NULL; -} - /** * port_range() - Represents a non-empty range of ports * @first: First port number in the range @@ -232,6 +217,18 @@ fail: fwd_rule_fmt(&rule, rulestr, sizeof(rulestr))); } +/* + * for_each_chunk - Step through delimited chunks of a string + * @p_: Pointer to start of each chunk (updated) + * @ep_: Pointer to end of each chunk (updated) + * @s_: String to step through + * @sep_: String of all allowed delimiters + */ +#define for_each_chunk(p_, ep_, s_, sep_) \ + for ((p_) = (s_); \ + (ep_) = (p_) + strcspn((p_), (sep_)), *(p_); \ + (p_) = *(ep_) ? (ep_) + 1 : (ep_)) + /** * conf_ports_spec() - Parse port range(s) specifier * @c: Execution context @@ -251,12 +248,11 @@ static void conf_ports_spec(const struct ctx *c, { uint8_t exclude[PORT_BITMAP_SIZE] = { 0 }; bool exclude_only = true; - const char *p; + const char *p, *ep; unsigned i; /* Mark all exclusions first, they might be given after base ranges */ - p = spec; - do { + for_each_chunk(p, ep, spec, ",") { struct port_range xrange; if (*p != '~') { @@ -273,7 +269,7 @@ static void conf_ports_spec(const struct ctx *c, for (i = xrange.first; i <= xrange.last; i++) bitmap_set(exclude, i); - } while ((p = next_chunk(p, ','))); + } if (exclude_only) { /* Exclude ephemeral ports */ @@ -287,8 +283,7 @@ static void conf_ports_spec(const struct ctx *c, } /* Now process base ranges, skipping exclusions */ - p = spec; - do { + for_each_chunk(p, ep, spec, ",") { struct port_range orig_range, mapped_range; if (*p == '~') @@ -321,7 +316,7 @@ static void conf_ports_spec(const struct ctx *c, orig_range.first, orig_range.last, exclude, mapped_range.first, 0); - } while ((p = next_chunk(p, ','))); + } return; bad: -- 2.53.0