On Tue, Oct 11, 2022 at 01:32:20AM +0200, Stefano Brivio wrote: > Since kernel version 5.7, commit c427bfec18f2 ("net: core: enable > SO_BINDTODEVICE for non-root users"), we can bind sockets to > interfaces, if they haven't been bound yet (as in bind()). > > Introduce an optional interface specification for forwarded ports, > prefixed by %, that can be passed together with an address. > > Reported use case: running local services that use ports we want > to have externally forwarded: > https://github.com/containers/podman/issues/14425 > > Signed-off-by: Stefano Brivio > --- > v3: > - escape % characters in usage() formatting > v2: > - fix check on interface name length (spec - ifname, not > ifname - buf) > > conf.c | 31 +++++++++++++++++++++---------- > icmp.c | 4 ++-- > passt.1 | 12 ++++++++++-- > tcp.c | 27 +++++++++++++++------------ > tcp.h | 2 +- > udp.c | 35 ++++++++++++++++++----------------- > udp.h | 2 +- > util.c | 19 ++++++++++++++++++- > util.h | 3 ++- > 9 files changed, 88 insertions(+), 47 deletions(-) > > diff --git a/conf.c b/conf.c > index 779371f..93ca0cd 100644 > --- a/conf.c > +++ b/conf.c > @@ -180,8 +180,8 @@ static int conf_ports(const struct ctx *c, char optname, const char *optarg, > struct port_fwd *fwd) > { > char addr_buf[sizeof(struct in6_addr)] = { 0 }, *addr = addr_buf; > + char buf[BUFSIZ], *spec, *ifname = NULL, *p; > uint8_t exclude[PORT_BITMAP_SIZE] = { 0 }; > - char buf[BUFSIZ], *spec, *p; > sa_family_t af = AF_UNSPEC; > bool exclude_only = true; > > @@ -209,9 +209,9 @@ static int conf_ports(const struct ctx *c, char optname, const char *optarg, > > for (i = 0; i < PORT_EPHEMERAL_MIN; i++) { > if (optname == 't') > - tcp_sock_init(c, 0, AF_UNSPEC, NULL, i); > + tcp_sock_init(c, 0, AF_UNSPEC, NULL, NULL, i); > else if (optname == 'u') > - udp_sock_init(c, 0, AF_UNSPEC, NULL, i); > + udp_sock_init(c, 0, AF_UNSPEC, NULL, NULL, i); > } > > return 0; > @@ -231,6 +231,14 @@ static int conf_ports(const struct ctx *c, char optname, const char *optarg, > if (optname != 't' && optname != 'u') > goto bad; > > + if ((ifname = strchr(buf, '%'))) { > + if (spec - ifname >= IFNAMSIZ - 1) > + goto bad; > + > + *ifname = 0; > + ifname++; > + } > + > if (inet_pton(AF_INET, buf, addr)) > af = AF_INET; > else if (inet_pton(AF_INET6, buf, addr)) > @@ -278,9 +286,9 @@ static int conf_ports(const struct ctx *c, char optname, const char *optarg, > bitmap_set(fwd->map, i); > > if (optname == 't') > - tcp_sock_init(c, 0, af, addr, i); > + tcp_sock_init(c, 0, af, addr, NULL, i); > else if (optname == 'u') > - udp_sock_init(c, 0, af, addr, i); > + udp_sock_init(c, 0, af, addr, NULL, i); AFAICT nothing prevents specifying an interface with the exclude only case, in which case shouldn't you also be passing ifname here? Apart from that, LGTM. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson