summaryrefslogtreecommitdiff
path: root/src/basic/socket-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-03-18 11:58:11 +0100
committerLennart Poettering <lennart@poettering.net>2019-03-18 12:02:32 +0100
commit5d594d012da06bec9b22cac41ecea7ee77aa972b (patch)
tree8b5fedea80dfe490003e4d0592ddf9f97857727f /src/basic/socket-util.c
parentef57c69b787e8efc0d451d0e3f8c6d3b41c67a21 (diff)
downloadsystemd-5d594d012da06bec9b22cac41ecea7ee77aa972b.tar.gz
socket-util: add wrappers for binding socket to ifindex/ifname
socket_bind_to_ifindex() uses the the SO_BINDTOIFINDEX sockopt of kernel 5.0, with a fallback to SO_BINDTODEVICE on older kernels. socket_bind_to_ifname() is a trivial wrapper around SO_BINDTODEVICE, the only benefit of using it instead of SO_BINDTODEVICE directly is that it determines the size of the interface name properly so that it also works for unbinding. Moreover, it's an attempt to unify our invocations of the sockopt with a size of strlen(ifname) rather than strlen(ifname)+1...
Diffstat (limited to 'src/basic/socket-util.c')
-rw-r--r--src/basic/socket-util.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 3c156fd659..3d929f5418 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1354,3 +1354,39 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
}
}
+
+int socket_bind_to_ifname(int fd, const char *ifname) {
+ assert(fd >= 0);
+
+ /* Call with NULL to drop binding */
+
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen_ptr(ifname)) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int socket_bind_to_ifindex(int fd, int ifindex) {
+ char ifname[IFNAMSIZ] = "";
+
+ assert(fd >= 0);
+
+ if (ifindex <= 0) {
+ /* Drop binding */
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0) < 0)
+ return -errno;
+
+ return 0;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTOIFINDEX, &ifindex, sizeof(ifindex)) >= 0)
+ return 0;
+ if (errno != ENOPROTOOPT)
+ return -errno;
+
+ /* Fall back to SO_BINDTODEVICE on kernels < 5.0 which didn't have SO_BINDTOIFINDEX */
+ if (!if_indextoname(ifindex, ifname))
+ return -errno;
+
+ return socket_bind_to_ifname(fd, ifname);
+}