]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: socket operations stick to namespace if necessary
authorPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 8 Dec 2017 18:06:34 +0000 (19:06 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 27 Feb 2018 10:11:24 +0000 (11:11 +0100)
Upon following calls: interface poll, address poll, route poll, and
ICMPv6 handling, each new Namespace is being parsed. For that, the
socket operations need to switch from one NS to one other, to get the
necessary information.

As of now, there is a crash when dumping interfaces, through show
running-config.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
lib/ns.c
lib/vrf.c
zebra/if_netlink.c
zebra/interface.c
zebra/kernel_netlink.c
zebra/kernel_socket.c
zebra/rtadv.c

index fcac28cf7e06754be42c82d83eb3926d5b07351a..170290a9e9e267062d6177e8dcf4ab5d9c5b9bee 100644 (file)
--- a/lib/ns.c
+++ b/lib/ns.c
@@ -565,9 +565,9 @@ void ns_terminate(void)
 int ns_socket(int domain, int type, int protocol, ns_id_t ns_id)
 {
        struct ns *ns = ns_lookup(ns_id);
-       int ret = -1;
+       int ret;
 
-       if (!ns_is_enabled(ns)) {
+       if (!ns || !ns_is_enabled(ns)) {
                errno = ENOSYS;
                return -1;
        }
index 56c8bdbabefade0386131a170976a6cd9ca0a513..81ff6d56fda9f1f72e2e2c1054b01837b5a2b2e8 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -97,7 +97,8 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
        int new = 0;
 
        if (debug_vrf)
-               zlog_debug("VRF_GET: %s(%u)", name, vrf_id);
+               zlog_debug("VRF_GET: %s(%u)",
+                          name == NULL ? "(NULL)" : name, vrf_id);
 
        /* Nothing to see, move along here */
        if (!name && vrf_id == VRF_UNKNOWN)
index ef30c7830f5f1fc2dcd083a23334226c7f714244..6897bd4ee21e65ad1b84893172996508ac3fd998 100644 (file)
@@ -792,8 +792,12 @@ static int netlink_address(int cmd, int family, struct interface *ifp,
                char buf[NL_PKT_BUF_SIZE];
        } req;
 
-       struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+       struct zebra_ns *zns;
 
+       if (vrf_is_backend_netns())
+               zns = zebra_ns_lookup((ns_id_t)ifp->vrf_id);
+       else
+               zns = zebra_ns_lookup(NS_DEFAULT);
        p = ifc->address;
        memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
 
@@ -1020,6 +1024,7 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
        zns = zebra_ns_lookup(ns_id);
        ifi = NLMSG_DATA(h);
 
+       /* assume if not default zns, then new VRF */
        if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) {
                /* If this is not link add/delete message so print warning. */
                zlog_warn("netlink_link_change: wrong kernel message %d",
@@ -1107,7 +1112,8 @@ int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
                        } else
                                zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
                }
-
+               if (vrf_is_backend_netns())
+                       vrf_id = (vrf_id_t)ns_id;
                if (ifp == NULL
                    || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
                        /* Add interface notification from kernel */
index 07570e64bfc2c32f5d045aee3396cd587fdd8a43..6ee1db6a4c36882c80dbafae35365965e1df57b8 100644 (file)
@@ -512,8 +512,13 @@ static void if_addr_wakeup(struct interface *ifp)
 void if_add_update(struct interface *ifp)
 {
        struct zebra_if *if_data;
+       struct zebra_ns *zns;
 
-       if_link_per_ns(zebra_ns_lookup(NS_DEFAULT), ifp);
+       if (vrf_is_backend_netns())
+               zns = zebra_ns_lookup((ns_id_t)ifp->vrf_id);
+       else
+               zns = zebra_ns_lookup(NS_DEFAULT);
+       if_link_per_ns(zns, ifp);
 
        if_data = ifp->info;
        assert(if_data);
index 1be2cbcaf54ea27b974cacfee3a58f9cb9a2bd5b..0b3b6eed45761b5db16ce36e597f6187ba5d0978 100644 (file)
@@ -188,7 +188,7 @@ static int netlink_socket(struct nlsock *nl, unsigned long groups,
                return -1;
        }
 
-       sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+       sock = ns_socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, ns_id);
        if (sock < 0) {
                zlog_err("Can't open %s socket: %s", nl->name,
                         safe_strerror(errno));
index 4d888d80695ceb576a912c76dfc2e3d45f7a263a..3b28a9b2426a2d23ee838092f333e98e99a34415 100644 (file)
@@ -1384,7 +1384,8 @@ static void routing_socket(struct zebra_ns *zns)
        if (zserv_privs.change(ZPRIVS_RAISE))
                zlog_err("routing_socket: Can't raise privileges");
 
-       routing_sock = socket(AF_ROUTE, SOCK_RAW, 0);
+       routing_sock = ns_socket(AF_ROUTE, SOCK_RAW,
+                                0, (ns_id_t)zns->ns->ns_id);
 
        if (routing_sock < 0) {
                if (zserv_privs.change(ZPRIVS_LOWER))
index 32418eb82fb45498d90d16505209135e1929bc39..860e8710d6899bff1d890c918a19f4b3dba79a7b 100644 (file)
@@ -34,6 +34,7 @@
 #include "command.h"
 #include "privs.h"
 #include "vrf.h"
+#include "ns.h"
 
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
@@ -621,7 +622,7 @@ static int rtadv_read(struct thread *thread)
        return 0;
 }
 
-static int rtadv_make_socket(void)
+static int rtadv_make_socket(ns_id_t ns_id)
 {
        int sock;
        int ret = 0;
@@ -631,7 +632,7 @@ static int rtadv_make_socket(void)
                zlog_err("rtadv_make_socket: could not raise privs, %s",
                         safe_strerror(errno));
 
-       sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+       sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
 
        if (zserv_privs.change(ZPRIVS_LOWER))
                zlog_err("rtadv_make_socket: could not lower privs, %s",
@@ -1686,7 +1687,7 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
 
 void rtadv_init(struct zebra_ns *zns)
 {
-       zns->rtadv.sock = rtadv_make_socket();
+       zns->rtadv.sock = rtadv_make_socket(zns->ns_id);
 }
 
 void rtadv_terminate(struct zebra_ns *zns)