From: Philippe Guibert Date: Mon, 5 Feb 2018 16:28:51 +0000 (+0100) Subject: lib: add vrf-lite bind capability to vrf APIs X-Git-Tag: frr-5.0-dev~209^2~7 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=0f4977c6689441e7b3075fc7a82c1ddc9ffdfa1c;p=mirror%2Ffrr.git lib: add vrf-lite bind capability to vrf APIs 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 --- diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 59c59f924e..240a23d198 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -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) { diff --git a/lib/vrf.c b/lib/vrf.c index 890a7adca2..ea106b90a2 100644 --- 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; } diff --git a/lib/vrf.h b/lib/vrf.h index cb4159a0a3..062e6f3d8d 100644 --- 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, diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 65f1e56587..639f70a6b4 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -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",