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