summaryrefslogtreecommitdiff
path: root/src/basic/socket-util.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/socket-util.h')
-rw-r--r--src/basic/socket-util.h21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index db3a73197..a85045d11 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -27,9 +27,11 @@
#include <sys/types.h>
#include <sys/un.h>
#include <linux/netlink.h>
+#include <linux/if_infiniband.h>
#include <linux/if_packet.h>
#include "macro.h"
+#include "missing.h"
#include "util.h"
union sockaddr_union {
@@ -45,6 +47,8 @@ union sockaddr_union {
struct sockaddr_ll ll;
struct sockaddr_vm vm;
#endif // 0
+ /* Ensure there is enough space to store Infiniband addresses */
+ uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)];
};
#if 0 /// UNNEEDED by elogind
@@ -158,6 +162,23 @@ int flush_accept(int fd);
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
#endif // 0
+/*
+ * Certain hardware address types (e.g Infiniband) do not fit into sll_addr
+ * (8 bytes) and run over the structure. This macro returns the correct size that
+ * must be passed to kernel.
+ */
+#define SOCKADDR_LL_LEN(sa) \
+ ({ \
+ const struct sockaddr_ll *_sa = &(sa); \
+ size_t _mac_len = sizeof(_sa->sll_addr); \
+ assert(_sa->sll_family == AF_PACKET); \
+ if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER) \
+ _mac_len = MAX(_mac_len, (size_t) ETH_ALEN); \
+ if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND) \
+ _mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \
+ offsetof(struct sockaddr_ll, sll_addr) + _mac_len; \
+ })
+
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
#define SOCKADDR_UN_LEN(sa) \
({ \