#include <unistd.h>
#include "alloc-util.h"
+#include "errno-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "log.h"
#include "macro.h"
+#include "memory-util.h"
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
#include "strv.h"
#include "user-util.h"
#include "utf8.h"
-#include "util.h"
#if ENABLE_IDN
# define IDN_FLAGS NI_IDN
}
int socket_address_parse_netlink(SocketAddress *a, const char *s) {
- int family;
+ _cleanup_free_ char *word = NULL;
unsigned group = 0;
- _cleanup_free_ char *sfamily = NULL;
+ int family, r;
+
assert(a);
assert(s);
zero(*a);
a->type = SOCK_RAW;
- errno = 0;
- if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
- return errno > 0 ? -errno : -EINVAL;
+ r = extract_first_word(&s, &word, NULL, 0);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL;
- family = netlink_family_from_string(sfamily);
+ family = netlink_family_from_string(word);
if (family < 0)
return -EINVAL;
+ if (!isempty(s)) {
+ r = safe_atou(s, &group);
+ if (r < 0)
+ return r;
+ }
+
a->sockaddr.nl.nl_family = AF_NETLINK;
a->sockaddr.nl.nl_groups = group;
continue;
return -errno;
-
- } else if (r == 0)
+ }
+ if (r == 0)
return 0;
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (cfd < 0) {
- if (errno == EINTR)
- continue;
-
if (errno == EAGAIN)
return 0;
+ if (ERRNO_IS_ACCEPT_AGAIN(errno))
+ continue;
+
return -errno;
}
- close(cfd);
+ safe_close(cfd);
}
}
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);
+}