<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt/fwd_rule.c, branch bug209</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>fwd, fwd_rule: Implement configurable target address mapping</title>
<updated>2026-07-08T18:59:11+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2026-07-07T04:24:52+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=e67acdebc2b725a9b4f80eaec17ff0d9771229fc'/>
<id>e67acdebc2b725a9b4f80eaec17ff0d9771229fc</id>
<content type='text'>
Add a 'taddr' field to forwarding rules, which controls the destination
address on the target side.  Since changing the structure alters the pesto
update protocol, bump the protocol version number

[dwg: Split from option parsing code, added protocol version bump,
 explicitly exclude splicing with target address for now]
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Add a 'taddr' field to forwarding rules, which controls the destination
address on the target side.  Since changing the structure alters the pesto
update protocol, bump the protocol version number

[dwg: Split from option parsing code, added protocol version bump,
 explicitly exclude splicing with target address for now]
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd_rule: Parse target addresses for forwarding rules</title>
<updated>2026-07-08T18:58:59+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-07T04:24:51+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=c8145c3bb2cca31599eeb483e7c8e5d428c72b4b'/>
<id>c8145c3bb2cca31599eeb483e7c8e5d428c72b4b</id>
<content type='text'>
Extend the parsing of forwarding rules (-[tu]) to allow the destination
address on the target side to be specified.  For now just parse them, and
give an error if we try to create rules with a specified target address.
We'll implement the actual forwarding logic in another patch.

Format (for either command line or pesto):
      -t 2222:192.0.2.1/2222

This should work along with all the other bits, that is, say:
      -t 192.0.2.1%eth0/2222-2225:192.0.2.2/22-25

FIXME: Ban for -[TU] for now
FIXME: Check interaction with splice handling

[dwg: Syntax from Stefano's earlier draft, largely rewritten on top of new
 parsing helpers]
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Extend the parsing of forwarding rules (-[tu]) to allow the destination
address on the target side to be specified.  For now just parse them, and
give an error if we try to create rules with a specified target address.
We'll implement the actual forwarding logic in another patch.

Format (for either command line or pesto):
      -t 2222:192.0.2.1/2222

This should work along with all the other bits, that is, say:
      -t 192.0.2.1%eth0/2222-2225:192.0.2.2/22-25

FIXME: Ban for -[TU] for now
FIXME: Check interaction with splice handling

[dwg: Syntax from Stefano's earlier draft, largely rewritten on top of new
 parsing helpers]
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd_rule: Rewrite forward rule parsing using parse.c helpers</title>
<updated>2026-07-04T11:14:32+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-03T03:54:45+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=bf2103815db917e532cad0b9b3530604de463d5a'/>
<id>bf2103815db917e532cad0b9b3530604de463d5a</id>
<content type='text'>
Forwarding rules for the -[tTuU] options are parsed in fwd_rule_parse()
and fwd_rule_parse_ports().  Currently those use a mix of loosely
recursive descent parsing helpers, consuming input from left to right,
and ad-hoc C parsing - searching for delimiters with strchr() or the like
and breaking down on that basis.

As well as being a slightly awkward mix, the current approach will not work
for adding target addresses to the rules: we can't easily split the
listening from target parts first, because the ':' delimiter could appear
multiple times for multiple port ranges, or in IPv6 addresses.  However,
without splitting the target part first, we can't first split off the
listening address and interface because the '/' delimiter could appear in
the target portion, but not the listening portion, e.g.:
    -t 12345:192.0.1.1/12345

To address this, rewrite the entirety of the parsing so we consume the
input left to right in a more-or-less recursive descent manner.  This means
we no longer rely on certain delimiters having a single meaning over the
whole input, just the next part of it.

Because of the semantics of port specs, we need to make several passes
over the list of comma separated chunks.  Previously, some of the logic was
duplicated between the two passes, making it fragile.  Now, we introduce
a parse_port_chunk() helper which we re-use in each pass to make it clearer
we parse exactly the same way on each pass.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Forwarding rules for the -[tTuU] options are parsed in fwd_rule_parse()
and fwd_rule_parse_ports().  Currently those use a mix of loosely
recursive descent parsing helpers, consuming input from left to right,
and ad-hoc C parsing - searching for delimiters with strchr() or the like
and breaking down on that basis.

As well as being a slightly awkward mix, the current approach will not work
for adding target addresses to the rules: we can't easily split the
listening from target parts first, because the ':' delimiter could appear
multiple times for multiple port ranges, or in IPv6 addresses.  However,
without splitting the target part first, we can't first split off the
listening address and interface because the '/' delimiter could appear in
the target portion, but not the listening portion, e.g.:
    -t 12345:192.0.1.1/12345

To address this, rewrite the entirety of the parsing so we consume the
input left to right in a more-or-less recursive descent manner.  This means
we no longer rely on certain delimiters having a single meaning over the
whole input, just the next part of it.

