diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md index d9b1c20c77f..f8282752973 100644 --- a/docs/TRANSIENT-SETTINGS.md +++ b/docs/TRANSIENT-SETTINGS.md @@ -429,6 +429,7 @@ Most socket unit settings are available to transient units. ✓ Broadcast= ✓ PassCredentials= ✓ PassSecurity= +✓ PassPacketInfo= ✓ TCPCongestion= ✓ ReusePort= ✓ MessageQueueMaxMessages= diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 60ea63f742a..46a2dbc7edf 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -709,6 +709,15 @@ Defaults to . + + PassPacketInfo= + Takes a boolean value. This controls the IP_PKTINFO, + IPV6_RECVPKTINFO and NETLINK_PKTINFO socket options, which + enable reception of additional per-packet metadata as ancillary message, on + AF_INET, AF_INET6 and AF_UNIX sockets. + Defaults to . + + TCPCongestion= Takes a string value. Controls the TCP diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 0be098df2ea..05dd7e70014 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1174,5 +1174,27 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) { } return n; - +} + +int socket_pass_pktinfo(int fd, bool b) { + int af; + socklen_t sl = sizeof(af); + + if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0) + return -errno; + + switch (af) { + + case AF_INET: + return setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, b); + + case AF_INET6: + return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, b); + + case AF_NETLINK: + return setsockopt_int(fd, SOL_NETLINK, NETLINK_PKTINFO, b); + + default: + return -EAFNOSUPPORT; + } } diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 6f366c04299..9e02e398875 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -220,3 +220,5 @@ int socket_bind_to_ifname(int fd, const char *ifname); int socket_bind_to_ifindex(int fd, int ifindex); ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); + +int socket_pass_pktinfo(int fd, bool b); diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index ad7b41a95b2..73e6a749147 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -104,6 +104,7 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PassPacketInfo", "b", bus_property_get_bool, offsetof(Socket, pass_pktinfo), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST), @@ -202,6 +203,9 @@ static int bus_socket_set_transient_property( if (streq(name, "PassSecurity")) return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error); + if (streq(name, "PassPacketInfo")) + return bus_set_transient_bool(u, name, &s->pass_pktinfo, message, flags, error); + if (streq(name, "ReusePort")) return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 5fd58b379ba..c76d08b3a6d 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -396,6 +396,7 @@ Socket.Transparent, config_parse_bool, 0, Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast) Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred) Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) +Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo) Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion) Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) diff --git a/src/core/socket.c b/src/core/socket.c index 218b4b245df..359683a4261 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -635,6 +635,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { "%sBroadcast: %s\n" "%sPassCredentials: %s\n" "%sPassSecurity: %s\n" + "%sPassPacketInfo: %s\n" "%sTCPCongestion: %s\n" "%sRemoveOnStop: %s\n" "%sWritable: %s\n" @@ -654,6 +655,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(s->broadcast), prefix, yes_no(s->pass_cred), prefix, yes_no(s->pass_sec), + prefix, yes_no(s->pass_pktinfo), prefix, strna(s->tcp_congestion), prefix, yes_no(s->remove_on_stop), prefix, yes_no(s->writable), @@ -1070,6 +1072,12 @@ static void socket_apply_socket_options(Socket *s, int fd) { log_unit_warning_errno(UNIT(s), r, "SO_PASSSEC failed: %m"); } + if (s->pass_pktinfo) { + r = socket_pass_pktinfo(fd, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m"); + } + if (s->priority >= 0) { r = setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, s->priority); if (r < 0) diff --git a/src/core/socket.h b/src/core/socket.h index 9e0be15ba8d..482e45fce74 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -121,6 +121,7 @@ struct Socket { bool broadcast; bool pass_cred; bool pass_sec; + bool pass_pktinfo; /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */ SocketAddressBindIPv6Only bind_ipv6_only; diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index 71b3d1e2f1f..bcd82fe1646 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -16,10 +16,6 @@ #include "socket-util.h" #include "util.h" -/* For some reason we need some extra cmsg space on some kernels. It's not clear why, and one of those days - * we need to track this down. See: https://github.com/systemd/systemd/pull/15457 */ -#define EXTRA_CMSG_SPACE 1024 - int socket_open(int family) { int fd; @@ -244,7 +240,7 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) { static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_group, bool peek) { union sockaddr_union sender; - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct nl_pktinfo)) + EXTRA_CMSG_SPACE) control; + CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct nl_pktinfo))) control; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1, diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index bbaffc165ac..1e2ff05c3e5 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -88,6 +88,7 @@ static int dns_stream_complete(DnsStream *s, int error) { static int dns_stream_identify(DnsStream *s) { CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) + + CMSG_SPACE(int) + /* for the TTL */ + EXTRA_CMSG_SPACE /* kernel appears to require extra space */) control; struct msghdr mh = {}; struct cmsghdr *cmsg; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 3be75e6b4d2..9a5730f3eae 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -1632,6 +1632,7 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons "Broadcast", "PassCredentials", "PassSecurity", + "PassPacketInfo", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet")) diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 048bd34e9e2..7435d7abec0 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -164,6 +164,7 @@ PIDFile= PartOf= PassCredentials= PassSecurity= +PassPacketInfo= PathChanged= PathExists= PathExistsGlob= diff --git a/units/systemd-networkd.socket b/units/systemd-networkd.socket index 445193e8d34..bc049e5ade9 100644 --- a/units/systemd-networkd.socket +++ b/units/systemd-networkd.socket @@ -17,7 +17,7 @@ Before=sockets.target [Socket] ReceiveBuffer=128M ListenNetlink=route 1361 -PassCredentials=yes +PassPacketInfo=yes [Install] WantedBy=sockets.target