From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Gibson To: passt-dev@passt.top Subject: [PATCH 7/8] Use explicit --netns option rather than multiplexing with PID Date: Fri, 26 Aug 2022 14:58:38 +1000 Message-ID: <20220826045839.1112152-8-david@gibson.dropbear.id.au> In-Reply-To: <20220826045839.1112152-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0701724398958187198==" --===============0701724398958187198== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When attaching to an existing namespace, pasta can take a PID or the name or path of a network namespace as a non-option parameter. We disambiguate based on what the parameter looks like. Make this more explicit by using a --netns option for explicitly giving the path or name, and treating a non-option argument always as a PID. Signed-off-by: David Gibson --- conf.c | 85 ++++++++++++++++++++++++++++++++++++++++----------------- passt.1 | 16 +++++++++-- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/conf.c b/conf.c index 10b7b9f..2a18124 100644 --- a/conf.c +++ b/conf.c @@ -490,19 +490,51 @@ out: } =20 /** - * conf_ns_opt() - Parse non-option argument to namespace paths + * conf_netns() - Parse --netns option + * @netns: buffer of size PATH_MAX, updated with netns path + * @arg: --netns argument + * + * Return: 0 on success, negative error code otherwise + */ +static int conf_netns(char *netns, const char *arg) +{ + int ret; + + if (!strchr(arg, '/')) { + /* looks like a netns name */ + ret =3D snprintf(netns, PATH_MAX, "%s/%s", NETNS_RUN_DIR, arg); + } else { + /* otherwise assume it's a netns path */ + ret =3D snprintf(netns, PATH_MAX, "%s", arg); + } + + if (ret <=3D 0 || ret > PATH_MAX) { + err("Network namespace name/path %s too long"); + return -E2BIG; + } + + return 0; +} + +/** + * conf_ns_pid() - Parse non-option argument as a PID * @userns: buffer of size PATH_MAX, initially contains --userns * argument (may be empty), updated with userns path - * @netns: buffer of size PATH_MAX, updated with netns path - * @arg: PID, path or name of network namespace + * @netns: buffer of size PATH_MAX, initial contains --netns + * argument (may be empty), updated with netns path + * @arg: PID of network namespace * * Return: 0 on success, negative error code otherwise */ -static int conf_ns_opt(char *userns, char *netns, const char *arg) +static int conf_ns_pid(char *userns, char *netns, const char *arg) { char *endptr; long pidval; - int ret; + + if (*netns) { + err("Both --netns and PID given"); + return -EINVAL; + } =20 pidval =3D strtol(arg, &endptr, 10); if (!*endptr) { @@ -518,20 +550,7 @@ static int conf_ns_opt(char *userns, char *netns, const = char *arg) return 0; } =20 - if (!strchr(arg, '/')) { - /* looks like a netns name */ - ret =3D snprintf(netns, PATH_MAX, "%s/%s", NETNS_RUN_DIR, arg); - } else { - /* otherwise assume it's a netns path */ - ret =3D snprintf(netns, PATH_MAX, "%s", arg); - } - - if (ret <=3D 0 || ret > PATH_MAX) { - err("Network namespace name/path %s too long"); - return -E2BIG; - } - - return 0; + return -EINVAL; } =20 /** @@ -708,10 +727,13 @@ static unsigned int conf_ip6(unsigned int ifi, static void usage(const char *name) { if (strstr(name, "pasta")) { - info("Usage: %s [OPTION]... [PID|PATH|NAME]", name); + info("Usage: %s [OPTION]... [COMMAND] [ARGS]...", name); + info(" %s [OPTION]... PID", name); + info(" %s [OPTION]... --netns [PATH|NAME]", name); info(""); - info("Without PID|PATH|NAME, run the default shell in a new"); - info("network and user namespace, and connect it via pasta."); + info("Without PID or --netns, run the given command or a"); + info("default shell in a new network and user namespace, and"); + info("connect it via pasta."); } else { info("Usage: %s [OPTION]...", name); } @@ -858,6 +880,7 @@ pasta_opts: info( " SPEC is as described above"); info( " default: auto"); info( " --userns NSPATH Target user namespace to join"); + info( " --netns PATH|NAME Target network namespace to join"); info( " --netns-only Don't join existing user namespace"); info( " implied if PATH or NAME are given without --userns"); info( " --config-net Configure tap interface in namespace"); @@ -1038,6 +1061,7 @@ void conf(struct ctx *c, int argc, char **argv) {"tcp-ns", required_argument, NULL, 'T' }, {"udp-ns", required_argument, NULL, 'U' }, {"userns", required_argument, NULL, 2 }, + {"netns", required_argument, NULL, 3 }, {"netns-only", no_argument, &c->netns_only, 1 }, {"config-net", no_argument, &c->pasta_conf_ns, 1 }, {"ns-mac-addr", required_argument, NULL, 4 }, @@ -1091,6 +1115,16 @@ void conf(struct ctx *c, int argc, char **argv) usage(argv[0]); } break; + case 3: + if (c->mode !=3D MODE_PASTA) { + err("--netns is for pasta mode only"); + usage(argv[0]); + } + + ret =3D conf_netns(netns, optarg); + if (ret < 0) + usage(argv[0]); + break; case 4: if (c->mode !=3D MODE_PASTA) { err("--ns-mac-addr is for pasta mode only"); @@ -1447,11 +1481,12 @@ void conf(struct ctx *c, int argc, char **argv) check_root(c); =20 if (c->mode =3D=3D MODE_PASTA && optind + 1 =3D=3D argc) { - ret =3D conf_ns_opt(userns, netns, argv[optind]); + ret =3D conf_ns_pid(userns, netns, argv[optind]); if (ret < 0) usage(argv[0]); - } else if (c->mode =3D=3D MODE_PASTA && *userns && optind =3D=3D argc) { - err("--userns requires PID, PATH or NAME"); + } else if (c->mode =3D=3D MODE_PASTA && *userns + && !*netns && optind =3D=3D argc) { + err("--userns requires --netns or PID"); usage(argv[0]); } else if (optind !=3D argc) { usage(argv[0]); diff --git a/passt.1 b/passt.1 index bbdadc1..4a09ced 100644 --- a/passt.1 +++ b/passt.1 @@ -15,7 +15,10 @@ [\fIOPTION\fR]... .br .B pasta -[\fIOPTION\fR]... [\fIPID\fR|\fIPATH\fR|\fINAME\fR] +[\fIOPTION\fR]... [\fIPID\fR] +.br +.B pasta +[\fIOPTION\fR]... \fB--netns\fR [\fIPATH\fR|\fINAME\fR] =20 .SH DESCRIPTION =20 @@ -59,7 +62,7 @@ or with the \fBqrap\fR(1) wrapper. equivalent functionality to network namespaces, as the one offered by \fBpasst\fR for virtual machines. =20 -If PID, PATH or NAME are given, \fBpasta\fR associates to an existing user a= nd +If PID or --netns are given, \fBpasta\fR associates to an existing user and network namespace. Otherwise, \fBpasta\fR creates a new user and network namespace, and spawns an interactive shell within this context. A \fItap\fR device within the network namespace is created to provide network connectivi= ty. @@ -445,7 +448,14 @@ Default is \fBauto\fR. Target user namespace to join, as a path. If PID is given, without this opti= on, the user namespace will be the one of the corresponding process. =20 -This option requires PID, PATH or NAME to be specified. +This option requires --netns or a PID to be specified. + +.TP +.BR \-\-netns " " \fIspec +Target network namespace to join, as a path or a name. A name is treated as +with \fBip-netns(8)\fR as a equivalent to a path in \fI/run/netns\fR. + +This option can't be specified with a PID. =20 .TP .BR \-\-netns-only --=20 2.37.2 --===============0701724398958187198==--