]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add vrf-lite bind capability to vrf APIs
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 5 Feb 2018 16:28:51 +0000 (17:28 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 27 Feb 2018 10:11:24 +0000 (11:11 +0100)
Because socket creation is tightly linked with socket binding for vrf
lite, the proposal is made to extend socket creation APIs and to create
a new API called vrf_bind that applies to vrf lite. The passed interface
name is the interface that will be bound to the socket passed.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_network.c
lib/vrf.c
lib/vrf.h
zebra/if_netlink.c

index 59c59f924eeb464d1d8ea608d62bb5c7d1b9b80a..240a23d198c838d53011ee6c32b16570ce1e4e69 100644 (file)
@@ -571,7 +571,7 @@ int bgp_connect(struct peer *peer)
        if (bgpd_privs.change(ZPRIVS_RAISE))
                zlog_err("Can't raise privileges");
        /* Make socket for the peer. */
-       peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id);
+       peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id, NULL);
        if (bgpd_privs.change(ZPRIVS_LOWER))
                zlog_err("Can't lower privileges");
        if (peer->fd < 0)
@@ -751,7 +751,7 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
                if (bgpd_privs.change(ZPRIVS_RAISE))
                        zlog_err("Can't raise privileges");
                sock = vrf_socket(ainfo->ai_family, ainfo->ai_socktype,
-                                 ainfo->ai_protocol, bgp->vrf_id);
+                                 ainfo->ai_protocol, bgp->vrf_id, NULL);
                if (bgpd_privs.change(ZPRIVS_LOWER))
                        zlog_err("Can't lower privileges");
                if (sock < 0) {
index 890a7adca2099fc43d560548e68457ec75bcd393..ea106b90a207570e5f48d8622f4a1e8ef26aef43 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -493,7 +493,8 @@ void vrf_terminate(void)
 }
 
 /* Create a socket for the VRF. */
-int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id)
+int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
+              char *interfacename)
 {
        int ret, save_errno, ret2;
 
@@ -508,6 +509,13 @@ int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id)
                zlog_err("%s: Can't switchback from VRF %u (%s)",
                         __func__, vrf_id, safe_strerror(errno));
        errno = save_errno;
+       if (ret <= 0)
+               return ret;
+       ret2 = vrf_bind(vrf_id, ret, interfacename);
+       if (ret2 < 0) {
+               close(ret);
+               ret = ret2;
+       }
        return ret;
 }
 
@@ -795,6 +803,23 @@ vrf_id_t vrf_get_default_id(void)
                return VRF_DEFAULT_INTERNAL;
 }
 
+int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
+{
+       int ret = 0;
+
+       if (fd < 0 || name == NULL)
+               return fd;
+       if (vrf_is_mapped_on_netns(vrf_id))
+               return fd;
+#ifdef SO_BINDTODEVICE
+       ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name,
+                        strlen(name));
+       if (ret < 0)
+               zlog_debug("bind to interface %s failed, errno=%d",
+                          name, errno);
+#endif /* SO_BINDTODEVICE */
+       return ret;
+}
 int vrf_getaddrinfo(const char *node, const char *service,
                    const struct addrinfo *hints,
                    struct addrinfo **res, vrf_id_t vrf_id)
@@ -835,7 +860,8 @@ int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
        return rc;
 }
 
-int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id)
+int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
+                        char *interfacename)
 {
        int ret, save_errno, ret2;
 
@@ -850,5 +876,13 @@ int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id)
                zlog_err("%s: Can't switchback from VRF %u (%s)",
                         __func__, vrf_id, safe_strerror(errno));
        errno = save_errno;
+
+       if (ret <= 0)
+               return ret;
+       ret2 = vrf_bind(vrf_id, ret, interfacename);
+       if (ret2 < 0) {
+               close(ret);
+               ret = ret2;
+       }
        return ret;
 }
index cb4159a0a3a6ff9229fe35e8a098d79ef6bfdba9..062e6f3d8df1c656f5a4949c73f4369110692e22 100644 (file)
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -207,9 +207,13 @@ extern void vrf_terminate(void);
 
 /* Create a socket serving for the given VRF */
 extern int vrf_socket(int domain, int type,
-                     int protocol, vrf_id_t vrf_id);
+                     int protocol, vrf_id_t vrf_id,
+                     char *name);
+
 extern int vrf_sockunion_socket(const union sockunion *su,
-                               vrf_id_t vrf_id);
+                               vrf_id_t vrf_id, char *name);
+
+extern int vrf_bind(vrf_id_t vrf_id, int fd, char *name);
 
 /* VRF ioctl operations */
 extern int vrf_getaddrinfo(const char *node, const char *service,
index 65f1e56587dd3cf776ea5a7b64465af848ad1c2b..639f70a6b4c3d7c9776be3991d968e7ffafe7612 100644 (file)
@@ -367,7 +367,8 @@ static int get_iflink_speed(struct interface *interface)
        /* use ioctl to get IP address of an interface */
        if (zserv_privs.change(ZPRIVS_RAISE))
                zlog_err("Can't raise privileges");
-       sd = vrf_socket(PF_INET, SOCK_DGRAM, IPPROTO_IP, interface->vrf_id);
+       sd = vrf_socket(PF_INET, SOCK_DGRAM, IPPROTO_IP,
+                       interface->vrf_id, NULL);
        if (sd < 0) {
                if (IS_ZEBRA_DEBUG_KERNEL)
                        zlog_debug("Failure to read interface %s speed: %d %s",