From 606cd5e780b3077d31c3ccc3b360a44a08c2e172 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 16 Dec 2014 12:58:48 -0500 Subject: rpcbind: IPv4/IPv6 dualmode Systemd will, by default, pass a socket that provides both IPv4 and IPv6 services. RPC netconfig requires that sockets be either IPv4 or IPv6. Adjust the rpcbind.socket unit file and add a warning to rpcbind should the user encounter an issue. Signed-off-by: Jeff Mahoney Signed-off-by: Steve Dickson --- src/rpcbind.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/rpcbind.c b/src/rpcbind.c index f7c71ee..f5159c7 100644 --- a/src/rpcbind.c +++ b/src/rpcbind.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #ifdef PORTMAP @@ -276,6 +277,31 @@ main(int argc, char *argv[]) return 0; } +/* + * Normally systemd will open sockets in dual ipv4/ipv6 mode. + * That won't work with netconfig and we'll only match + * the ipv6 socket. Convert it to IPV6_V6ONLY and issue + * a warning for the user to fix their systemd config. + */ +static int +handle_ipv6_socket(int fd) +{ + int opt; + socklen_t len = sizeof(opt); + + if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, &len)) { + syslog(LOG_ERR, "failed to get ipv6 socket opts: %m"); + return -1; + } + + if (opt) /* socket is already in V6ONLY mode */ + return 0; + + syslog(LOG_ERR, "systemd has passed an IPv4/IPv6 dual-mode socket."); + syslog(LOG_ERR, "Please fix your systemd config by specifying IPv4 and IPv6 sockets separately and using BindIPv6Only=ipv6-only."); + return -1; +} + /* * Adds the entry into the rpcbind database. * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also @@ -361,6 +387,9 @@ init_transport(struct netconfig *nconf) goto error; } + if (sa.sa.sa_family == AF_INET6 && handle_ipv6_socket(fd)) + goto error; + /* Copy the address */ taddr.addr.maxlen = taddr.addr.len = addrlen; taddr.addr.buf = malloc(addrlen); -- cgit v1.2.1