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=OAGD7nq2; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by passt.top (Postfix) with ESMTPS id C63125A0624 for ; Wed, 21 Jan 2026 20:42:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769024540; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lYhSaqPblMSCmiAAycet1isSscBfbZhUm1i8Hyqw2yU=; b=OAGD7nq2oSO9fl2vYbS0zetpbdzmDTmFuMqzaJUHke0hIEIh34Tb93/zOeqxjjMyhE5wcy NcTIgQYaP5fUtB06JjOJW/QgfIdxG0eJAHtz9s+a5dpiHkXATOIN6ltO/9Qs++h0eDi2RS YDAImVFd9lCsugKSrwTpNUFRq8LD+uE= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-100-00_G-5baPx2-jyd76YjV9A-1; Wed, 21 Jan 2026 14:42:14 -0500 X-MC-Unique: 00_G-5baPx2-jyd76YjV9A-1 X-Mimecast-MFC-AGG-ID: 00_G-5baPx2-jyd76YjV9A_1769024533 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-477cf2230c8so2002885e9.0 for ; Wed, 21 Jan 2026 11:42:13 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769024533; x=1769629333; h=content-transfer-encoding:mime-version:organization:references :in-reply-to:message-id:subject:cc:to:from:date:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lYhSaqPblMSCmiAAycet1isSscBfbZhUm1i8Hyqw2yU=; b=KTNAbWAgqjNHrAjdD5E/2AqFEz4YV8u4yv76KPh6Mz1CWBziVguoLreOY0SCUwZgYp NNIecRm5lXT1aTHyWuPph4+S4oXWXuOmZJyfw3aLauv5ENYKxeH7o9plGKsrJXt2MY6r hKz/sdtdpcn/z41dPe5CD+ZUQogIrOqm+QdFIju6CdA7neXn+EXfSVVLDcdAkTX+Rtbl +pov086PXhF6sB3JqFSVwTPocRt97CO5wyXlrnZD0NmLiU+So9DY4iKVsq8cVeQ93cd4 3CE47TXrI4XPtaHkN6grb9pAYCv6ZkswolnSqXvOd0sUmulD2feHLxIj1CfmaaPvKcW5 ZNdw== X-Forwarded-Encrypted: i=1; AJvYcCUzUDyKlCrxxT2852PCyuVu7fwwGlv0l7WIBP4uHySjEXb5UNCjZOjVHGeMlpqA7lOlVqMJp+NwRkA=@passt.top X-Gm-Message-State: AOJu0YwmRvcrn5y1hCHleui7zdHQ9U3w7VVQuLD6Ls+5pfQod1Y1dB0i M0h3KlGFLjngW9Kf5KX8fpAQGeNG3xQ+Kso8bzMap+5+MmyVjVRxI8X8SJEfdGYbTTms6jLlqKG 7KUTaNZxNgFz8bP5XRRLf8tDwJzBhhYcXSFj0dZ6dGl73ZO6u9SbXlw== X-Gm-Gg: AZuq6aK6UzJUOu9K5WrcBVYRBI+Fu28pL0QtbFmmGvN4woDNL3IRvpwpSwEXpBl3F/q xbvu4DPyo72BCp0bHslV4OjaqpBpmfwyBy4Csn/1ZTZKhed0SagwdZyYalT3o1V5Nk4xs7RGhRL lECPrwR6REJBSzSjifS7mCFrHWZKgGzN+NYa9WU6NgIeC+WdoVcjqq+RAZP+xpno1VcTYHeDWOT 2gO1pz3liVCLnhrrBcCysK3Pp3+qfy7RJExrF2pxhdmZEEeUw3FGbGjFN74LzibWI2HQRYus7Xg r69Z/sIGxb2yxgRA+EClzc6RsYRmhrbM7i23e+boDxNrUu0zKgEONjDPfCmiQ3K8qH+xMFSo/sq pi6W5rdS9d4lT3i/DUCawUS452gwqbY66UblN6g== X-Received: by 2002:a05:6000:2f8a:b0:435:9bf5:b32c with SMTP id ffacd0b85a97d-4359bf5b507mr6127645f8f.29.1769024532692; Wed, 21 Jan 2026 11:42:12 -0800 (PST) X-Received: by 2002:a05:6000:2f8a:b0:435:9bf5:b32c with SMTP id ffacd0b85a97d-4359bf5b507mr6127611f8f.29.1769024532203; Wed, 21 Jan 2026 11:42:12 -0800 (PST) Received: from maya.myfinge.rs (ifcgrfdd.trafficplex.cloud. [176.103.220.4]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-4356992211dsm39371992f8f.7.2026.01.21.11.42.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jan 2026 11:42:11 -0800 (PST) Date: Wed, 21 Jan 2026 20:42:10 +0100 From: Stefano Brivio To: Jon Maloy Subject: Re: [PATCH v2 6/9] conf: Allow multiple -a/--address options per address family Message-ID: <20260121204210.78097bfb@elisabeth> In-Reply-To: <20260118221612.2115386-7-jmaloy@redhat.com> References: <20260118221612.2115386-1-jmaloy@redhat.com> <20260118221612.2115386-7-jmaloy@redhat.com> Organization: Red Hat X-Mailer: Claws Mail 4.2.0 (GTK 3.24.49; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 0uv7HfzM_tI-dj22tC7m0okXPR68ayJGRTpQX_jMoAo_1769024533 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Message-ID-Hash: P26UPULFI64M66F6PDI34XKKJF2SDTMF X-Message-ID-Hash: P26UPULFI64M66F6PDI34XKKJF2SDTMF X-MailFrom: sbrivio@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 CC: dgibson@redhat.com, david@gibson.dropbear.id.au, passt-dev@passt.top 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 Sun, 18 Jan 2026 17:16:09 -0500 Jon Maloy wrote: > We enable configuration of multiple IPv4 and IPv6 addresses by allowing > repeated use of the -a/--address option. > > - We update option parsing to append addresses to the addrs[] array. > - Each address specified via -a does initially get a class-based default > prefix. That doesn't seem to be the case...? > - If no -a option is given, address and prefix are inherited from > the template interface. ...but this doesn't change here? > - If a prefix length is to be added, it has to be done in CIDR format, > except for the very first address. > - We configure all indicated addresses in the namespace interface. > Link: https://bugs.passt.top/show_bug.cgi?id=47 > Signed-off-by: Jon Maloy > > --- > v2: Adapted to previous code changes > --- > conf.c | 42 +++++++++++++++++++++++++++++------------- > pasta.c | 24 ++++++++++++++++++------ > 2 files changed, 47 insertions(+), 19 deletions(-) > > diff --git a/conf.c b/conf.c > index 3ecd1a0..32a754d 100644 > --- a/conf.c > +++ b/conf.c > @@ -789,7 +789,7 @@ static unsigned int conf_ip4(unsigned int ifi, struct ip4_ctx *ip4) > > ip4->our_tap_addr = ip4->guest_gw; > > - if (inany_is_unspecified(&ip4->addrs[0].addr)) > + if (!ip4->addr_count) > return 0; > > return ifi; > @@ -858,8 +858,7 @@ static unsigned int conf_ip6(unsigned int ifi, struct ip6_ctx *ip6) > if (IN6_IS_ADDR_LINKLOCAL(&ip6->guest_gw)) > ip6->our_tap_ll = ip6->guest_gw; > > - if (IN6_IS_ADDR_UNSPECIFIED(&ip6->addrs[0].addr.a6) || > - IN6_IS_ADDR_UNSPECIFIED(&ip6->our_tap_ll)) > + if (!ip6->addr_count || IN6_IS_ADDR_UNSPECIFIED(&ip6->our_tap_ll)) > return 0; > > return ifi; > @@ -951,9 +950,11 @@ static void usage(const char *name, FILE *f, int status) > " default: 65520: maximum 802.3 MTU minus 802.3 header\n" > " length, rounded to 32 bits (IPv4 words)\n" > " -a, --address ADDR Assign IPv4 or IPv6 address ADDR[/PREFIXLEN]\n" > - " can be specified zero to two times (for IPv4 and IPv6)\n" > + " can be specified multiple times (limit: %d IPv4, %d IPv6)\n" > " default: use addresses from interface with default route\n" > - " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n" > + " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n", > + IP4_MAX_ADDRS, IP6_MAX_ADDRS); > + FPRINTF(f, > " default: netmask from matching address on the host\n" > " -M, --mac-addr ADDR Use source MAC address ADDR\n" > " default: 9a:55:9a:55:9a:55 (locally administered)\n" > @@ -1882,6 +1883,7 @@ void conf(struct ctx *c, int argc, char **argv) > union inany_addr addr; > const struct in_addr *a4; > int prefix_len = 0; > + unsigned int i; > int af; > > af = conf_addr_prefix_len(optarg, &addr, &prefix_len); > @@ -1893,9 +1895,15 @@ void conf(struct ctx *c, int argc, char **argv) > die("Invalid address: %s", optarg); > > if (af == AF_INET6) { > - c->ip6.addrs[0].addr.a6 = addr.a6; > - c->ip6.addrs[0].flags |= INANY_ADDR_CONFIGURED; > - c->ip6.addr_count = 1; > + i = c->ip6.addr_count; > + > + if (i >= IP6_MAX_ADDRS) > + die("Too many IPv6 addresses"); > + > + c->ip6.addrs[i].addr.a6 = addr.a6; > + c->ip6.addrs[i].prefix_len = prefix_len; > + c->ip6.addrs[i].flags = INANY_ADDR_CONFIGURED; This made me realise that perhaps _CONFIGURED isn't the best description for these addresses: the other ones were configured by somebody or something anyway, just not directly specified by the user. What about INANY_ADDR_USER? Or INANY_ADDR_OPTION? > + c->ip6.addr_count++; > if (c->mode == MODE_PASTA) > c->ip6.no_copy_addrs = true; > break; > @@ -1904,10 +1912,15 @@ void conf(struct ctx *c, int argc, char **argv) > a4 = inany_v4(&addr); > > if (af == AF_INET && a4) { > - c->ip4.addrs[0].addr = inany_from_v4(*a4); > - c->ip4.addrs[0].flags |= INANY_ADDR_CONFIGURED; > - c->ip4.addr_count = 1; > - if (prefix_len) { > + i = c->ip4.addr_count; > + > + if (i >= IP4_MAX_ADDRS) > + die("Too many IPv4 addresses"); > + > + c->ip4.addrs[i].addr = inany_from_v4(*a4); > + c->ip4.addrs[i].prefix_len = prefix_len; > + c->ip4.addrs[i].flags = INANY_ADDR_CONFIGURED; > + if (i == 0 && prefix_len) { > if (prefix_from_opt) > die("Can't mix CIDR with -n"); > prefix_from_cidr = true; > @@ -1915,6 +1928,9 @@ void conf(struct ctx *c, int argc, char **argv) > prefix_len = ip4_default_prefix_len(a4); > } > c->ip4.addrs[0].prefix_len = prefix_len; > + c->ip4.addr_count++; > + if (c->mode == MODE_PASTA) > + c->ip4.no_copy_addrs = true; > break; > } > > @@ -2217,7 +2233,7 @@ void conf(struct ctx *c, int argc, char **argv) > if (!c->ifi6) { > c->no_ndp = 1; > c->no_dhcpv6 = 1; > - } else if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addrs[0].addr.a6)) { > + } else if (!c->ip6.addr_count) { > c->no_dhcpv6 = 1; > } > > diff --git a/pasta.c b/pasta.c > index 1bb3dd0..27ce6a7 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -338,10 +338,16 @@ void pasta_ns_conf(struct ctx *c) > > if (c->ifi4) { > if (c->ip4.no_copy_addrs) { > - rc = nl_addr_set(nl_sock_ns, c->pasta_ifi, > - AF_INET, > - inany_v4(&c->ip4.addrs[0].addr), > - c->ip4.addrs[0].prefix_len); > + int i; > + > + for (i = 0; i < c->ip4.addr_count; i++) { > + rc = nl_addr_set(nl_sock_ns, > + c->pasta_ifi, AF_INET, > + inany_v4(&c->ip4.addrs[i].addr), > + c->ip4.addrs[i].prefix_len); > + if (rc < 0) > + break; > + } Same comment as David had on the configuration part: this is rather deeply nested. A helper like pasta_ns_conf_ip4() might... help. Same for the IPv6 part. > } else { > rc = nl_addr_dup(nl_sock, c->ifi4, > nl_sock_ns, c->pasta_ifi, > @@ -387,12 +393,18 @@ void pasta_ns_conf(struct ctx *c) > 0, IFF_NOARP); > > if (c->ip6.no_copy_addrs) { > - struct in6_addr *a = &c->ip6.addrs[0].addr.a6; > + struct in6_addr *a; cppcheck suggests that: pasta.c:406:22: style: The scope of the variable 'a' can be reduced. [variableScope] struct in6_addr *a; ^ > + int i; > > - if (!IN6_IS_ADDR_UNSPECIFIED(a)) { > + for (i = 0; i < c->ip6.addr_count; i++) { > + a = &c->ip6.addrs[i].addr.a6; > + if (IN6_IS_ADDR_UNSPECIFIED(a)) > + continue; > rc = nl_addr_set(nl_sock_ns, > c->pasta_ifi, > AF_INET6, a, 64); > + if (rc < 0) > + break; > } > } else { > rc = nl_addr_dup(nl_sock, c->ifi6, -- Stefano