Because of the semantics of port specs, we need to make several passes
over the list of comma separated chunks.  Previously, some of the logic was
duplicated between the two passes, making it fragile.  Now, we introduce
a parse_port_chunk() helper which we re-use in each pass to make it clearer
we parse exactly the same way on each pass.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd_rule: Allow "all" port specs to be combined with other options</title>
<updated>2026-07-04T11:14:30+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-03T03:54:44+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=0581b0ab0f58d5c2fa4cb06ab614055749c4404b'/>
<id>0581b0ab0f58d5c2fa4cb06ab614055749c4404b</id>
<content type='text'>
Currently we handle -t all and the like as a special case, it can't be
combined with other port specifier options.  Remove that restriction,
allowing combined options like:
     -t all,~9999          # Forward everything non-ephemeral except 9999
     -t all,auto           # Equivalent to -t auto
     -t all,33000          # Forward non-ephemeral plus port 33,000

This isn't particularly useful immediately, but will become important for
destination address specification - it provides a place to attach the
target address for "all" or exclude only mappings.  It will also work
better with some parsing reworks we want to make.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently we handle -t all and the like as a special case, it can't be
combined with other port specifier options.  Remove that restriction,
allowing combined options like:
     -t all,~9999          # Forward everything non-ephemeral except 9999
     -t all,auto           # Equivalent to -t auto
     -t all,33000          # Forward non-ephemeral plus port 33,000

This isn't particularly useful immediately, but will become important for
destination address specification - it provides a place to attach the
target address for "all" or exclude only mappings.  It will also work
better with some parsing reworks we want to make.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>parse: Add helpers for parsing IP addresses</title>
<updated>2026-07-04T11:14:09+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-03T03:54:40+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=11f4fba6a9a90efccf16d6438065d22c5878734a'/>
<id>11f4fba6a9a90efccf16d6438065d22c5878734a</id>
<content type='text'>
parse_ipv[46]() are wrappers around inet_pton() that are more
convenient for use when the IP is part of a longer string, rather than
the entire string.  parse_inany() replaces inany_pton() which again
will become more convenient for strings including IPs that aren't just
an IP.

For now we only have some simple and sometimes awkward use cases,
we'll replace these with more natural uses in future.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
parse_ipv[46]() are wrappers around inet_pton() that are more
convenient for use when the IP is part of a longer string, rather than
the entire string.  parse_inany() replaces inany_pton() which again
will become more convenient for strings including IPs that aren't just
an IP.

For now we only have some simple and sometimes awkward use cases,
we'll replace these with more natural uses in future.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>parse: Move parse_port_range() to new parsing framework</title>
<updated>2026-07-04T11:14:07+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-03T03:54:39+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=42069134e9ff3cbcb35dccf92a0a044a4b71999b'/>
<id>42069134e9ff3cbcb35dccf92a0a044a4b71999b</id>
<content type='text'>
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 &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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 &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>parse: Add helper to parse unsigned integer values</title>
<updated>2026-07-04T11:14:04+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-03T03:54:38+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=8ffff9b9fca92afb785a37ddde1397805122befc'/>
<id>8ffff9b9fca92afb785a37ddde1397805122befc</id>
<content type='text'>
Most places we need to parse an integer encoded as a string, we use
strtol() or strtoul().  These already work a bit like descent parser
helpers, in that they consume as much as they can, but don't require the
number parsed to be the whole of the einput string.  Make a wrapper to
parse unsigned integers as part of our parsing helper.  This wrapper
handles the mildly fiddly error checking requirements for strtoul().

We replace a number, though not all, of our existing strtoul() uses with
the new parse_unsigned().  We also replace a number of strtol() use cases,
because, despite using that instead of strtoul() they are only used for
non-negative values.  In some cases this makes the logic a little more
straightforward.  In some other cases it will catch some error cases we
previously could have missed.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Most places we need to parse an integer encoded as a string, we use
strtol() or strtoul().  These already work a bit like descent parser
helpers, in that they consume as much as they can, but don't require the
number parsed to be the whole of the einput string.  Make a wrapper to
parse unsigned integers as part of our parsing helper.  This wrapper
handles the mildly fiddly error checking requirements for strtoul().

We replace a number, though not all, of our existing strtoul() uses with
the new parse_unsigned().  We also replace a number of strtol() use cases,
because, despite using that instead of strtoul() they are only used for
non-negative values.  In some cases this makes the logic a little more
straightforward.  In some other cases it will catch some error cases we
previously could have missed.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>parse: Start splitting out parsing helpers</title>
<updated>2026-07-04T11:13:56+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-07-03T03:54:35+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=d29eb296a3004d435914d8be05d3bdb9e44bc755'/>
<id>d29eb296a3004d435914d8be05d3bdb9e44bc755</id>
<content type='text'>
As we add more complexity to what forwarding rules are allowed, our
existing ad-hoc C parsing is starting to become quite awkward.  We already
have some parts that resemble a very simple recursive[0] descent parser,
with composable subfunctions that consume as much input as they need,
rather than pre-splitting based on known delimiters.

