From 00ed2fff1a87372e6af37398f48527d75c00339c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Nov 2020 12:41:23 +0100 Subject: [PATCH 1/3] socket-util: add sockopt helper for controlling IP_RECVFRAGSIZE --- src/basic/missing_socket.h | 8 ++++++++ src/basic/socket-util.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/basic/missing_socket.h b/src/basic/missing_socket.h index 17bc1a5a01..30ac297e17 100644 --- a/src/basic/missing_socket.h +++ b/src/basic/missing_socket.h @@ -67,6 +67,14 @@ struct sockaddr_vm { #define IPV6_FREEBIND 78 #endif +#ifndef IP_RECVFRAGSIZE +#define IP_RECVFRAGSIZE 25 +#endif + +#ifndef IPV6_RECVFRAGSIZE +#define IPV6_RECVFRAGSIZE 77 +#endif + /* linux/sockios.h */ #ifndef SIOCGSKNS #define SIOCGSKNS 0x894C diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index e353f82a42..7d77144f43 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -266,6 +266,7 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); int socket_get_family(int fd, int *ret); int socket_set_recvpktinfo(int fd, int af, bool b); int socket_set_unicast_if(int fd, int af, int ifi); + int socket_set_option(int fd, int af, int opt_ipv4, int opt_ipv6, int val); static inline int socket_set_recverr(int fd, int af, bool b) { return socket_set_option(fd, af, IP_RECVERR, IPV6_RECVERR, b); @@ -282,3 +283,6 @@ static inline int socket_set_freebind(int fd, int af, bool b) { static inline int socket_set_transparent(int fd, int af, bool b) { return socket_set_option(fd, af, IP_TRANSPARENT, IPV6_TRANSPARENT, b); } +static inline int socket_set_recvfragsize(int fd, int af, bool b) { + return socket_set_option(fd, af, IP_RECVFRAGSIZE, IPV6_RECVFRAGSIZE, b); +} From 4e25d4cf0f78ef7c960f2b77c941e3d8751535df Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Nov 2020 12:41:39 +0100 Subject: [PATCH 2/3] socket-util: add getsockopt_int() helper --- src/basic/socket-util.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 7d77144f43..0dd6798d32 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -258,6 +258,19 @@ static inline int setsockopt_int(int fd, int level, int optname, int value) { return 0; } +static inline int getsockopt_int(int fd, int level, int optname, int *ret) { + int v; + socklen_t sl = sizeof(v); + + if (getsockopt(fd, level, optname, &v, &sl) < 0) + return -errno; + if (sl != sizeof(v)) + return -EIO; + + *ret = v; + return 0; +} + int socket_bind_to_ifname(int fd, const char *ifname); int socket_bind_to_ifindex(int fd, int ifindex); From 52975f86721e4f1c612dbf39f92a590edcea2b72 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Nov 2020 15:01:03 +0100 Subject: [PATCH 3/3] socket-util: add common API for querying socket MTU --- src/basic/socket-util.c | 32 ++++++++++++++++++++++++++++++++ src/basic/socket-util.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 1e53ac4e86..59039bea4f 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1314,3 +1314,35 @@ int socket_set_option(int fd, int af, int opt_ipv4, int opt_ipv6, int val) { return -EAFNOSUPPORT; } } + +int socket_get_mtu(int fd, int af, size_t *ret) { + int mtu, r; + + if (af == AF_UNSPEC) { + r = socket_get_family(fd, &af); + if (r < 0) + return r; + } + + switch (af) { + + case AF_INET: + r = getsockopt_int(fd, IPPROTO_IP, IP_MTU, &mtu); + break; + + case AF_INET6: + r = getsockopt_int(fd, IPPROTO_IPV6, IPV6_MTU, &mtu); + break; + + default: + return -EAFNOSUPPORT; + } + + if (r < 0) + return r; + if (mtu <= 0) + return -EINVAL; + + *ret = (size_t) mtu; + return 0; +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 0dd6798d32..240d209c14 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -299,3 +299,5 @@ static inline int socket_set_transparent(int fd, int af, bool b) { static inline int socket_set_recvfragsize(int fd, int af, bool b) { return socket_set_option(fd, af, IP_RECVFRAGSIZE, IPV6_RECVFRAGSIZE, b); } + +int socket_get_mtu(int fd, int af, size_t *ret);