From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 85C3A5A004E for ; Thu, 20 Jun 2024 02:05:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1718841913; bh=An5SXkqu65OfgVZu9i8gcst0C/RSa1WFL21dNMglqPw=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=cpdWr55Sr4+KYKqWz0shYiRnZZ8wDjOhXyH4MYp6UYMbcPMoQWl4NeNiB8OVj3L+9 o8THXFG8882nKilauy0BwMfLRN2XVIpw9AT9JvMTBz4Ukh7K3FP49xiuFUmWXCrtHg RE+YUg7il9cD9GQP0MoKmY6kUDvVd6aX2WhwC7IO92dwzU6C6elZjbzrxdCCVHaNg+ Z3p2DytlI3wztJcHxxe3yZ/l+yBHizMEzHQC9nl5nrRFfSZ1xCJw1XqF4Pp8Ur5YQl wEA0xDlb2ht8QjBlY+F6AUgBCFq6FA/P1OVjwNhewrHw0cmhMcRpb6nenz8SVAHA0z fD7yjmAs/FZQA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4W4LN93RKBz4wqK; Thu, 20 Jun 2024 10:05:13 +1000 (AEST) Date: Thu, 20 Jun 2024 10:03:12 +1000 From: David Gibson To: Stefano Brivio Subject: Re: [PATCH] conf: Accept duplicate and conflicting options, the last one wins Message-ID: References: <20240618161723.1896519-1-sbrivio@redhat.com> <20240619094522.4515597e@elisabeth> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="u/LfNjC4o/FZ4mpl" Content-Disposition: inline In-Reply-To: <20240619094522.4515597e@elisabeth> Message-ID-Hash: AKZN6PCMONQPB2KAR2UL7VBDKIHDLL44 X-Message-ID-Hash: AKZN6PCMONQPB2KAR2UL7VBDKIHDLL44 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: passt-dev@passt.top, Paul Holzinger 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: --u/LfNjC4o/FZ4mpl Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, Jun 19, 2024 at 09:45:30AM +0200, Stefano Brivio wrote: > On Wed, 19 Jun 2024 11:50:44 +1000 > David Gibson wrote: >=20 > > On Tue, Jun 18, 2024 at 06:17:23PM +0200, Stefano Brivio wrote: > > > In multiple occasions, especially when passt(1) and pasta(1) are used > > > in integrations such as the one with Podman, the ability to override > > > earlier options on the command line with later one would have been > > > convenient. > > >=20 > > > Recently, to debug a number of issues happening with Podman, I would > > > have liked to ask users to share a debug log by passing --debug as > > > additional option, but pasta refuses --quiet (always passed by Podman) > > > and --debug at the same time. > > >=20 > > > Finally, somebody took care of this on Podman side at: > > > https://github.com/containers/common/pull/2052 > > >=20 > > > but still, we'll probably have similar cases, or older versions of > > > Podman around, etc. > > >=20 > > > I think there's some value in telling users about duplicated or > > > conflicting options, because that might reveal issues in integrations > > > or accidental misconfigurations, but by now I'm fairly convinced that > > > the downsides outweigh this. =20 > >=20 > > I tend to agree. > >=20 > > > Drop checks about duplicate options and mutually exclusive ones. In > > > some cases, we need to also undo a couple of initialisations caused > > > by earlier options, but this looks like a simplification, overall. > > >=20 > > > Suggested-by: Paul Holzinger > > > Suggested-by: David Gibson > > > Signed-off-by: Stefano Brivio =20 > >=20 > > [snip] > > > + case 'd': > > > c->debug =3D 1; > > > + c->quiet =3D 0; > > > break; > > > case 'e': > > > - if (logfile) > > > - die("Can't log to both file and stderr"); > > > - > > > - if (c->force_stderr) > > > - die("Multiple --stderr options given"); > > > - > > > c->force_stderr =3D 1; > > > + logfile =3D NULL; > > > break; =20 > >=20 > > I would suggest leaving this one as is for now. I think the least > > surprising behaviour for -e and -l together would be to log to both > > stderr and the file. They're not inherently contradictory, it's just > > because of an implementation limitation. >=20 > It's not really because of something missing in the implementation, > it's that way because the KubeVirt integration needed to ensure that, > with a log file, we won't print anything to standard error (which was > otherwise giving them issues). Hmmmmm... I mean, I get that we generally want to make things easy for KubeVirt. But I don't think we want to implement otherwise more surprising behaviour, just so they can avoid a '2> /dev/null'. > > Theferore, in this case, I > > think it's best to give an error rather than behaving in a surprising > > way. Later on we can implement being able to log to both at once. >=20 > But sure, one might have the reasonable expectation (even though that > would conflict with the description from the man page) that -e and -l > would log to file and stderr at the same time, so I'll drop this part, > and describe this behaviour as an exception in the man page. >=20 > > > case 'l': > > > - if (c->force_stderr) > > > - die("Can't log to both stderr and file"); > > > - > > > - if (logfile) > > > - die("Multiple --log-file options given"); > > > - > > > logfile =3D optarg; > > > + c->force_stderr =3D 0; =20 > >=20 > > Same here, of course. > >=20 > >=20 > > > break; > > > case 'q': > > > - if (c->quiet) > > > - die("Multiple --quiet options given"); > > > - > > > - if (c->debug) > > > - die("Either --debug or --quiet"); > > > - > > > c->quiet =3D 1; > > > + c->debug =3D c->trace =3D 0; > > > break; > > > case 'f': > > > - if (c->foreground) > > > - die("Multiple --foreground options given"); > > > - > > > c->foreground =3D 1; > > > break; > > > case 's': > > > - if (*c->sock_path) > > > - die("Multiple --socket options given"); > > > - > > > ret =3D snprintf(c->sock_path, UNIX_SOCK_MAX - 1, "%s", > > > optarg); > > > if (ret <=3D 0 || ret >=3D (int)sizeof(c->sock_path)) > > > die("Invalid socket path: %s", optarg); > > > =20 > > > + c->fd_tap =3D -1; > > > break; > > > case 'F': > > > - if (c->fd_tap >=3D 0) > > > - die("Multiple --fd options given"); > > > - > > > errno =3D 0; > > > c->fd_tap =3D strtol(optarg, NULL, 0); =20 > >=20 > > I'm a little bit dubious about this one too. In terms of pure > > semantics, then yes, overriding makes sense. But -F specifically > > requires the caller to have set up fds in specific slots, so it's > > pretty hard to see a real situation where overriding this would make > > sense. >=20 > Sure, I don't see that either, but for the sake of keeping the > documentation simple, I would still force this. Faor enough. > > > @@ -1460,12 +1421,9 @@ void conf(struct ctx *c, int argc, char **argv) > > > die("Invalid --fd: %s", optarg); > > > =20 > > > c->one_off =3D true; > > > - > > > + *c->sock_path =3D 0; =20 > >=20 > > This makes sense, although we weren't actually giving an error for > > that case previously. >=20 > We did, but later: >=20 > if (*c->sock_path && c->fd_tap >=3D 0) > die("Options --socket and --fd are mutually exclusive"); >=20 > as I'm dropping this now, we need to make sure that c->sock_path is > cleared. Good point. > > > break; > > > case 'I': > > > - if (*c->pasta_ifn) > > > - die("Multiple --ns-ifname options given"); > > > - > > > ret =3D snprintf(c->pasta_ifn, IFNAMSIZ, "%s", > > > optarg); > > > if (ret <=3D 0 || ret >=3D IFNAMSIZ) > > > @@ -1473,18 +1431,12 @@ void conf(struct ctx *c, int argc, char **arg= v) > > > =20 > > > break; > > > case 'p': > > > - if (*c->pcap) > > > - die("Multiple --pcap options given"); > > > - =20 > >=20 > > Again, I'm unsure about this one, since I think the least surprising > > behaviour would be to write to _all_ the listed pcap files. >=20 > ...but we clearly don't want to implement that. And if we give an error > here, we should also specifically document that multiple --pcap options > are not allowed, at this point, which just looks like unnecessary bloat > in the man page to me. I suppose. > > > ret =3D snprintf(c->pcap, sizeof(c->pcap), "%s", optarg); > > > if (ret <=3D 0 || ret >=3D (int)sizeof(c->pcap)) > > > die("Invalid pcap path: %s", optarg); > > > =20 > > > break; > > > case 'P': > > > - if (*c->pidfile) > > > - die("Multiple --pid options given"); > > > - > > > ret =3D snprintf(c->pidfile, sizeof(c->pidfile), "%s", > > > optarg); > > > if (ret <=3D 0 || ret >=3D (int)sizeof(c->pidfile)) > > > @@ -1492,9 +1444,6 @@ void conf(struct ctx *c, int argc, char **argv) > > > =20 > > > break; > > > case 'm': > > > - if (c->mtu) > > > - die("Multiple --mtu options given"); > > > - > > > errno =3D 0; > > > c->mtu =3D strtol(optarg, NULL, 0); > > > =20 > > > @@ -1544,14 +1493,12 @@ void conf(struct ctx *c, int argc, char **arg= v) > > > if (c->mode =3D=3D MODE_PASTA) > > > c->no_copy_routes =3D 1; > > > =20 > > > - if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.gw) && > > > - inet_pton(AF_INET6, optarg, &c->ip6.gw) && > > > + if (inet_pton(AF_INET6, optarg, &c->ip6.gw) && > > > !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.gw) && > > > !IN6_IS_ADDR_LOOPBACK(&c->ip6.gw)) > > > break; > > > =20 > > > - if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.gw) && > > > - inet_pton(AF_INET, optarg, &c->ip4.gw) && > > > + if (inet_pton(AF_INET, optarg, &c->ip4.gw) && > > > !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.gw) && > > > !IN4_IS_ADDR_BROADCAST(&c->ip4.gw) && > > > !IN4_IS_ADDR_LOOPBACK(&c->ip4.gw)) > > > @@ -1560,15 +1507,11 @@ void conf(struct ctx *c, int argc, char **arg= v) > > > die("Invalid gateway address: %s", optarg); > > > break; > > > case 'i': > > > - if (ifi4 || ifi6) > > > - die("Redundant interface: %s", optarg); > > > - > > > if (!(ifi4 =3D ifi6 =3D if_nametoindex(optarg))) > > > die_perror("Invalid interface name %s", optarg); > > > break; > > > case 'o': > > > - if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr_out) && > > > - inet_pton(AF_INET6, optarg, &c->ip6.addr_out) && > > > + if (inet_pton(AF_INET6, optarg, &c->ip6.addr_out) && > > > !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr_out) && > > > !IN6_IS_ADDR_LOOPBACK(&c->ip6.addr_out) && > > > !IN6_IS_ADDR_V4MAPPED(&c->ip6.addr_out) && > > > @@ -1576,8 +1519,7 @@ void conf(struct ctx *c, int argc, char **argv) > > > !IN6_IS_ADDR_MULTICAST(&c->ip6.addr_out)) > > > break; > > > =20 > > > - if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.addr_out) && > > > - inet_pton(AF_INET, optarg, &c->ip4.addr_out) && > > > + if (inet_pton(AF_INET, optarg, &c->ip4.addr_out) && > > > !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.addr_out) && > > > !IN4_IS_ADDR_BROADCAST(&c->ip4.addr_out) && > > > !IN4_IS_ADDR_MULTICAST(&c->ip4.addr_out)) > > > @@ -1588,18 +1530,23 @@ void conf(struct ctx *c, int argc, char **arg= v) > > > break; > > > case 'D': > > > if (!strcmp(optarg, "none")) { > > > - if (c->no_dns) > > > - die("Redundant DNS options"); > > > + c->no_dns =3D 1; > > > =20 > > > - if (dns4 - c->ip4.dns || dns6 - c->ip6.dns) > > > - die("Conflicting DNS options"); > > > + dns4 =3D &c->ip4.dns[0]; > > > + memset(c->ip4.dns, 0, sizeof(c->ip4.dns)); > > > + c->ip4.dns[0] =3D (struct in_addr){ 0 }; > > > + c->ip4.dns_match =3D (struct in_addr){ 0 }; > > > + c->ip4.dns_host =3D (struct in_addr){ 0 }; > > > + > > > + dns6 =3D &c->ip6.dns[0]; > > > + memset(c->ip6.dns, 0, sizeof(c->ip6.dns)); > > > + c->ip6.dns_match =3D (struct in6_addr){ 0 }; > > > + c->ip6.dns_host =3D (struct in6_addr){ 0 }; > > > =20 > > > - c->no_dns =3D 1; > > > break; > > > } > > > =20 > > > - if (c->no_dns) > > > - die("Conflicting DNS options"); > > > + c->no_dns =3D 0; > > > =20 > > > if (dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) && > > > inet_pton(AF_INET, optarg, &dns4_tmp)) { > > > @@ -1617,18 +1564,14 @@ void conf(struct ctx *c, int argc, char **arg= v) > > > break; > > > case 'S': > > > if (!strcmp(optarg, "none")) { > > > - if (c->no_dns_search) > > > - die("Redundant DNS search options"); > > > + c->no_dns_search =3D 1; > > > =20 > > > - if (dnss !=3D c->dns_search) > > > - die("Conflicting DNS search options"); > > > + memset(c->dns_search, 0, sizeof(c->dns_search)); > > > =20 > > > - c->no_dns_search =3D 1; > > > break; > > > } > > > =20 > > > - if (c->no_dns_search) > > > - die("Conflicting DNS search options"); > > > + c->no_dns_search =3D 0; > > > =20 > > > if (dnss - c->dns_search < ARRAY_SIZE(c->dns_search)) { > > > ret =3D snprintf(dnss->n, sizeof(*c->dns_search), > > > @@ -1644,17 +1587,16 @@ void conf(struct ctx *c, int argc, char **arg= v) > > > break; > > > case '4': > > > v4_only =3D true; > > > + v6_only =3D false; > > > break; > > > case '6': > > > v6_only =3D true; > > > + v4_only =3D false; > > > break; > > > case '1': > > > if (c->mode =3D=3D MODE_PASTA) > > > die("--one-off is for passt mode only"); > > > =20 > > > - if (c->one_off) > > > - die("Redundant --one-off option"); > > > - > > > c->one_off =3D true; > > > break; > > > case 't': > > > @@ -1673,12 +1615,6 @@ void conf(struct ctx *c, int argc, char **argv) > > > } > > > } while (name !=3D -1); > > > =20 > > > - if (v4_only && v6_only) > > > - die("Options ipv4-only and ipv6-only are mutually exclusive"); =20 > >=20 > > This could now be an ASSERT() instead of an error message. >=20 > But it can't happen, right? I mean, it's very clear that when we set > one, we clear the other one (hunk above). >=20 > > > - if (*c->sock_path && c->fd_tap >=3D 0) > > > - die("Options --socket and --fd are mutually exclusive"); > > > - > > > if (c->mode =3D=3D MODE_PASTA && !c->pasta_conf_ns) { > > > if (copy_routes_opt) > > > die("--no-copy-routes needs --config-net"); > > > diff --git a/passt.1 b/passt.1 > > > index 31e528e..6dfa670 100644 > > > --- a/passt.1 > > > +++ b/passt.1 > > > @@ -73,6 +73,8 @@ for performance reasons. > > > =20 > > > .SH OPTIONS > > > =20 > > > +\fBIf conflicting or multiple options are given, the last one takes = effect.\fR > > > + > > > .TP > > > .BR \-d ", " \-\-debug > > > Be verbose, don't log to the system logger. =20 > >=20 >=20 --=20 David Gibson (he or they) | 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 --u/LfNjC4o/FZ4mpl Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmZzcZcACgkQzQJF27ox 2GfaUA//TXdw47MMcZjBKsENfOuSCw58sGxeqtG5UACedeBr6AI16aFnNs6/F31q JFux33yTroTK81W8IOxNXDb5ZEYqh2gPcK1f0H4A9GIv/czsDkmPcg1qOR8TGxKM 637CRxvU6WpoOKlZCzdX/CJ+LfzKYGcRY+vN3H6ljGbwRAB89wYY5JY5DLkg4mO5 OiuI9nwV+foIX0YxGWd318dLrKxMC3Dc5rtyH8+pFTU5p1MddmwcDl8rLFHFQfAP VZmt2ns5KyygiGEKTSBvBMaeYuX/atwNXBkHir/a/ISnlpSfWapNCqciskpyljfI jQ3OrOXCjjyqz0V9vAX8rpqPx3BlGQU3G3VZu2hU6XXswfnqIac5CHsJ+oB8xJaY Osh7OItQr06aI5QzRZLWaYb2/jSBHnVbxkc+wZVyP7vo6T3I6FjQ4niOPTRrSByq lCtGoDsi2qguKvEzqrUWTczolEBx93v9g1iBhpZ+qat6FF7oi8n3J0nPMhUUtpdU bmxfWENAv9bAAACpRjBCBODIZR5VTbBYx9WTkzr3z6oM1OOjf68ngACHEVbcpwQF vfkDwJIETOrBGViNgGdNrXhWu3pMpYoS0pcDmBXt5Rm6D33f8Z5LmiW9tpZr8Ulz m/rdGrzQKMkUhLEimf1A3mgJPCkVgDLP0hY1ugarbuF6HESExuM= =dMO+ -----END PGP SIGNATURE----- --u/LfNjC4o/FZ4mpl--