From patchwork Fri Oct 11 08:01:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiao Liang X-Patchwork-Id: 13832217 X-Patchwork-Delegate: stephen@networkplumber.org Received: from mail-pf1-f169.google.com (mail-pf1-f169.google.com [209.85.210.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC25920A5FA for ; Fri, 11 Oct 2024 08:01:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728633695; cv=none; b=AZZo7y64HxXSR8upCqHKT3EAIdId5p4f73U8jHnO2+DG3mktoeRKUPSpaMJxz2jkP9MRPdchP3n98o/c+fCDgcseLmuVnVm8V4xLEC/SNPeGuDfBJ6SCNYdHtdjCGotY9EYHqMJlhAbSr6eAXpbrPREl+9o6fQ4GDq1oy298xVg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728633695; c=relaxed/simple; bh=bQ1U7FMoKyxmOaJGDLz2OydB7yXq3H1wx77FlrNphK4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bgYs8pVZ44CGMQzkUyTzjam3jGoa5haQA4J+EKKoZ0u0eoZBTn4T4/nI3fR5OIjIqfRZs2yEb0NQThrF/GqtLRD+dwMfF9bfJ7GKdM4XPtZ6Bstqx9Av2BhjAKRZ1z3xpmr8vOmcCj3pALdGCIJAy9H1sRVcIQ9svSX5g1vRHxY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Tm+WuRfd; arc=none smtp.client-ip=209.85.210.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Tm+WuRfd" Received: by mail-pf1-f169.google.com with SMTP id d2e1a72fcca58-71df67c67fcso1343176b3a.2 for ; Fri, 11 Oct 2024 01:01:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728633693; x=1729238493; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=2Zx1nxBtgn7NWS2XbEDdXzhu+nkPhEjrFTGR71Ez+rc=; b=Tm+WuRfdl2sKCoWq+9gapmEcyBM7sa7PP+CcPg0a/fZB4k0rqn5zwIuwxCaF1Wn2g5 dyJy1LzsY3bVQmikJOAExp0xaeIFrvylJaTdomnXlHAjZUTxza7nTv+eOy4FBYWAdmfv Sv1wDty7q/YCuE0mUlnxXjozmajMbhg4FPVzJlkAzs4eGSgtG0lxloLgSplSPi/PCOZV 9QVXaUaJ5GRXGGu/iiCsSSmBhaKFjcGrm7NdDUQAYWsYDsOspsbKouZEL7lkXGXbq7p5 kK6q/8vccatL+Tqv/2JR49DPJCTzF8JyYOqmoFFOrcu10PWfG8E7fdg/EGvK++kMVXbx 2ToA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728633693; x=1729238493; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2Zx1nxBtgn7NWS2XbEDdXzhu+nkPhEjrFTGR71Ez+rc=; b=YbLTS/kAImJh7g9TNuCQkP01nDtyo0QM2lNeqcq1Rzm/YMVJACnJc4qp6FcNopEAZq yO0KjFDdvQQgX+Rik6I63qo4eKkKQq3k3I24HL85bFVm8KmLOqWx9g8s06Hlr3HklpN4 I2wA/+OZrVcs+ZXoGad8Kh7XW13zJrPrLHWIgRsMbP++0nswOgrrXqu5KOO+AID7RcZ/ kVkvhod4dzEaeWIzWZ77w8yP3oNGQc7XcFbHf0V/cbMfdLBSYbYqM3HprvCdXVcheqyq LReL1IY2F3dB4jeUlCYCjonSpX4ZS2X8UP0d5dNnlfRK2j/VhnqZkN2ccTe/wXxJOxw9 W/kg== X-Forwarded-Encrypted: i=1; AJvYcCVHn9LYb2bQbb1FJ00GUxEN/ZLcyZ3sK2FKG3hnu7dhRj2/vfl4IonhLQVnVSjXr8VP6txxhts=@vger.kernel.org X-Gm-Message-State: AOJu0Yxk5TKdZdqYX9xGOSobfu+DuZQwHZ8ZRIEe9Yto0b/cdbNKkE6K lOtO57oYMqG9MFYV91ZrU9y1n+DSSvbfzwButuzPiU09HIMbXIT2t2GM+rD5 X-Google-Smtp-Source: AGHT+IF6dFfvNw34oWaXPkKw0M69dpFXzdSf540hMIVa1G8Q/RRVOBmuyNE53l1r+8k62Z4/npO3Gw== X-Received: by 2002:a05:6a00:3d14:b0:71d:f15e:d023 with SMTP id d2e1a72fcca58-71e37e52e22mr3158014b3a.11.1728633692887; Fri, 11 Oct 2024 01:01:32 -0700 (PDT) Received: from nova-ws.. ([103.167.140.11]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71e2ab0b5dfsm2126908b3a.199.2024.10.11.01.01.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Oct 2024 01:01:32 -0700 (PDT) From: Xiao Liang To: Stephen Hemminger , netdev@vger.kernel.org Subject: [PATCH v2 iproute2 1/2] ip: Move of set_netnsid_from_name() to namespace.c Date: Fri, 11 Oct 2024 16:01:08 +0800 Message-ID: <20241011080111.387028-2-shaw.leon@gmail.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241011080111.387028-1-shaw.leon@gmail.com> References: <20241011080111.387028-1-shaw.leon@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: dsahern@gmail.com Move set_netnsid_from_name() outside for reuse, like what's done for netns_id_from_name(). Signed-off-by: Xiao Liang --- include/namespace.h | 2 ++ ip/ip_common.h | 2 -- ip/iplink.c | 6 +++--- ip/ipnetns.c | 28 +++------------------------- lib/namespace.c | 27 +++++++++++++++++++++++++++ 5 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/namespace.h b/include/namespace.h index 86000543..98f4af59 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -60,6 +60,8 @@ struct netns_func { }; int netns_id_from_name(struct rtnl_handle *rtnl, const char *name); +int set_netns_id_from_name(struct rtnl_handle *rtnl, const char *name, + int nsid); char *netns_name_from_id(int32_t id); #endif /* __NAMESPACE_H__ */ diff --git a/ip/ip_common.h b/ip/ip_common.h index 625311c2..726262ab 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -63,8 +63,6 @@ void netns_nsid_socket_init(void); int print_nsid(struct nlmsghdr *n, void *arg); int ipstats_print(struct nlmsghdr *n, void *arg); char *get_name_from_nsid(int nsid); -int get_netnsid_from_name(const char *name); -int set_netnsid_from_name(const char *name, int nsid); int do_ipaddr(int argc, char **argv); int do_ipaddrlabel(int argc, char **argv); int do_iproute(int argc, char **argv); diff --git a/ip/iplink.c b/ip/iplink.c index 0dd83ff4..c9168985 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -819,11 +819,11 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) NEXT_ARG(); if (link_netnsid != -1) duparg("link-netns/link-netnsid", *argv); - link_netnsid = get_netnsid_from_name(*argv); + link_netnsid = netns_id_from_name(&rth, *argv); /* No nsid? Try to assign one. */ if (link_netnsid < 0) - set_netnsid_from_name(*argv, -1); - link_netnsid = get_netnsid_from_name(*argv); + set_netns_id_from_name(&rth, *argv, -1); + link_netnsid = netns_id_from_name(&rth, *argv); if (link_netnsid < 0) invarg("Invalid \"link-netns\" value\n", *argv); diff --git a/ip/ipnetns.c b/ip/ipnetns.c index 972d7e9c..5c943400 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -104,7 +104,7 @@ static int ipnetns_have_nsid(void) return have_rtnl_getnsid; } -int get_netnsid_from_name(const char *name) +static int get_netnsid_from_name(const char *name) { netns_nsid_socket_init(); @@ -896,33 +896,11 @@ out_delete: return -1; } -int set_netnsid_from_name(const char *name, int nsid) +static int set_netnsid_from_name(const char *name, int nsid) { - struct { - struct nlmsghdr n; - struct rtgenmsg g; - char buf[1024]; - } req = { - .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), - .n.nlmsg_flags = NLM_F_REQUEST, - .n.nlmsg_type = RTM_NEWNSID, - .g.rtgen_family = AF_UNSPEC, - }; - int fd, err = 0; - netns_nsid_socket_init(); - fd = netns_get_fd(name); - if (fd < 0) - return fd; - - addattr32(&req.n, 1024, NETNSA_FD, fd); - addattr32(&req.n, 1024, NETNSA_NSID, nsid); - if (rtnl_talk(&rth, &req.n, NULL) < 0) - err = -2; - - close(fd); - return err; + return set_netns_id_from_name(&rth, name, nsid); } static int netns_set(int argc, char **argv) diff --git a/lib/namespace.c b/lib/namespace.c index d3aeb965..74b7e7ca 100644 --- a/lib/namespace.c +++ b/lib/namespace.c @@ -189,6 +189,33 @@ out: return ret; } +int set_netns_id_from_name(struct rtnl_handle *rtnl, const char *name, int nsid) +{ + struct { + struct nlmsghdr n; + struct rtgenmsg g; + char buf[1024]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_NEWNSID, + .g.rtgen_family = AF_UNSPEC, + }; + int fd, err = 0; + + fd = netns_get_fd(name); + if (fd < 0) + return fd; + + addattr32(&req.n, 1024, NETNSA_FD, fd); + addattr32(&req.n, 1024, NETNSA_NSID, nsid); + if (rtnl_talk(rtnl, &req.n, NULL) < 0) + err = -2; + + close(fd); + return err; +} + struct netns_name_from_id_ctx { int32_t id; char *name; From patchwork Fri Oct 11 08:01:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiao Liang X-Patchwork-Id: 13832218 X-Patchwork-Delegate: stephen@networkplumber.org Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 15AF320ADDE for ; Fri, 11 Oct 2024 08:01:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728633697; cv=none; b=H9XeRIug+kxla8CwSlyga7wXsijazHQcqndB492reiGHgOETJE4xdYxyXCgioi8ExoHXkcDbcwK7yAoJnJOgkjpOGyyy6q5Jw4z0/rTsI+6WjpKu1hb1k4wPoIS6fxjeu7FUECoj/y8s1Fgux2l99VjR7ynNEaoi8H/Ju56ZK9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728633697; c=relaxed/simple; bh=hZc4iccOeziC/FK/ZUoE+bwy6dTziB8ALPcnuzBpoII=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J1sUxPng7n4dqit3nxaDKGltsSuPv3OrZlxkkoFM94/KN+MRzxDcxb901isAmptloN9IemtXHasUtFh/eBOZVwsg5qIMLbD8NdzSqPKc1cwt3t385VQ22os68CFHWKI/ABMKtR7zGDRjlM4FE3jfHbD4Nt0eQz4S5t/uxaCvnt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TQB/cZ3M; arc=none smtp.client-ip=209.85.215.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TQB/cZ3M" Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-7ea0ff74b15so1098289a12.3 for ; Fri, 11 Oct 2024 01:01:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728633695; x=1729238495; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=6dxktlx5j7SK3d83gJf5bzIo9DXB971U8e6n2fUHqnc=; b=TQB/cZ3MshwUpyl18DeyI6bT3EDNmFLyv/nZvEPBCZHBARWA7alHVcNpvdVz3nwLyY /h18av2cOFS8lZsLQaCbwRuWos+VlG7b9Ibzys29SdUo95dURyNoqi2gab+Yx/s7UaVX 1YiSK7+85/paicIB64USAv5C5jVboOMnDR8AAT4RGPq6Jlp/w4CivRp8pM1gnInLWJ+A bEpnQtPZZfwIUeO1KYk2h9IeyKmkL7xsI67NBACYkNrHeJ8VEu26tyUd+QdzOhfQsuDY CaR3YpmK6j8E8xJkTuMLuBAwuHmZOiOSuWMSVCnqwbxDLX1VYszAj83UkzeFLWHJ+wKE ySpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728633695; x=1729238495; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6dxktlx5j7SK3d83gJf5bzIo9DXB971U8e6n2fUHqnc=; b=fkCj/GBPxLkPxo35kaBJ8lA+Wcn+Yv3F7FwFtNk+ttoocmE4DSpEELQBa5TA0gcMLK 8G1AdlMtR9ZOzt0+A2rMYqKT5MB+X7Tr2xs3ArwpIf2pDRK+8IIC+kI/nHOdImXMRXgV DkihkirV7sTu12U0ipIzdwW81DauxUM2h5YcqVH+kx7+FsinvXMiXtlm2rEDsUtNNheY VtDCdHuUgydL9n/Lr/yOuJJIO3ohbqEflaUhIZdDSuW4aH83nNVKJvhr3yfK/Pp/x3J1 uy51EdrHTXH4KSK8ZSrSGioWgpkKgUDnU6VG/ylN2QUl05J+yenG/2NVSUDSiu0gtItH Cd/w== X-Forwarded-Encrypted: i=1; AJvYcCW0B/7cMSKAJj3kimsIc8Dk+XXzXUz7Kva+F5lZQ8shQItRb60MMiCC4peFPyItm1wUwwRmwCQ=@vger.kernel.org X-Gm-Message-State: AOJu0YzV/d8akWXy1DZTrHMLb/UrY+YMmK2ZaDdR+yaC7vj5svtvov3x jDF4cRKfacq1FOlZyAYH8j9JET4EfRvJ9FOIw/N475G6O1/YiaQH1GErfxVZ X-Google-Smtp-Source: AGHT+IEkulzpPzACP8URla5leVU+Sn/xTzZjKdw+MtO5k6B0mBO3NSZhSUy8J+RHezKHkVyTNjNtAg== X-Received: by 2002:a05:6a21:118a:b0:1d8:a13d:d6b4 with SMTP id adf61e73a8af0-1d8bcf06da2mr2525108637.4.1728633695135; Fri, 11 Oct 2024 01:01:35 -0700 (PDT) Received: from nova-ws.. ([103.167.140.11]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71e2ab0b5dfsm2126908b3a.199.2024.10.11.01.01.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Oct 2024 01:01:34 -0700 (PDT) From: Xiao Liang To: Stephen Hemminger , netdev@vger.kernel.org Subject: [PATCH v2 iproute2 2/2] iplink: Fix link-netns id and link ifindex Date: Fri, 11 Oct 2024 16:01:09 +0800 Message-ID: <20241011080111.387028-3-shaw.leon@gmail.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241011080111.387028-1-shaw.leon@gmail.com> References: <20241011080111.387028-1-shaw.leon@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: dsahern@gmail.com When link-netns or link-netnsid is supplied, lookup link in that netns. And if both netns and link-netns are given, IFLA_LINK_NETNSID should be the nsid of link-netns from the view of target netns, not from current one. For example, when handling: # ip -n ns1 link add netns ns2 link-netns ns3 link eth1 eth1.100 type vlan id 100 should lookup eth1 in ns3 and IFLA_LINK_NETNSID is the id of ns3 from ns2. Signed-off-by: Xiao Liang Acked-by: Nicolas Dichtel --- ip/iplink.c | 143 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 25 deletions(-) diff --git a/ip/iplink.c b/ip/iplink.c index c9168985..c2c0e371 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -240,6 +240,38 @@ static int nl_get_ll_addr_len(const char *ifname) return len; } +static int get_ifindex_in_netns(struct rtnl_handle *rtnl, int netnsid, + const char *ifname) +{ + struct { + struct nlmsghdr n; + struct ifinfomsg ifm; + char buf[1024]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_GETLINK, + }; + struct nlmsghdr *answer; + int ifindex; + + addattr32(&req.n, sizeof(req), IFLA_TARGET_NETNSID, netnsid); + addattr_l(&req.n, sizeof(req), + !check_ifname(ifname) ? IFLA_IFNAME : IFLA_ALT_IFNAME, + ifname, strlen(ifname) + 1); + + if (rtnl_talk(rtnl, &req.n, &answer) < 0) + return 0; + + if (answer->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) { + free(answer); + return 0; + } + ifindex = ((struct ifinfomsg *)NLMSG_DATA(answer))->ifi_index; + free(answer); + return ifindex; +} + static void iplink_parse_vf_vlan_info(int vf, int *argcp, char ***argvp, struct ifla_vf_vlan_info *ivvip) { @@ -536,7 +568,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) int vf = -1; int numtxqueues = -1; int numrxqueues = -1; + char *link_netns = NULL; int link_netnsid = -1; + struct rtnl_handle netns_rtnl; + struct rtnl_handle *rtnl = &rth; int index = 0; int group = -1; int addr_len = 0; @@ -618,20 +653,25 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) if (offload && name == dev) dev = NULL; } else if (strcmp(*argv, "netns") == 0) { + int pid; + NEXT_ARG(); if (netns != -1) duparg("netns", *argv); netns = netns_get_fd(*argv); - if (netns >= 0) { - open_fds_add(netns); - addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, - &netns, 4); + if (netns < 0 && get_integer(&pid, *argv, 0) == 0) { + char path[PATH_MAX]; + + snprintf(path, sizeof(path), "/proc/%d/ns/net", + pid); + netns = open(path, O_RDONLY); } - else if (get_integer(&netns, *argv, 0) == 0) - addattr_l(&req->n, sizeof(*req), - IFLA_NET_NS_PID, &netns, 4); - else + if (netns < 0) invarg("Invalid \"netns\" value\n", *argv); + + open_fds_add(netns); + addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, + &netns, 4); move_netns = true; } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); @@ -817,21 +857,12 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) addattr_nest_end(&req->n, afs); } else if (matches(*argv, "link-netns") == 0) { NEXT_ARG(); - if (link_netnsid != -1) + if (link_netnsid != -1 || link_netns) duparg("link-netns/link-netnsid", *argv); - link_netnsid = netns_id_from_name(&rth, *argv); - /* No nsid? Try to assign one. */ - if (link_netnsid < 0) - set_netns_id_from_name(&rth, *argv, -1); - link_netnsid = netns_id_from_name(&rth, *argv); - if (link_netnsid < 0) - invarg("Invalid \"link-netns\" value\n", - *argv); - addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID, - link_netnsid); + link_netns = *argv; } else if (matches(*argv, "link-netnsid") == 0) { NEXT_ARG(); - if (link_netnsid != -1) + if (link_netnsid != -1 || link_netns) duparg("link-netns/link-netnsid", *argv); if (get_integer(&link_netnsid, *argv, 0)) invarg("Invalid \"link-netnsid\" value\n", @@ -983,6 +1014,53 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) } } + if (netns != -1 && (link_netnsid != -1 || link_netns)) { + int orig_netns; + + /* + * When both link-netns and netns are set, open an RTNL in + * target netns, to + * 1) get link-netns id from the view of target netns, and + * 2) get link ifindex from link-netns. + */ + orig_netns = open("/proc/self/ns/net", O_RDONLY); + if (orig_netns == -1) { + fprintf(stderr, "Cannot open namespace: %s\n", + strerror(errno)); + exit(-1); + } + if (setns(netns, CLONE_NEWNET) < 0) { + fprintf(stderr, "Cannot set namespace: %s\n", + strerror(errno)); + exit(-1); + } + if (rtnl_open(&netns_rtnl, 0) < 0) { + fprintf(stderr, "Cannot open rtnetlink\n"); + exit(-1); + } + if (setns(orig_netns, CLONE_NEWNET) < 0) { + fprintf(stderr, "Cannot set namespace: %s\n", + strerror(errno)); + exit(-1); + } + close(orig_netns); + rtnl = &netns_rtnl; + } + + if (link_netns) { + link_netnsid = netns_id_from_name(rtnl, link_netns); + /* No nsid? Try to assign one. */ + if (link_netnsid < 0) { + set_netns_id_from_name(rtnl, link_netns, -1); + link_netnsid = netns_id_from_name(rtnl, link_netns); + } + if (link_netnsid < 0) + invarg("Invalid \"link-netns\" value\n", + *argv); + addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID, + link_netnsid); + } + if (!(req->n.nlmsg_flags & NLM_F_CREATE)) { if (!dev) { fprintf(stderr, @@ -991,8 +1069,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) } req->i.ifi_index = ll_name_to_index(dev); - if (!req->i.ifi_index) - return nodev(dev); + if (!req->i.ifi_index) { + ret = nodev(dev); + goto out; + } /* Not renaming to the same name */ if (name == dev) @@ -1010,9 +1090,17 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) if (link) { int ifindex; - ifindex = ll_name_to_index(link); - if (!ifindex) - return nodev(link); + if (link_netnsid == -1) + ifindex = ll_name_to_index(link); + else + ifindex = get_ifindex_in_netns(rtnl, + link_netnsid, + link); + + if (!ifindex) { + ret = nodev(link); + goto out; + } addattr32(&req->n, sizeof(*req), IFLA_LINK, ifindex); } @@ -1024,6 +1112,11 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) IFLA_IFNAME, name, strlen(name) + 1); } +out: + if (rtnl == &netns_rtnl) { + rtnl_close(rtnl); + } + return ret; }