int force = 0;
int max_flush_loops = 10;
int batch_mode = 0;
+bool do_all = false;
struct rtnl_handle rth = { .fd = -1 };
" -4 | -6 | -I | -D | -B | -0 |\n"
" -l[oops] { maximum-addr-flush-attempts } |\n"
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
-" -rc[vbuf] [size] | -n[etns] name }\n");
+" -rc[vbuf] [size] | -n[etns] name | -a[ll] }\n");
exit(-1);
}
NEXT_ARG();
if (netns_switch(argv[1]))
exit(-1);
+ } else if (matches(opt, "-all") == 0) {
+ do_all = true;
} else {
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
exit(-1);
fprintf(stderr, " ip netns delete NAME\n");
fprintf(stderr, " ip netns identify [PID]\n");
fprintf(stderr, " ip netns pids NAME\n");
- fprintf(stderr, " ip netns exec NAME cmd ...\n");
+ fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n");
fprintf(stderr, " ip netns monitor\n");
exit(-1);
}
return 0;
}
-static int netns_exec(int argc, char **argv)
+static int cmd_exec(const char *cmd, char **argv, bool do_fork)
{
- /* Setup the proper environment for apps that are not netns
- * aware, and execute a program in that environment.
- */
- const char *cmd;
-
- if (argc < 1) {
- fprintf(stderr, "No netns name specified\n");
- return -1;
- }
- if (argc < 2) {
- fprintf(stderr, "No command specified\n");
- return -1;
- }
- cmd = argv[1];
-
- if (netns_switch(argv[0]))
- return -1;
-
fflush(stdout);
-
- if (batch_mode) {
+ if (do_fork) {
int status;
pid_t pid;
}
if (WIFEXITED(status)) {
- /* ip must return the status of the child,
- * but do_cmd() will add a minus to this,
- * so let's add another one here to cancel it.
- */
- return -WEXITSTATUS(status);
+ return WEXITSTATUS(status);
}
exit(1);
}
}
- if (execvp(cmd, argv + 1) < 0)
+ if (execvp(cmd, argv) < 0)
fprintf(stderr, "exec of \"%s\" failed: %s\n",
- cmd, strerror(errno));
+ cmd, strerror(errno));
_exit(1);
}
+static int on_netns_exec(char *nsname, void *arg)
+{
+ char **argv = arg;
+ cmd_exec(argv[1], argv + 1, true);
+ return 0;
+}
+
+static int netns_exec(int argc, char **argv)
+{
+ /* Setup the proper environment for apps that are not netns
+ * aware, and execute a program in that environment.
+ */
+ const char *cmd;
+
+ if (argc < 1 && !do_all) {
+ fprintf(stderr, "No netns name specified\n");
+ return -1;
+ }
+ if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
+ fprintf(stderr, "No command specified\n");
+ return -1;
+ }
+
+ if (do_all)
+ return do_each_netns(on_netns_exec, --argv, 1);
+
+ if (netns_switch(argv[0]))
+ return -1;
+
+ /* ip must return the status of the child,
+ * but do_cmd() will add a minus to this,
+ * so let's add another one here to cancel it.
+ */
+ cmd = argv[1];
+ return -cmd_exec(cmd, argv + 1, !!batch_mode);
+}
+
static int is_pid(const char *str)
{
int ch;
.I NETNSNAME
.ti -8
-.BR "ip netns exec "
-.I NETNSNAME command ...
+.BR "ip [-all] netns exec "
+.RI "[ " NETNSNAME " ] " command ...
.ti -8
.BR "ip netns monitor"
the named network namespace as their primary network namespace.
.TP
-.B ip netns exec NAME cmd ... - Run cmd in the named network namespace
+.B ip [-all] netns exec [ NAME ] cmd ... - Run cmd in the named network namespace
.sp
This command allows applications that are network namespace unaware
to be run in something other than the default network namespace with
are used to move files from their network namespace specific location
to their default locations without affecting other processes.
+If
+.B -all
+option was specified then
+.B cmd
+will be executed synchronously on the each named network namespace even if
+.B cmd
+fails on some of them. Network namespace name is printed on each
+.B cmd
+executing.
+
.TP
.B ip netns monitor - Report as network namespace names are added and deleted
.sp