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=nMtheDKE; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 422515A0623 for ; Tue, 07 Apr 2026 05:16:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1775531792; bh=hGpgC5udaLZ5eM1Yq4vGoY57KWCFTeMuPDgYjlXt+yM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nMtheDKE7IhIkxpyzOwQBlejxnUFKK6C1GkeMZwPhJTydI8m4/3GD1PSX0SVUMrJO 5iASOf56/1JYnBowcPKq0SITbXLkFi8SU8O110F5tZs2+Kl0xetvmppMHTFRtI7ds4 4tD24mmcrKc6SjAJ1vsE3mIEWOuJlIeBT3eUZi3wzjSnZvWXjWG+Wcz9Khj01DADOE +Hl9oiuR1HhyvJLmxJPqFVdJ6v0PJByo9iqA++7VxAre6qcNkjbg3ffpS4Q54wOAL2 RuaWyV/H1gGookuuOWoP0LI77t/2G6JMJwE9FcAKxk0Mgu4Ue+EPy/u9m1k1U/571e v4WqYpK/x6U3g== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fqWZ86Brjz4wLH; Tue, 07 Apr 2026 13:16:32 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 13/18] conf: Rework stepping through chunks of port specifiers Date: Tue, 7 Apr 2026 13:16:25 +1000 Message-ID: <20260407031630.2457081-14-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260407031630.2457081-1-david@gibson.dropbear.id.au> References: <20260407031630.2457081-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: POZJH5JGN3JUPXRK2ZRBFIMEG4EJKZVC X-Message-ID-Hash: POZJH5JGN3JUPXRK2ZRBFIMEG4EJKZVC 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 1e456361..1ab1b071 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