Start extending this approach, by creating parse.[ch] with parsing helpers
with a uniform interface.  Initially we start with very simple cases: the
parse_keyword() function from fwd_rule.c and another helper to check that
we've reached the end of input.

Rename parse_keyword() to parse_literal(), because it's not just useful
for "keywords" as such.  We can use it in a bunch of additional places for
parsing delimiters and other symbols.  This doesn't gain us a lot now but
will make things clearer as we use more such parser helpers.

[0] Except that the grammars we have aren't actually recursive, so neither
    is the code.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
As we add more complexity to what forwarding rules are allowed, our
existing ad-hoc C parsing is starting to become quite awkward.  We already
have some parts that resemble a very simple recursive[0] descent parser,
with composable subfunctions that consume as much input as they need,
rather than pre-splitting based on known delimiters.

Start extending this approach, by creating parse.[ch] with parsing helpers
with a uniform interface.  Initially we start with very simple cases: the
parse_keyword() function from fwd_rule.c and another helper to check that
we've reached the end of input.

Rename parse_keyword() to parse_literal(), because it's not just useful
for "keywords" as such.  We can use it in a bunch of additional places for
parsing delimiters and other symbols.  This doesn't gain us a lot now but
will make things clearer as we use more such parser helpers.

[0] Except that the grammars we have aren't actually recursive, so neither
    is the code.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd_rule: Allow parsing * as a forwarding address</title>
<updated>2026-05-16T15:05:56+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-15T08:24:34+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=296d7e32ec93f7534fcbf94b922a19eaea6e217c'/>
<id>296d7e32ec93f7534fcbf94b922a19eaea6e217c</id>
<content type='text'>
In our output in various places, we use "*", or sometimes "[*]" to indicate
a dual stack unspecified address: that is a case where we listen on both
0.0.0.0 and ::.  However we don't currently allow the same syntax when
specifying forwarding rules on the command line.

A * address can be indirectly specified by omitting the address entirely,
but for consistency allow an explicit "*" or "[*]" as well.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In our output in various places, we use "*", or sometimes "[*]" to indicate
a dual stack unspecified address: that is a case where we listen on both
0.0.0.0 and ::.  However we don't currently allow the same syntax when
specifying forwarding rules on the command line.

A * address can be indirectly specified by omitting the address entirely,
but for consistency allow an explicit "*" or "[*]" as well.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fwd_rule: Don't attempt dual stack listen()s if only one IP family</title>
<updated>2026-05-16T15:05:56+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-15T08:24:33+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=666ef9e20c5c0ef2a5a61a7a7b68b9e2421e14e9'/>
<id>666ef9e20c5c0ef2a5a61a7a7b68b9e2421e14e9</id>
<content type='text'>
With the recent rework to forwarding configuration, we're stricter about
what forwarding rules we allow.  In particular we don't allow dual stack
forwards (listening on both IPv4 and IPv6 addresses) if we only have one
IP family enabled.

This makes what I think was a pre-existing minor bug into a nasty failure.
If we use default forwards with no address specified, e.g.:
    $ pasta -t 1234 -4
    $ pasta -U 4321 -6
these are interpreted as dual-stack forwards.  Previously these would be
applied, leading to a surprising dual stack socket.  Since 0aeda87ca185,
they instead result in an immediate fatal error.

Add logic to interpret a default "any" address as only one IP family if
only one IP family is enabled.

Link: https://bugs.passt.top/show_bug.cgi?id=205
Reported-by: &lt;j.d03@cpc.cx&gt;
Fixes: 0aeda87ca185 ("conf, fwd: Stricter rule checking in fwd_rule_add()")
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
With the recent rework to forwarding configuration, we're stricter about
what forwarding rules we allow.  In particular we don't allow dual stack
forwards (listening on both IPv4 and IPv6 addresses) if we only have one
IP family enabled.

This makes what I think was a pre-existing minor bug into a nasty failure.
If we use default forwards with no address specified, e.g.:
    $ pasta -t 1234 -4
    $ pasta -U 4321 -6
these are interpreted as dual-stack forwards.  Previously these would be
applied, leading to a surprising dual stack socket.  Since 0aeda87ca185,
they instead result in an immediate fatal error.

Add logic to interpret a default "any" address as only one IP family if
only one IP family is enabled.

Link: https://bugs.passt.top/show_bug.cgi?id=205
Reported-by: &lt;j.d03@cpc.cx&gt;
Fixes: 0aeda87ca185 ("conf, fwd: Stricter rule checking in fwd_rule_add()")
Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
