'ip netns exec' changes the current netns just before executing a child process, and restores it after forking. This is needed if we're running in batch or do_all mode, as well as other cleanup things like VRF associations. Add an argument to cmd_exec() which allows to switch the current netns directly in the child, so the parent environment is kept unaltered. By doing so, some utility functions became unused, so remove them.
Signed-off-by: Matteo Croce <mcr...@redhat.com> --- include/utils.h | 5 +---- ip/ip_common.h | 1 - ip/ipnetns.c | 18 ++++-------------- ip/ipvrf.c | 16 +--------------- lib/exec.c | 6 +++++- lib/utils.c | 27 --------------------------- 6 files changed, 11 insertions(+), 62 deletions(-) diff --git a/include/utils.h b/include/utils.h index 8a9c3020..c58a3886 100644 --- a/include/utils.h +++ b/include/utils.h @@ -294,14 +294,11 @@ extern int cmdlineno; ssize_t getcmdline(char **line, size_t *len, FILE *in); int makeargs(char *line, char *argv[], int maxargs); -int do_each_netns(int (*func)(char *nsname, void *arg), void *arg, - bool show_label); - char *int_to_str(int val, char *buf); int get_guid(__u64 *guid, const char *arg); int get_real_family(int rtm_type, int rtm_family); -int cmd_exec(const char *cmd, char **argv, bool do_fork); +int cmd_exec(const char *cmd, char **argv, bool do_fork, char *netns); int make_path(const char *path, mode_t mode); char *find_cgroup2_mount(void); int get_command_name(const char *pid, char *comm, size_t len); diff --git a/ip/ip_common.h b/ip/ip_common.h index b4aa34a7..38203aae 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -77,7 +77,6 @@ int do_tcp_metrics(int argc, char **argv); int do_ipnetconf(int argc, char **argv); int do_iptoken(int argc, char **argv); int do_ipvrf(int argc, char **argv); -void vrf_reset(void); int netns_identify_pid(const char *pidstr, char *name, int len); int do_seg6(int argc, char **argv); diff --git a/ip/ipnetns.c b/ip/ipnetns.c index 8ead0c4c..9e414b55 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -400,7 +400,8 @@ static int on_netns_exec(char *nsname, void *arg) { char **argv = arg; - cmd_exec(argv[1], argv + 1, true); + printf("\nnetns: %s\n", nsname); + cmd_exec(argv[0], argv, true, nsname); return 0; } @@ -409,8 +410,6 @@ 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; @@ -421,22 +420,13 @@ static int netns_exec(int argc, char **argv) } if (do_all) - return do_each_netns(on_netns_exec, --argv, 1); - - if (netns_switch(argv[0])) - return -1; - - /* we just changed namespaces. clear any vrf association - * with prior namespace before exec'ing command - */ - vrf_reset(); + return netns_foreach(on_netns_exec, argv); /* 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); + return -cmd_exec(argv[1], argv + 1, !!batch_mode, argv[0]); } static int is_pid(const char *str) diff --git a/ip/ipvrf.c b/ip/ipvrf.c index a13cf653..894d85fc 100644 --- a/ip/ipvrf.c +++ b/ip/ipvrf.c @@ -456,21 +456,7 @@ static int ipvrf_exec(int argc, char **argv) if (vrf_switch(argv[0])) return -1; - return -cmd_exec(argv[1], argv + 1, !!batch_mode); -} - -/* reset VRF association of current process to default VRF; - * used by netns_exec - */ -void vrf_reset(void) -{ - char vrf[32]; - - if (vrf_identify(getpid(), vrf, sizeof(vrf)) || - (vrf[0] == '\0')) - return; - - vrf_switch("default"); + return -cmd_exec(argv[1], argv + 1, !!batch_mode, NULL); } static int ipvrf_filter_req(struct nlmsghdr *nlh, int reqlen) diff --git a/lib/exec.c b/lib/exec.c index eb36b59d..3b07e908 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -5,8 +5,9 @@ #include <unistd.h> #include "utils.h" +#include "namespace.h" -int cmd_exec(const char *cmd, char **argv, bool do_fork) +int cmd_exec(const char *cmd, char **argv, bool do_fork, char *netns) { fflush(stdout); if (do_fork) { @@ -34,6 +35,9 @@ int cmd_exec(const char *cmd, char **argv, bool do_fork) } } + if (netns && netns_switch(netns)) + return -1; + if (execvp(cmd, argv) < 0) fprintf(stderr, "exec of \"%s\" failed: %s\n", cmd, strerror(errno)); diff --git a/lib/utils.c b/lib/utils.c index a81c0700..be0f11b0 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1418,33 +1418,6 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n) fprintf(fp, "Timestamp: %s %lu us\n", tstr, usecs); } -static int on_netns(char *nsname, void *arg) -{ - struct netns_func *f = arg; - - if (netns_switch(nsname)) - return -1; - - return f->func(nsname, f->arg); -} - -static int on_netns_label(char *nsname, void *arg) -{ - printf("\nnetns: %s\n", nsname); - return on_netns(nsname, arg); -} - -int do_each_netns(int (*func)(char *nsname, void *arg), void *arg, - bool show_label) -{ - struct netns_func nsf = { .func = func, .arg = arg }; - - if (show_label) - return netns_foreach(on_netns_label, &nsf); - - return netns_foreach(on_netns, &nsf); -} - char *int_to_str(int val, char *buf) { sprintf(buf, "%d", val); -- 2.21.0