iproute2/ip/ipnetns.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#define _ATFILE_SOURCE
   3#include <sys/file.h>
   4#include <sys/types.h>
   5#include <sys/stat.h>
   6#include <sys/wait.h>
   7#include <sys/inotify.h>
   8#include <sys/mount.h>
   9#include <sys/syscall.h>
  10#include <stdio.h>
  11#include <string.h>
  12#include <sched.h>
  13#include <fcntl.h>
  14#include <dirent.h>
  15#include <errno.h>
  16#include <unistd.h>
  17#include <ctype.h>
  18#include <linux/limits.h>
  19
  20#include <linux/net_namespace.h>
  21
  22#include "utils.h"
  23#include "list.h"
  24#include "ip_common.h"
  25#include "namespace.h"
  26#include "json_print.h"
  27
  28static int usage(void)
  29{
  30        fprintf(stderr,
  31                "Usage: ip netns list\n"
  32                "       ip netns add NAME\n"
  33                "       ip netns attach NAME PID\n"
  34                "       ip netns set NAME NETNSID\n"
  35                "       ip [-all] netns delete [NAME]\n"
  36                "       ip netns identify [PID]\n"
  37                "       ip netns pids NAME\n"
  38                "       ip [-all] netns exec [NAME] cmd ...\n"
  39                "       ip netns monitor\n"
  40                "       ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]\n"
  41                "NETNSID := auto | POSITIVE-INT\n");
  42        exit(-1);
  43}
  44
  45/* This socket is used to get nsid */
  46static struct rtnl_handle rtnsh = { .fd = -1 };
  47
  48static int have_rtnl_getnsid = -1;
  49static int saved_netns = -1;
  50static struct link_filter filter;
  51
  52static int ipnetns_accept_msg(struct rtnl_ctrl_data *ctrl,
  53                              struct nlmsghdr *n, void *arg)
  54{
  55        struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
  56
  57        if (n->nlmsg_type == NLMSG_ERROR &&
  58            (err->error == -EOPNOTSUPP || err->error == -EINVAL))
  59                have_rtnl_getnsid = 0;
  60        else
  61                have_rtnl_getnsid = 1;
  62        return -1;
  63}
  64
  65static int ipnetns_have_nsid(void)
  66{
  67        struct {
  68                struct nlmsghdr n;
  69                struct rtgenmsg g;
  70                char            buf[1024];
  71        } req = {
  72                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
  73                .n.nlmsg_flags = NLM_F_REQUEST,
  74                .n.nlmsg_type = RTM_GETNSID,
  75                .g.rtgen_family = AF_UNSPEC,
  76        };
  77        int fd;
  78
  79        if (have_rtnl_getnsid >= 0) {
  80                fd = open("/proc/self/ns/net", O_RDONLY);
  81                if (fd < 0) {
  82                        fprintf(stderr,
  83                                "/proc/self/ns/net: %s. Continuing anyway.\n",
  84                                strerror(errno));
  85                        have_rtnl_getnsid = 0;
  86                        return 0;
  87                }
  88
  89                addattr32(&req.n, 1024, NETNSA_FD, fd);
  90
  91                if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
  92                        fprintf(stderr,
  93                                "rtnl_send(RTM_GETNSID): %s. Continuing anyway.\n",
  94                                strerror(errno));
  95                        have_rtnl_getnsid = 0;
  96                        close(fd);
  97                        return 0;
  98                }
  99                rtnl_listen(&rth, ipnetns_accept_msg, NULL);
 100                close(fd);
 101        }
 102
 103        return have_rtnl_getnsid;
 104}
 105
 106int get_netnsid_from_name(const char *name)
 107{
 108        struct {
 109                struct nlmsghdr n;
 110                struct rtgenmsg g;
 111                char            buf[1024];
 112        } req = {
 113                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
 114                .n.nlmsg_flags = NLM_F_REQUEST,
 115                .n.nlmsg_type = RTM_GETNSID,
 116                .g.rtgen_family = AF_UNSPEC,
 117        };
 118        struct nlmsghdr *answer;
 119        struct rtattr *tb[NETNSA_MAX + 1];
 120        struct rtgenmsg *rthdr;
 121        int len, fd, ret = -1;
 122
 123        netns_nsid_socket_init();
 124
 125        fd = netns_get_fd(name);
 126        if (fd < 0)
 127                return fd;
 128
 129        addattr32(&req.n, 1024, NETNSA_FD, fd);
 130        if (rtnl_talk(&rtnsh, &req.n, &answer) < 0) {
 131                close(fd);
 132                return -2;
 133        }
 134        close(fd);
 135
 136        /* Validate message and parse attributes */
 137        if (answer->nlmsg_type == NLMSG_ERROR)
 138                goto out;
 139
 140        rthdr = NLMSG_DATA(answer);
 141        len = answer->nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
 142        if (len < 0)
 143                goto out;
 144
 145        parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
 146
 147        if (tb[NETNSA_NSID]) {
 148                ret = rta_getattr_s32(tb[NETNSA_NSID]);
 149        }
 150
 151out:
 152        free(answer);
 153        return ret;
 154}
 155
 156struct nsid_cache {
 157        struct hlist_node       nsid_hash;
 158        struct hlist_node       name_hash;
 159        int                     nsid;
 160        char                    name[0];
 161};
 162
 163#define NSIDMAP_SIZE            128
 164#define NSID_HASH_NSID(nsid)    (nsid & (NSIDMAP_SIZE - 1))
 165#define NSID_HASH_NAME(name)    (namehash(name) & (NSIDMAP_SIZE - 1))
 166
 167static struct hlist_head        nsid_head[NSIDMAP_SIZE];
 168static struct hlist_head        name_head[NSIDMAP_SIZE];
 169
 170static struct nsid_cache *netns_map_get_by_nsid(int nsid)
 171{
 172        struct hlist_node *n;
 173        uint32_t h;
 174
 175        if (nsid < 0)
 176                return NULL;
 177
 178        h = NSID_HASH_NSID(nsid);
 179        hlist_for_each(n, &nsid_head[h]) {
 180                struct nsid_cache *c = container_of(n, struct nsid_cache,
 181                                                    nsid_hash);
 182                if (c->nsid == nsid)
 183                        return c;
 184        }
 185
 186        return NULL;
 187}
 188
 189char *get_name_from_nsid(int nsid)
 190{
 191        struct nsid_cache *c;
 192
 193        if (nsid < 0)
 194                return NULL;
 195
 196        netns_nsid_socket_init();
 197        netns_map_init();
 198
 199        c = netns_map_get_by_nsid(nsid);
 200        if (c)
 201                return c->name;
 202
 203        return NULL;
 204}
 205
 206static int netns_map_add(int nsid, const char *name)
 207{
 208        struct nsid_cache *c;
 209        uint32_t h;
 210
 211        if (netns_map_get_by_nsid(nsid) != NULL)
 212                return -EEXIST;
 213
 214        c = malloc(sizeof(*c) + strlen(name) + 1);
 215        if (c == NULL) {
 216                perror("malloc");
 217                return -ENOMEM;
 218        }
 219        c->nsid = nsid;
 220        strcpy(c->name, name);
 221
 222        h = NSID_HASH_NSID(nsid);
 223        hlist_add_head(&c->nsid_hash, &nsid_head[h]);
 224
 225        h = NSID_HASH_NAME(name);
 226        hlist_add_head(&c->name_hash, &name_head[h]);
 227
 228        return 0;
 229}
 230
 231static void netns_map_del(struct nsid_cache *c)
 232{
 233        hlist_del(&c->name_hash);
 234        hlist_del(&c->nsid_hash);
 235        free(c);
 236}
 237
 238void netns_nsid_socket_init(void)
 239{
 240        if (rtnsh.fd > -1 || !ipnetns_have_nsid())
 241                return;
 242
 243        if (rtnl_open(&rtnsh, 0) < 0) {
 244                fprintf(stderr, "Cannot open rtnetlink\n");
 245                exit(1);
 246        }
 247
 248}
 249
 250void netns_map_init(void)
 251{
 252        static int initialized;
 253        struct dirent *entry;
 254        DIR *dir;
 255        int nsid;
 256
 257        if (initialized || !ipnetns_have_nsid())
 258                return;
 259
 260        dir = opendir(NETNS_RUN_DIR);
 261        if (!dir)
 262                return;
 263
 264        while ((entry = readdir(dir)) != NULL) {
 265                if (strcmp(entry->d_name, ".") == 0)
 266                        continue;
 267                if (strcmp(entry->d_name, "..") == 0)
 268                        continue;
 269                nsid = get_netnsid_from_name(entry->d_name);
 270
 271                if (nsid >= 0)
 272                        netns_map_add(nsid, entry->d_name);
 273        }
 274        closedir(dir);
 275        initialized = 1;
 276}
 277
 278static int netns_get_name(int nsid, char *name)
 279{
 280        struct dirent *entry;
 281        DIR *dir;
 282        int id;
 283
 284        if (nsid < 0)
 285                return -EINVAL;
 286
 287        dir = opendir(NETNS_RUN_DIR);
 288        if (!dir)
 289                return -ENOENT;
 290
 291        while ((entry = readdir(dir)) != NULL) {
 292                if (strcmp(entry->d_name, ".") == 0)
 293                        continue;
 294                if (strcmp(entry->d_name, "..") == 0)
 295                        continue;
 296                id = get_netnsid_from_name(entry->d_name);
 297
 298                if (id >= 0 && nsid == id) {
 299                        strcpy(name, entry->d_name);
 300                        closedir(dir);
 301                        return 0;
 302                }
 303        }
 304        closedir(dir);
 305        return -ENOENT;
 306}
 307
 308int print_nsid(struct nlmsghdr *n, void *arg)
 309{
 310        struct rtgenmsg *rthdr = NLMSG_DATA(n);
 311        struct rtattr *tb[NETNSA_MAX+1];
 312        int len = n->nlmsg_len;
 313        FILE *fp = (FILE *)arg;
 314        struct nsid_cache *c;
 315        char name[NAME_MAX];
 316        int nsid, current;
 317
 318        if (n->nlmsg_type != RTM_NEWNSID && n->nlmsg_type != RTM_DELNSID)
 319                return 0;
 320
 321        len -= NLMSG_SPACE(sizeof(*rthdr));
 322        if (len < 0) {
 323                fprintf(stderr, "BUG: wrong nlmsg len %d in %s\n", len,
 324                        __func__);
 325                return -1;
 326        }
 327
 328        parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
 329        if (tb[NETNSA_NSID] == NULL) {
 330                fprintf(stderr, "BUG: NETNSA_NSID is missing %s\n", __func__);
 331                return -1;
 332        }
 333
 334        open_json_object(NULL);
 335        if (n->nlmsg_type == RTM_DELNSID)
 336                print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 337
 338        nsid = rta_getattr_s32(tb[NETNSA_NSID]);
 339        if (nsid < 0)
 340                print_string(PRINT_FP, NULL, "nsid unassigned ", NULL);
 341        else
 342                print_int(PRINT_ANY, "nsid", "nsid %d ", nsid);
 343
 344        if (tb[NETNSA_CURRENT_NSID]) {
 345                current = rta_getattr_s32(tb[NETNSA_CURRENT_NSID]);
 346                if (current < 0)
 347                        print_string(PRINT_FP, NULL,
 348                                     "current-nsid unassigned ", NULL);
 349                else
 350                        print_int(PRINT_ANY, "current-nsid",
 351                                  "current-nsid %d ", current);
 352        }
 353
 354        c = netns_map_get_by_nsid(tb[NETNSA_CURRENT_NSID] ? current : nsid);
 355        if (c != NULL) {
 356                print_string(PRINT_ANY, "name",
 357                             "(iproute2 netns name: %s)", c->name);
 358                netns_map_del(c);
 359        }
 360
 361        /* nsid might not be in cache */
 362        if (c == NULL && n->nlmsg_type == RTM_NEWNSID)
 363                if (netns_get_name(nsid, name) == 0) {
 364                        print_string(PRINT_ANY, "name",
 365                                     "(iproute2 netns name: %s)", name);
 366                        netns_map_add(nsid, name);
 367                }
 368
 369        print_string(PRINT_FP, NULL, "\n", NULL);
 370        close_json_object();
 371        fflush(fp);
 372        return 0;
 373}
 374
 375static int get_netnsid_from_netnsid(int nsid)
 376{
 377        struct {
 378                struct nlmsghdr n;
 379                struct rtgenmsg g;
 380                char            buf[1024];
 381        } req = {
 382                .n.nlmsg_len = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct rtgenmsg))),
 383                .n.nlmsg_flags = NLM_F_REQUEST,
 384                .n.nlmsg_type = RTM_GETNSID,
 385                .g.rtgen_family = AF_UNSPEC,
 386        };
 387        struct nlmsghdr *answer;
 388        int err;
 389
 390        netns_nsid_socket_init();
 391
 392        err = addattr32(&req.n, sizeof(req), NETNSA_NSID, nsid);
 393        if (err)
 394                return err;
 395
 396        if (filter.target_nsid >= 0) {
 397                err = addattr32(&req.n, sizeof(req), NETNSA_TARGET_NSID,
 398                                filter.target_nsid);
 399                if (err)
 400                        return err;
 401        }
 402
 403        if (rtnl_talk(&rtnsh, &req.n, &answer) < 0)
 404                return -2;
 405
 406        /* Validate message and parse attributes */
 407        if (answer->nlmsg_type == NLMSG_ERROR)
 408                goto err_out;
 409
 410        new_json_obj(json);
 411        err = print_nsid(answer, stdout);
 412        delete_json_obj();
 413err_out:
 414        free(answer);
 415        return err;
 416}
 417
 418static int netns_filter_req(struct nlmsghdr *nlh, int reqlen)
 419{
 420        int err;
 421
 422        if (filter.target_nsid >= 0) {
 423                err = addattr32(nlh, reqlen, NETNSA_TARGET_NSID,
 424                                filter.target_nsid);
 425                if (err)
 426                        return err;
 427        }
 428
 429        return 0;
 430}
 431
 432static int netns_list_id(int argc, char **argv)
 433{
 434        int nsid = -1;
 435
 436        if (!ipnetns_have_nsid()) {
 437                fprintf(stderr,
 438                        "RTM_GETNSID is not supported by the kernel.\n");
 439                return -ENOTSUP;
 440        }
 441
 442        filter.target_nsid = -1;
 443        while (argc > 0) {
 444                if (strcmp(*argv, "target-nsid") == 0) {
 445                        if (filter.target_nsid >= 0)
 446                                duparg("target-nsid", *argv);
 447                        NEXT_ARG();
 448
 449                        if (get_integer(&filter.target_nsid, *argv, 0))
 450                                invarg("\"target-nsid\" value is invalid",
 451                                       *argv);
 452                        else if (filter.target_nsid < 0)
 453                                invarg("\"target-nsid\" value should be >= 0",
 454                                       argv[1]);
 455                } else if (strcmp(*argv, "nsid") == 0) {
 456                        if (nsid >= 0)
 457                                duparg("nsid", *argv);
 458                        NEXT_ARG();
 459
 460                        if (get_integer(&nsid, *argv, 0))
 461                                invarg("\"nsid\" value is invalid", *argv);
 462                        else if (nsid < 0)
 463                                invarg("\"nsid\" value should be >= 0",
 464                                       argv[1]);
 465                } else
 466                        usage();
 467                argc--; argv++;
 468        }
 469
 470        if (nsid >= 0)
 471                return get_netnsid_from_netnsid(nsid);
 472
 473        if (rtnl_nsiddump_req_filter_fn(&rth, AF_UNSPEC,
 474                                        netns_filter_req) < 0) {
 475                perror("Cannot send dump request");
 476                exit(1);
 477        }
 478
 479        new_json_obj(json);
 480        if (rtnl_dump_filter(&rth, print_nsid, stdout) < 0) {
 481                delete_json_obj();
 482                fprintf(stderr, "Dump terminated\n");
 483                exit(1);
 484        }
 485        delete_json_obj();
 486        return 0;
 487}
 488
 489static int netns_list(int argc, char **argv)
 490{
 491        struct dirent *entry;
 492        DIR *dir;
 493        int id;
 494
 495        dir = opendir(NETNS_RUN_DIR);
 496        if (!dir)
 497                return 0;
 498
 499        new_json_obj(json);
 500        while ((entry = readdir(dir)) != NULL) {
 501                if (strcmp(entry->d_name, ".") == 0)
 502                        continue;
 503                if (strcmp(entry->d_name, "..") == 0)
 504                        continue;
 505
 506                open_json_object(NULL);
 507                print_string(PRINT_ANY, "name",
 508                             "%s", entry->d_name);
 509                if (ipnetns_have_nsid()) {
 510                        id = get_netnsid_from_name(entry->d_name);
 511                        if (id >= 0)
 512                                print_int(PRINT_ANY, "id", " (id: %d)", id);
 513                }
 514                print_string(PRINT_FP, NULL, "\n", NULL);
 515                close_json_object();
 516        }
 517        closedir(dir);
 518        delete_json_obj();
 519        return 0;
 520}
 521
 522static int do_switch(void *arg)
 523{
 524        char *netns = arg;
 525
 526        /* we just changed namespaces. clear any vrf association
 527         * with prior namespace before exec'ing command
 528         */
 529        vrf_reset();
 530
 531        return netns_switch(netns);
 532}
 533
 534static int on_netns_exec(char *nsname, void *arg)
 535{
 536        char **argv = arg;
 537
 538        printf("\nnetns: %s\n", nsname);
 539        cmd_exec(argv[0], argv, true, do_switch, nsname);
 540        return 0;
 541}
 542
 543static int netns_exec(int argc, char **argv)
 544{
 545        /* Setup the proper environment for apps that are not netns
 546         * aware, and execute a program in that environment.
 547         */
 548        if (argc < 1 && !do_all) {
 549                fprintf(stderr, "No netns name specified\n");
 550                return -1;
 551        }
 552        if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
 553                fprintf(stderr, "No command specified\n");
 554                return -1;
 555        }
 556
 557        if (do_all)
 558                return netns_foreach(on_netns_exec, argv);
 559
 560        /* ip must return the status of the child,
 561         * but do_cmd() will add a minus to this,
 562         * so let's add another one here to cancel it.
 563         */
 564        return -cmd_exec(argv[1], argv + 1, !!batch_mode, do_switch, argv[0]);
 565}
 566
 567static int is_pid(const char *str)
 568{
 569        int ch;
 570
 571        for (; (ch = *str); str++) {
 572                if (!isdigit(ch))
 573                        return 0;
 574        }
 575        return 1;
 576}
 577
 578static int netns_pids(int argc, char **argv)
 579{
 580        const char *name;
 581        char net_path[PATH_MAX];
 582        int netns = -1, ret = -1;
 583        struct stat netst;
 584        DIR *dir;
 585        struct dirent *entry;
 586
 587        if (argc < 1) {
 588                fprintf(stderr, "No netns name specified\n");
 589                goto out;
 590        }
 591        if (argc > 1) {
 592                fprintf(stderr, "extra arguments specified\n");
 593                goto out;
 594        }
 595
 596        name = argv[0];
 597        snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
 598        netns = open(net_path, O_RDONLY);
 599        if (netns < 0) {
 600                fprintf(stderr, "Cannot open network namespace: %s\n",
 601                        strerror(errno));
 602                goto out;
 603        }
 604        if (fstat(netns, &netst) < 0) {
 605                fprintf(stderr, "Stat of netns failed: %s\n",
 606                        strerror(errno));
 607                goto out;
 608        }
 609        dir = opendir("/proc/");
 610        if (!dir) {
 611                fprintf(stderr, "Open of /proc failed: %s\n",
 612                        strerror(errno));
 613                goto out;
 614        }
 615        while ((entry = readdir(dir))) {
 616                char pid_net_path[PATH_MAX];
 617                struct stat st;
 618
 619                if (!is_pid(entry->d_name))
 620                        continue;
 621                snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net",
 622                        entry->d_name);
 623                if (stat(pid_net_path, &st) != 0)
 624                        continue;
 625                if ((st.st_dev == netst.st_dev) &&
 626                    (st.st_ino == netst.st_ino)) {
 627                        printf("%s\n", entry->d_name);
 628                }
 629        }
 630        ret = 0;
 631        closedir(dir);
 632out:
 633        if (netns >= 0)
 634                close(netns);
 635        return ret;
 636
 637}
 638
 639int netns_identify_pid(const char *pidstr, char *name, int len)
 640{
 641        char net_path[PATH_MAX];
 642        int netns = -1, ret = -1;
 643        struct stat netst;
 644        DIR *dir;
 645        struct dirent *entry;
 646
 647        name[0] = '\0';
 648
 649        snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
 650        netns = open(net_path, O_RDONLY);
 651        if (netns < 0) {
 652                fprintf(stderr, "Cannot open network namespace: %s\n",
 653                        strerror(errno));
 654                goto out;
 655        }
 656        if (fstat(netns, &netst) < 0) {
 657                fprintf(stderr, "Stat of netns failed: %s\n",
 658                        strerror(errno));
 659                goto out;
 660        }
 661        dir = opendir(NETNS_RUN_DIR);
 662        if (!dir) {
 663                /* Succeed treat a missing directory as an empty directory */
 664                if (errno == ENOENT) {
 665                        ret = 0;
 666                        goto out;
 667                }
 668
 669                fprintf(stderr, "Failed to open directory %s:%s\n",
 670                        NETNS_RUN_DIR, strerror(errno));
 671                goto out;
 672        }
 673
 674        while ((entry = readdir(dir))) {
 675                char name_path[PATH_MAX];
 676                struct stat st;
 677
 678                if (strcmp(entry->d_name, ".") == 0)
 679                        continue;
 680                if (strcmp(entry->d_name, "..") == 0)
 681                        continue;
 682
 683                snprintf(name_path, sizeof(name_path), "%s/%s", NETNS_RUN_DIR,
 684                        entry->d_name);
 685
 686                if (stat(name_path, &st) != 0)
 687                        continue;
 688
 689                if ((st.st_dev == netst.st_dev) &&
 690                    (st.st_ino == netst.st_ino)) {
 691                        strlcpy(name, entry->d_name, len);
 692                }
 693        }
 694        ret = 0;
 695        closedir(dir);
 696out:
 697        if (netns >= 0)
 698                close(netns);
 699        return ret;
 700
 701}
 702
 703static int netns_identify(int argc, char **argv)
 704{
 705        const char *pidstr;
 706        char name[256];
 707        int rc;
 708
 709        if (argc < 1) {
 710                pidstr = "self";
 711        } else if (argc > 1) {
 712                fprintf(stderr, "extra arguments specified\n");
 713                return -1;
 714        } else {
 715                pidstr = argv[0];
 716                if (!is_pid(pidstr)) {
 717                        fprintf(stderr, "Specified string '%s' is not a pid\n",
 718                                        pidstr);
 719                        return -1;
 720                }
 721        }
 722
 723        rc = netns_identify_pid(pidstr, name, sizeof(name));
 724        if (!rc)
 725                printf("%s\n", name);
 726
 727        return rc;
 728}
 729
 730static int on_netns_del(char *nsname, void *arg)
 731{
 732        char netns_path[PATH_MAX];
 733
 734        snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname);
 735        umount2(netns_path, MNT_DETACH);
 736        if (unlink(netns_path) < 0) {
 737                fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
 738                        netns_path, strerror(errno));
 739                return -1;
 740        }
 741        return 0;
 742}
 743
 744static int netns_delete(int argc, char **argv)
 745{
 746        if (argc < 1 && !do_all) {
 747                fprintf(stderr, "No netns name specified\n");
 748                return -1;
 749        }
 750
 751        if (do_all)
 752                return netns_foreach(on_netns_del, NULL);
 753
 754        return on_netns_del(argv[0], NULL);
 755}
 756
 757static int create_netns_dir(void)
 758{
 759        /* Create the base netns directory if it doesn't exist */
 760        if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
 761                if (errno != EEXIST) {
 762                        fprintf(stderr, "mkdir %s failed: %s\n",
 763                                NETNS_RUN_DIR, strerror(errno));
 764                        return -1;
 765                }
 766        }
 767
 768        return 0;
 769}
 770
 771/* Obtain a FD for the current namespace, so we can reenter it later */
 772static void netns_save(void)
 773{
 774        if (saved_netns != -1)
 775                return;
 776
 777        saved_netns = open("/proc/self/ns/net", O_RDONLY | O_CLOEXEC);
 778        if (saved_netns == -1) {
 779                perror("Cannot open init namespace");
 780                exit(1);
 781        }
 782}
 783
 784static void netns_restore(void)
 785{
 786        if (saved_netns == -1)
 787                return;
 788
 789        if (setns(saved_netns, CLONE_NEWNET)) {
 790                perror("setns");
 791                exit(1);
 792        }
 793
 794        close(saved_netns);
 795        saved_netns = -1;
 796}
 797
 798static int netns_add(int argc, char **argv, bool create)
 799{
 800        /* This function creates a new network namespace and
 801         * a new mount namespace and bind them into a well known
 802         * location in the filesystem based on the name provided.
 803         *
 804         * If create is true, a new namespace will be created,
 805         * otherwise an existing one will be attached to the file.
 806         *
 807         * The mount namespace is created so that any necessary
 808         * userspace tweaks like remounting /sys, or bind mounting
 809         * a new /etc/resolv.conf can be shared between users.
 810         */
 811        char netns_path[PATH_MAX], proc_path[PATH_MAX];
 812        const char *name;
 813        pid_t pid;
 814        int fd;
 815        int lock;
 816        int made_netns_run_dir_mount = 0;
 817
 818        if (create) {
 819                if (argc < 1) {
 820                        fprintf(stderr, "No netns name specified\n");
 821                        return -1;
 822                }
 823        } else {
 824                if (argc < 2) {
 825                        fprintf(stderr, "No netns name and PID specified\n");
 826                        return -1;
 827                }
 828
 829                if (get_s32(&pid, argv[1], 0) || !pid) {
 830                        fprintf(stderr, "Invalid PID: %s\n", argv[1]);
 831                        return -1;
 832                }
 833        }
 834        name = argv[0];
 835
 836        snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
 837
 838        if (create_netns_dir())
 839                return -1;
 840
 841        /* Make it possible for network namespace mounts to propagate between
 842         * mount namespaces.  This makes it likely that a unmounting a network
 843         * namespace file in one namespace will unmount the network namespace
 844         * file in all namespaces allowing the network namespace to be freed
 845         * sooner.
 846         * These setup steps need to happen only once, as if multiple ip processes
 847         * try to attempt the same operation at the same time, the mountpoints will
 848         * be recursively created multiple times, eventually causing the system
 849         * to lock up. For example, this has been observed when multiple netns
 850         * namespaces are created in parallel at boot. See:
 851         * https://bugs.debian.org/949235
 852         * Try to take an exclusive file lock on the top level directory to ensure
 853         * this cannot happen, but proceed nonetheless if it cannot happen for any
 854         * reason.
 855         */
 856        lock = open(NETNS_RUN_DIR, O_RDONLY|O_DIRECTORY, 0);
 857        if (lock < 0) {
 858                fprintf(stderr, "Cannot open netns runtime directory \"%s\": %s\n",
 859                        NETNS_RUN_DIR, strerror(errno));
 860                return -1;
 861        }
 862        if (flock(lock, LOCK_EX) < 0) {
 863                fprintf(stderr, "Warning: could not flock netns runtime directory \"%s\": %s\n",
 864                        NETNS_RUN_DIR, strerror(errno));
 865                close(lock);
 866                lock = -1;
 867        }
 868        while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
 869                /* Fail unless we need to make the mount point */
 870                if (errno != EINVAL || made_netns_run_dir_mount) {
 871                        fprintf(stderr, "mount --make-shared %s failed: %s\n",
 872                                NETNS_RUN_DIR, strerror(errno));
 873                        if (lock != -1) {
 874                                flock(lock, LOCK_UN);
 875                                close(lock);
 876                        }
 877                        return -1;
 878                }
 879
 880                /* Upgrade NETNS_RUN_DIR to a mount point */
 881                if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND | MS_REC, NULL)) {
 882                        fprintf(stderr, "mount --bind %s %s failed: %s\n",
 883                                NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
 884                        if (lock != -1) {
 885                                flock(lock, LOCK_UN);
 886                                close(lock);
 887                        }
 888                        return -1;
 889                }
 890                made_netns_run_dir_mount = 1;
 891        }
 892        if (lock != -1) {
 893                flock(lock, LOCK_UN);
 894                close(lock);
 895        }
 896
 897        /* Create the filesystem state */
 898        fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
 899        if (fd < 0) {
 900                fprintf(stderr, "Cannot create namespace file \"%s\": %s\n",
 901                        netns_path, strerror(errno));
 902                return -1;
 903        }
 904        close(fd);
 905
 906        if (create) {
 907                netns_save();
 908                if (unshare(CLONE_NEWNET) < 0) {
 909                        fprintf(stderr, "Failed to create a new network namespace \"%s\": %s\n",
 910                                name, strerror(errno));
 911                        goto out_delete;
 912                }
 913
 914                strcpy(proc_path, "/proc/self/ns/net");
 915        } else {
 916                snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/net", pid);
 917        }
 918
 919        /* Bind the netns last so I can watch for it */
 920        if (mount(proc_path, netns_path, "none", MS_BIND, NULL) < 0) {
 921                fprintf(stderr, "Bind %s -> %s failed: %s\n",
 922                        proc_path, netns_path, strerror(errno));
 923                goto out_delete;
 924        }
 925        netns_restore();
 926
 927        return 0;
 928out_delete:
 929        if (create) {
 930                netns_restore();
 931                netns_delete(argc, argv);
 932        } else if (unlink(netns_path) < 0) {
 933                fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
 934                        netns_path, strerror(errno));
 935        }
 936        return -1;
 937}
 938
 939int set_netnsid_from_name(const char *name, int nsid)
 940{
 941        struct {
 942                struct nlmsghdr n;
 943                struct rtgenmsg g;
 944                char            buf[1024];
 945        } req = {
 946                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
 947                .n.nlmsg_flags = NLM_F_REQUEST,
 948                .n.nlmsg_type = RTM_NEWNSID,
 949                .g.rtgen_family = AF_UNSPEC,
 950        };
 951        int fd, err = 0;
 952
 953        netns_nsid_socket_init();
 954
 955        fd = netns_get_fd(name);
 956        if (fd < 0)
 957                return fd;
 958
 959        addattr32(&req.n, 1024, NETNSA_FD, fd);
 960        addattr32(&req.n, 1024, NETNSA_NSID, nsid);
 961        if (rtnl_talk(&rth, &req.n, NULL) < 0)
 962                err = -2;
 963
 964        close(fd);
 965        return err;
 966}
 967
 968static int netns_set(int argc, char **argv)
 969{
 970        char netns_path[PATH_MAX];
 971        const char *name;
 972        int netns, nsid;
 973
 974        if (argc < 1) {
 975                fprintf(stderr, "No netns name specified\n");
 976                return -1;
 977        }
 978        if (argc < 2) {
 979                fprintf(stderr, "No nsid specified\n");
 980                return -1;
 981        }
 982        name = argv[0];
 983        /* If a negative nsid is specified the kernel will select the nsid. */
 984        if (strcmp(argv[1], "auto") == 0)
 985                nsid = -1;
 986        else if (get_integer(&nsid, argv[1], 0))
 987                invarg("Invalid \"netnsid\" value", argv[1]);
 988        else if (nsid < 0)
 989                invarg("\"netnsid\" value should be >= 0", argv[1]);
 990
 991        snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
 992        netns = open(netns_path, O_RDONLY | O_CLOEXEC);
 993        if (netns < 0) {
 994                fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
 995                        name, strerror(errno));
 996                return -1;
 997        }
 998
 999        return set_netnsid_from_name(name, nsid);
