From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=FRZod6bd; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by passt.top (Postfix) with ESMTPS id 4A5795A026E for ; Mon, 20 Apr 2026 16:45:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776696334; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=QtT0jy88jJ/6WxB5uBp0ZD5FeSgAkf5vB4VoXK83z5I=; b=FRZod6bdWISV3N8eWy0DdnzST+GptlzYIxCcAyWJGmmt5lT/UlVmqS7ndWDMeTd1jOwkRt 4If9Cyn24CIAqK5Q7QNLtrbs4R2TrJnOM5gSf832zXM4b6lEcZa6B5oxSJanosK5jd04nU HvjO7ym/Hms48oNC3m1fcfNUqWAqkyQ= Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-49-USFMY4ErOke6b-oVuK_18g-1; Mon, 20 Apr 2026 10:45:32 -0400 X-MC-Unique: USFMY4ErOke6b-oVuK_18g-1 X-Mimecast-MFC-AGG-ID: USFMY4ErOke6b-oVuK_18g_1776696332 Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-2b24a00d12cso32405415ad.1 for ; Mon, 20 Apr 2026 07:45:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776696332; x=1777301132; h=content-transfer-encoding:in-reply-to:autocrypt:from :content-language:references:to:subject:user-agent:mime-version:date :message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=QtT0jy88jJ/6WxB5uBp0ZD5FeSgAkf5vB4VoXK83z5I=; b=RV3NysCRtw0jxgQA0szXhmPFtTqayjjARDquqhTR27TBAcTB/G379B0tvLW6pgG5k6 9fPJgfzHc/tiy2qmAD7Wn7T7AspZ9aQ8QNGiDVHnNfJqFSvcG3sLW31Tc0/wmX2dh1AK 1/MLvzloGwDK8WbdDKlnn6Q7jBwPHA6zwEFQnFyPCQ/CYozw042+K5fjCSnNmEqsQOOE LrvqggZbJHH9lPDtWrumX2iKPue96uggiMmtSW4WoH9WbbfBcQkNL2ogzC+oT8bmcnlV quZkQzPCIMRB87KFEmN540EQpgvLw52J7FU9don97LT7hOY3KT0Ofqsfkh4aZ6DgYFA3 tWGg== X-Forwarded-Encrypted: i=1; AFNElJ84o/z+P2dyv3lVgOcR7UxarIWedEdG09eHblLppXy6SWfUUKUXo74X5M3/ruU2u/ByDmbKtNWVmds=@passt.top X-Gm-Message-State: AOJu0Yx1hOPP5EmDMYCi7EVC07x8PC4aFpVGf78TheZW0dluZC1sNHIY Lt3ttlH7KkBUqzYtfylnAF5U9CBmEgnViaJZBoQRPt552p5PLk3ltQfTo01zrrYTDIcMRR+21OV PyqVeLYQOS1yCqSUbH28xsYL+lhJb6Dlp1OwnUt5hmilyvKVEehq6Cg== X-Gm-Gg: AeBDiesBdvAtl+JAB8d/4Oqtl8rl+N5axOplPfmW4hWkJGBnH7HSvB3jBaxrftOqhwQ jbYon8jqnMbay735fSGfEh/Hrue2/RDv3cPzZT3GVHQBZpjUMsrQArysqoF00g8ZhPtqYjTWHji zkk1kp9JZod5pgy0ZI3Wz3pXtF7a3OMZA+dpkBA2KaTijqtbBsBy9888lcnODThDRqIDy8RfuQl m1RpfSDbouwSnuRkF/SggbWWK7ABHhfT/WRE/Os0r4+20onS6HKaHk9j/zdvGIfstqQgMSxVoPw CVDt/FnAWXS01v9D99InsP8O7X8ztyedG0HobU3cFrpZE3fKM9Lk2Sk69TuZTd0/wL1aDezLVUf R58XQthgdESkfL/4xyju/EjQUWiC5PXmW4o4HANYKP8UPRbhGZhoz4UCYqCrh9fieNw== X-Received: by 2002:a17:902:be0c:b0:2b4:5e65:5d0e with SMTP id d9443c01a7336-2b5f9ea23admr104455665ad.10.1776696331371; Mon, 20 Apr 2026 07:45:31 -0700 (PDT) X-Received: by 2002:a17:902:be0c:b0:2b4:5e65:5d0e with SMTP id d9443c01a7336-2b5f9ea23admr104455305ad.10.1776696330548; Mon, 20 Apr 2026 07:45:30 -0700 (PDT) Received: from [192.168.100.100] (82-64-211-94.subs.proxad.net. [82.64.211.94]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fab0caf1sm109857675ad.42.2026.04.20.07.45.27 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 20 Apr 2026 07:45:30 -0700 (PDT) Message-ID: Date: Mon, 20 Apr 2026 16:45:24 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v3 03/11] conf: Allow user-specified auto-scanned port forwarding ranges To: David Gibson , passt-dev@passt.top, Stefano Brivio References: <20260417050520.102247-1-david@gibson.dropbear.id.au> <20260417050520.102247-4-david@gibson.dropbear.id.au> From: Laurent Vivier Autocrypt: addr=lvivier@redhat.com; keydata= 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 In-Reply-To: <20260417050520.102247-4-david@gibson.dropbear.id.au> X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: _rDf67TJFwDaJb1FcaUMoqoPOJyqebi7y2TzLlxz2oQ_1776696332 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Message-ID-Hash: NBSLYCVUQ67C7BC4IA3VYUAMNHGOZNWI X-Message-ID-Hash: NBSLYCVUQ67C7BC4IA3VYUAMNHGOZNWI X-MailFrom: lvivier@redhat.com 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 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: On 4/17/26 07:05, David Gibson wrote: > The forwarding table now allows for arbitrary port ranges to be marked as > FWD_SCAN, meaning we don't open sockets for every port, but only those we > scan as listening on the target side. However, there's currently no way > to create such rules, except -[tTuU] auto which always scans every port > with an unspecified listening address and interface. > > Allow user-specified "auto" ranges by moving the parsing of the "auto" > keyword from conf_ports(), to conf_ports_spec() as part of the port > specified. "auto" can be combined freely with other port ranges, e.g. > -t 127.0.0.1/auto > -u %lo/5000-7000,auto > -T auto,12345 > -U auto,~1-9000 > > Note that any address and interface given only affects where the automatic > forwards listen, not what addresses we consider when scanning. That is, > if the target side is listening on *any* address, we will create a forward > on the specified address. > > Link: https://bugs.passt.top/show_bug.cgi?id=180 > > Signed-off-by: David Gibson Reviewed-by: Laurent Vivier With a minor cosmetic nit below > --- > conf.c | 85 ++++++++++++++++++++++++++++++++++++++++++--------------- > passt.1 | 30 ++++++++++++++------ > 2 files changed, 85 insertions(+), 30 deletions(-) > > diff --git a/conf.c b/conf.c > index dacea182..33b96eac 100644 > --- a/conf.c > +++ b/conf.c > @@ -13,6 +13,7 @@ > */ > > #include > +#include > #include > #include > #include > @@ -112,6 +113,28 @@ static int parse_port_range(const char *s, const char **endptr, > return 0; > } > > +/** > + * parse_keyword() - Parse a literal keyword > + * @s: String to parse > + * @endptr: Update to the character after the keyword > + * @kw: Keyword to accept > + * > + * Return: 0, if @s starts with @kw, -EINVAL if it does not > + */ > +static int parse_keyword(const char *s, const char **endptr, const char *kw) > +{ > + size_t len = strlen(kw); > + > + if (strlen(s) < len) > + return -EINVAL; > + > + if (memcmp(s, kw, len)) > + return -EINVAL; > + > + *endptr = s + len; > + return 0; > +} > + > /** > * conf_ports_range_except() - Set up forwarding for a range of ports minus a > * bitmap of exclusions > @@ -249,6 +272,7 @@ static void conf_ports_spec(const struct ctx *c, > uint8_t exclude[PORT_BITMAP_SIZE] = { 0 }; > bool exclude_only = true; > const char *p, *ep; > + uint8_t flags = 0; > unsigned i; > > if (!strcmp(spec, "all")) { > @@ -256,15 +280,32 @@ static void conf_ports_spec(const struct ctx *c, > spec = ""; > } > > - /* Mark all exclusions first, they might be given after base ranges */ > + /* Parse excluded ranges and "auto" in the first pass */ > for_each_chunk(p, ep, spec, ",") { > struct port_range xrange; > > - if (*p != '~') { > - /* Not an exclude range, parse later */ > + if (isdigit(*p)) { double space between ) and { Thanks, Laurent > + /* Include range, parse later */ > exclude_only = false; > continue; > } > + > + if (parse_keyword(p, &p, "auto") == 0) { > + if (p != ep) /* Garbage after the keyword */ > + goto bad; > + > + if (c->mode != MODE_PASTA) { > + die( > +"'auto' port forwarding is only allowed for pasta"); > + } > + > + flags |= FWD_SCAN; > + continue; > + } > + > + /* Should be an exclude range */ > + if (*p != '~') > + goto bad; > p++; > > if (parse_port_range(p, &p, &xrange)) > @@ -283,7 +324,7 @@ static void conf_ports_spec(const struct ctx *c, > conf_ports_range_except(c, optname, optarg, fwd, > proto, addr, ifname, > 1, NUM_PORTS - 1, exclude, > - 1, FWD_WEAK); > + 1, flags | FWD_WEAK); > return; > } > > @@ -291,8 +332,8 @@ static void conf_ports_spec(const struct ctx *c, > for_each_chunk(p, ep, spec, ",") { > struct port_range orig_range, mapped_range; > > - if (*p == '~') > - /* Exclude range, already parsed */ > + if (!isdigit(*p)) > + /* Already parsed */ > continue; > > if (parse_port_range(p, &p, &orig_range)) > @@ -320,7 +361,7 @@ static void conf_ports_spec(const struct ctx *c, > proto, addr, ifname, > orig_range.first, orig_range.last, > exclude, > - mapped_range.first, 0); > + mapped_range.first, flags); > } > > return; > @@ -366,17 +407,6 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, > if (proto == IPPROTO_UDP && c->no_udp) > die("UDP port forwarding requested but UDP is disabled"); > > - if (!strcmp(optarg, "auto")) { > - if (c->mode != MODE_PASTA) > - die("'auto' port forwarding is only allowed for pasta"); > - > - conf_ports_range_except(c, optname, optarg, fwd, > - proto, NULL, NULL, > - 1, NUM_PORTS - 1, NULL, 1, FWD_SCAN); > - > - return; > - } > - > strncpy(buf, optarg, sizeof(buf) - 1); > > if ((spec = strchr(buf, '/'))) { > @@ -1031,13 +1061,13 @@ static void usage(const char *name, FILE *f, int status) > " can be specified multiple times\n" > " SPEC can be:\n" > " 'none': don't forward any ports\n" > - "%s" > " [ADDR[%%IFACE]/]PORTS: forward specific ports\n" > " PORTS is either 'all' (forward all unbound, non-ephemeral\n" > " ports), or a comma-separated list of ports, optionally\n" > " ranged with '-' and optional target ports after ':'.\n" > " Ranges can be reduced by excluding ports or ranges\n" > - " prefixed by '~'\n" > + " prefixed by '~'.\n" > + "%s" > " Examples:\n" > " -t all Forward all ports\n" > " -t ::1/all Forward all ports from local address ::1\n" > @@ -1050,15 +1080,26 @@ static void usage(const char *name, FILE *f, int status) > " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1 to %s\n" > " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25\n" > " -t ~25 Forward all ports except for 25\n" > + "%s" > " default: %s\n" > " -u, --udp-ports SPEC UDP port forwarding to %s\n" > " SPEC is as described for TCP above\n" > " default: %s\n", > guest, > strstr(name, "pasta") ? > - " 'auto': forward all ports currently bound in namespace\n" > + " The 'auto' keyword may be given to only forward\n" > + " ports which are bound in the target namespace\n" > + : "", > + guest, guest, guest, > + strstr(name, "pasta") ? > + " -t auto\t Forward all ports bound in namespace\n" > + " -t ::1/auto Forward ports from ::1 if they are\n" > + " bound in the namespace\n" > + " -t 80-82,auto Forward ports 80-82 if they are bound\n" > + " in the namespace\n" > : "", > - guest, guest, guest, fwd_default, guest, fwd_default); > + > + fwd_default, guest, fwd_default); > > if (strstr(name, "pasta")) > goto pasta_opts; > diff --git a/passt.1 b/passt.1 > index 20dc72ca..6303aeb0 100644 > --- a/passt.1 > +++ b/passt.1 > @@ -434,12 +434,6 @@ Configure TCP port forwarding to guest or namespace. \fIspec\fR can be one of: > .BR none > Don't forward any ports > > -.TP > -.BR auto " " (\fBpasta\fR " " only) > -Dynamically forward ports bound in the namespace. The list of ports is > -periodically derived (every second) from listening sockets reported by > -\fI/proc/net/tcp\fR and \fI/proc/net/tcp6\fR, see \fBproc\fR(5). > - > .TP > [\fIaddress\fR[\fB%\fR\fIinterface\fR]\fB/\fR]\fIports\fR ... > Specific ports to forward. Optionally, a specific listening address > @@ -468,11 +462,20 @@ as \fIfirst\fR. > \fB~\fR\fIfirst\fR[\fB-\fR\fIlast\fR] > Exclude range. Don't forward port numbers between \fIfirst\fR and > \fIlast\fR. This takes precedences over include ranges. > + > +.TP > +.BR auto > +\fBpasta\fR only. Only forward ports in the specified set if the > +target ports are bound in the namespace. The list of ports is > +periodically derived (every second) from listening sockets reported by > +\fI/proc/net/tcp\fR and \fI/proc/net/tcp6\fR, see \fBproc\fR(5). > .RE > > Specifying excluded ranges only implies that all other non-ephemeral > -ports are forwarded. In this case, no failures are reported for > -unavailable ports, unless no ports could be forwarded at all. > +ports are forwarded. Specifying no ranges at all implies forwarding > +all non-ephemeral ports permitted by current capabilities. In this > +case, no failures are reported for unavailable ports, unless no ports > +could be forwarded at all. > > Examples: > .RS > @@ -519,6 +522,17 @@ and 30 > .TP > -t ~20000-20010 > Forward all ports to the guest, except for the range from 20000 to 20010 > +.TP > +-t auto > +Automatically forward any ports which are bound in the namespace > +.TP > +-t ::1/auto > +Automatically forward any ports which are bound in the namespace, > +listening only on local port ::1 > +.TP > +-t 8000-8010,auto > +Forward ports in the range 8000-8010 if and only if they are bound in > +the namespace > .RE > > Default is \fBnone\fR for \fBpasst\fR and \fBauto\fR for \fBpasta\fR.