summaryrefslogtreecommitdiff
path: root/lib/vrf.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-02-05 17:28:51 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-02-27 11:11:24 +0100
commit0f4977c6689441e7b3075fc7a82c1ddc9ffdfa1c (patch)
treea4679fd142c21212e652e3253c23bec821fff7b4 /lib/vrf.c
parent516d7591d68cf4537bb7f0603ff703e808381d03 (diff)
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 <philippe.guibert@6wind.com>
Diffstat (limited to 'lib/vrf.c')
-rw-r--r--lib/vrf.c38
1 files changed, 36 insertions, 2 deletions
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;
}