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)
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) {
}
/* 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;
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;
}
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)
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;
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;
}
/* 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,
/* 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",