1000}
1001
1002static int netns_monitor(int argc, char **argv)
1003{
1004        char buf[4096];
1005        struct inotify_event *event;
1006        int fd;
1007
1008        fd = inotify_init();
1009        if (fd < 0) {
1010                fprintf(stderr, "inotify_init failed: %s\n",
1011                        strerror(errno));
1012                return -1;
1013        }
1014
1015        if (create_netns_dir())
1016                return -1;
1017
1018        if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
1019                fprintf(stderr, "inotify_add_watch failed: %s\n",
1020                        strerror(errno));
1021                return -1;
1022        }
1023        for (;;) {
1024                ssize_t len = read(fd, buf, sizeof(buf));
1025
1026                if (len < 0) {
1027                        fprintf(stderr, "read failed: %s\n",
1028                                strerror(errno));
1029                        return -1;
1030                }
1031                for (event = (struct inotify_event *)buf;
1032                     (char *)event < &buf[len];
1033                     event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) {
1034                        if (event->mask & IN_CREATE)
1035                                printf("add %s\n", event->name);
1036                        if (event->mask & IN_DELETE)
1037                                printf("delete %s\n", event->name);
1038                }
1039        }
1040        return 0;
1041}
1042
1043static int invalid_name(const char *name)
1044{
1045        return !*name || strlen(name) > NAME_MAX ||
1046                strchr(name, '/') || !strcmp(name, ".") || !strcmp(name, "..");
1047}
1048
1049int do_netns(int argc, char **argv)
1050{
1051        netns_nsid_socket_init();
1052
1053        if (argc < 1) {
1054                netns_map_init();
1055                return netns_list(0, NULL);
1056        }
1057
1058        if (!do_all && argc > 1 && invalid_name(argv[1])) {
1059                fprintf(stderr, "Invalid netns name \"%s\"\n", argv[1]);
1060                exit(-1);
1061        }
1062
1063        if ((matches(*argv, "list") == 0) || (matches(*argv, "show") == 0) ||
1064            (matches(*argv, "lst") == 0)) {
1065                netns_map_init();
1066                return netns_list(argc-1, argv+1);
1067        }
1068
1069        if ((matches(*argv, "list-id") == 0)) {
1070                netns_map_init();
1071                return netns_list_id(argc-1, argv+1);
1072        }
1073
1074        if (matches(*argv, "help") == 0)
1075                return usage();
1076
1077        if (matches(*argv, "add") == 0)
1078                return netns_add(argc-1, argv+1, true);
1079
1080        if (matches(*argv, "set") == 0)
1081                return netns_set(argc-1, argv+1);
1082
1083        if (matches(*argv, "delete") == 0)
1084                return netns_delete(argc-1, argv+1);
1085
1086        if (matches(*argv, "identify") == 0)
1087                return netns_identify(argc-1, argv+1);
1088
1089        if (matches(*argv, "pids") == 0)
1090                return netns_pids(argc-1, argv+1);
1091
1092        if (matches(*argv, "exec") == 0)
1093                return netns_exec(argc-1, argv+1);
1094
1095        if (matches(*argv, "monitor") == 0)
1096                return netns_monitor(argc-1, argv+1);
1097
1098        if (matches(*argv, "attach") == 0)
1099                return netns_add(argc-1, argv+1, false);
1100
1101        fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv);
1102        exit(-1);
1103}
1104