Dirk Mueller
868d58656c
- Fixed rpc broadcast handling (bnc#857324) Upgraded to upstream 0.2.1-rc4 as part of this, and rebased the patch set. OBS-URL: https://build.opensuse.org/request/show/215477 OBS-URL: https://build.opensuse.org/package/show/network/rpcbind?expand=0&rev=32
373 lines
9.4 KiB
Diff
373 lines
9.4 KiB
Diff
From d92c22d7e8d476b7772ce4e3d8e23200d0048b45 Mon Sep 17 00:00:00 2001
|
|
From: Olaf Kirch <okir@suse.de>
|
|
Date: Tue, 20 Aug 2013 11:26:42 +0200
|
|
Subject: [PATCH 12/24] Support systemd activation.
|
|
|
|
This code is loosely based on previous work by Tom Gundersen <teg@jklm.no>.
|
|
|
|
Signed-off-by: Olaf Kirch <okir@suse.de>
|
|
---
|
|
Makefile.am | 15 ++++
|
|
configure.ac | 11 +++
|
|
src/rpcbind.c | 172 ++++++++++++++++++++++++++++++++++++---------
|
|
systemd/.gitignore | 1 +
|
|
systemd/rpcbind.service.in | 9 +++
|
|
systemd/rpcbind.socket | 12 ++++
|
|
6 files changed, 188 insertions(+), 32 deletions(-)
|
|
create mode 100644 systemd/.gitignore
|
|
create mode 100644 systemd/rpcbind.service.in
|
|
create mode 100644 systemd/rpcbind.socket
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index d10c906..df755dd 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -38,6 +38,21 @@ rpcbind_SOURCES = \
|
|
src/warmstart.c
|
|
rpcbind_LDADD = $(TIRPC_LIBS)
|
|
|
|
+if SYSTEMD
|
|
+AM_CPPFLAGS += $(SYSTEMD_CFLAGS) -DSYSTEMD
|
|
+
|
|
+rpcbind_LDADD += $(SYSTEMD_LIBS)
|
|
+
|
|
+systemd/rpcbind.service: systemd/rpcbind.service.in Makefile
|
|
+ sed -e 's,@bindir\@,$(bindir),g' \
|
|
+ < $< > $@ || rm $@
|
|
+
|
|
+systemdsystemunit_DATA = \
|
|
+ systemd/rpcbind.service \
|
|
+ systemd/rpcbind.socket
|
|
+
|
|
+endif
|
|
+
|
|
rpcinfo_SOURCES = src/rpcinfo.c
|
|
rpcinfo_LDADD = $(TIRPC_LIBS)
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 1cf42d3..a94933b 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -29,6 +29,17 @@ AC_SUBST([rpcuser], [$with_rpcuser])
|
|
|
|
PKG_CHECK_MODULES([TIRPC], [libtirpc])
|
|
|
|
+PKG_PROG_PKG_CONFIG
|
|
+AC_ARG_WITH([systemdsystemunitdir],
|
|
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
|
|
+ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
|
|
+ if test "x$with_systemdsystemunitdir" != xno -a "x$with_systemdsystemunitdir" != "x"; then
|
|
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
|
|
+ PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon])
|
|
+ fi
|
|
+AM_CONDITIONAL(SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
|
|
+
|
|
+
|
|
AS_IF([test x$enable_libwrap = xyes], [
|
|
AC_CHECK_LIB([wrap], [hosts_access], ,
|
|
AC_MSG_ERROR([libwrap support requested but unable to find libwrap]))
|
|
diff --git a/src/rpcbind.c b/src/rpcbind.c
|
|
index 3b753c6..baf1ac0 100644
|
|
--- a/src/rpcbind.c
|
|
+++ b/src/rpcbind.c
|
|
@@ -56,6 +56,9 @@
|
|
#include <netinet/in.h>
|
|
#endif
|
|
#include <arpa/inet.h>
|
|
+#ifdef SYSTEMD
|
|
+#include <systemd/sd-daemon.h>
|
|
+#endif
|
|
#include <fcntl.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
@@ -100,6 +103,9 @@ int runasdaemon = 0;
|
|
int insecure = 0;
|
|
int oldstyle_local = 0;
|
|
int verboselog = 0;
|
|
+#ifdef SYSTEMD
|
|
+int systemd_activation = 0;
|
|
+#endif
|
|
|
|
char **hosts = NULL;
|
|
int nhosts = 0;
|
|
@@ -123,6 +129,10 @@ static char superuser[] = "superuser";
|
|
|
|
int main __P((int, char *[]));
|
|
|
|
+static void init_transports_daemon __P((void));
|
|
+#ifdef SYSTEMD
|
|
+static void init_transports_systemd __P((void));
|
|
+#endif
|
|
static int init_transport __P((struct netconfig *));
|
|
static void rbllist_add __P((rpcprog_t, rpcvers_t, struct netconfig *,
|
|
struct netbuf *));
|
|
@@ -132,11 +142,15 @@ static void parseargs __P((int, char *[]));
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
- struct netconfig *nconf;
|
|
- void *nc_handle; /* Net config handle */
|
|
struct rlimit rl;
|
|
int maxrec = RPC_MAXDATASIZE;
|
|
|
|
+#ifdef SYSTEMD
|
|
+ /* See whether we've been activated by systemd */
|
|
+ if (sd_listen_fds(0) > 0)
|
|
+ systemd_activation = 1;
|
|
+#endif
|
|
+
|
|
parseargs(argc, argv);
|
|
|
|
/* Check that another rpcbind isn't already running. */
|
|
@@ -167,29 +181,14 @@ main(int argc, char *argv[])
|
|
*/
|
|
__nss_configure_lookup("services", "files");
|
|
|
|
- nc_handle = setnetconfig(); /* open netconfig file */
|
|
- if (nc_handle == NULL) {
|
|
- syslog(LOG_ERR, "could not read /etc/netconfig");
|
|
- exit(1);
|
|
- }
|
|
-
|
|
- nconf = getnetconfigent("local");
|
|
- if (nconf == NULL)
|
|
- nconf = getnetconfigent("unix");
|
|
- if (nconf == NULL) {
|
|
- syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
|
|
- exit(1);
|
|
- }
|
|
-
|
|
rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
|
|
|
|
- init_transport(nconf);
|
|
-
|
|
- while ((nconf = getnetconfig(nc_handle))) {
|
|
- if (nconf->nc_flag & NC_VISIBLE)
|
|
- init_transport(nconf);
|
|
- }
|
|
- endnetconfig(nc_handle);
|
|
+#ifdef SYSTEMD
|
|
+ if (systemd_activation)
|
|
+ init_transports_systemd();
|
|
+ else
|
|
+#endif
|
|
+ init_transports_daemon();
|
|
|
|
#ifdef PORTMAP
|
|
if (!udptrans)
|
|
@@ -571,17 +570,29 @@ rpcbind_register_transport(struct netconfig *nconf, SVCXPRT *xprt, struct netbuf
|
|
* <0: error - ignore this netid
|
|
*/
|
|
static int
|
|
-rpcbind_init_endpoint(struct netconfig *nconf, const char *hostname)
|
|
+rpcbind_init_endpoint(struct netconfig *nconf, const char *hostname, int fd)
|
|
{
|
|
struct t_bind taddr;
|
|
SVCXPRT *my_xprt = NULL;
|
|
- int r, fd = -1;
|
|
+ int r;
|
|
|
|
memset(&taddr, 0, sizeof(taddr));
|
|
|
|
- r = create_transport_socket(nconf, hostname, &taddr.addr, &fd);
|
|
- if (r <= 0)
|
|
- return r;
|
|
+ if (fd < 0) {
|
|
+ r = create_transport_socket(nconf, hostname, &taddr.addr, &fd);
|
|
+ if (r <= 0)
|
|
+ return r;
|
|
+ } else {
|
|
+ struct sockaddr_storage addr;
|
|
+ socklen_t alen = sizeof(addr);
|
|
+
|
|
+ if (getsockname(fd, (struct sockaddr *) &addr, &alen) < 0) {
|
|
+ syslog(LOG_ERR, "cannot get address for socket fd %d", fd);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ sockaddr2netbuf((struct sockaddr *) &addr, alen, &taddr.addr);
|
|
+ }
|
|
|
|
my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
|
|
if (my_xprt == (SVCXPRT *)NULL) {
|
|
@@ -645,12 +656,12 @@ init_transport(struct netconfig *nconf)
|
|
/* Ensure that we always bind to loopback */
|
|
switch (si.si_af) {
|
|
case AF_INET:
|
|
- if (rpcbind_init_endpoint(nconf, "127.0.0.1") > 0)
|
|
+ if (rpcbind_init_endpoint(nconf, "127.0.0.1", -1) > 0)
|
|
numbound++;
|
|
break;
|
|
|
|
case AF_INET6:
|
|
- if (rpcbind_init_endpoint(nconf, "::1") > 0)
|
|
+ if (rpcbind_init_endpoint(nconf, "::1", -1) > 0)
|
|
numbound++;
|
|
break;
|
|
}
|
|
@@ -662,7 +673,7 @@ init_transport(struct netconfig *nconf)
|
|
if (strcmp("*", hostname) == 0)
|
|
hostname = NULL;
|
|
|
|
- r = rpcbind_init_endpoint(nconf, hostname);
|
|
+ r = rpcbind_init_endpoint(nconf, hostname, -1);
|
|
if (r < 0)
|
|
return 1;
|
|
if (r > 0)
|
|
@@ -672,7 +683,7 @@ init_transport(struct netconfig *nconf)
|
|
if (numbound == 0)
|
|
return 1;
|
|
} else {
|
|
- if (rpcbind_init_endpoint(nconf, NULL) <= 0)
|
|
+ if (rpcbind_init_endpoint(nconf, NULL, -1) <= 0)
|
|
return 1;
|
|
}
|
|
|
|
@@ -699,6 +710,103 @@ init_transport(struct netconfig *nconf)
|
|
}
|
|
|
|
static void
|
|
+init_transports_daemon(void)
|
|
+{
|
|
+ void *nc_handle;
|
|
+ struct netconfig *nconf;
|
|
+
|
|
+ nc_handle = setnetconfig(); /* open netconfig file */
|
|
+ if (nc_handle == NULL) {
|
|
+ syslog(LOG_ERR, "could not read /etc/netconfig");
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ nconf = getnetconfigent("local");
|
|
+ if (nconf == NULL)
|
|
+ nconf = getnetconfigent("unix");
|
|
+ if (nconf == NULL) {
|
|
+ syslog(LOG_ERR, "rpcbind: can't find local transport\n");
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ init_transport(nconf);
|
|
+
|
|
+ while ((nconf = getnetconfig(nc_handle))) {
|
|
+ if (nconf->nc_flag & NC_VISIBLE)
|
|
+ init_transport(nconf);
|
|
+ }
|
|
+ endnetconfig(nc_handle);
|
|
+}
|
|
+
|
|
+#ifdef SYSTEMD
|
|
+static struct netconfig *
|
|
+sockinfo2nconf(void **handlep, const struct __rpc_sockinfo *match)
|
|
+{
|
|
+ struct netconfig *nconf;
|
|
+
|
|
+ if (*handlep)
|
|
+ endnetconfig(*handlep);
|
|
+ *handlep = setnetconfig();
|
|
+
|
|
+ while ((nconf = getnetconfig(*handlep))) {
|
|
+ struct __rpc_sockinfo si;
|
|
+
|
|
+ if (!__rpc_nconf2sockinfo(nconf, &si))
|
|
+ continue;
|
|
+
|
|
+ if (si.si_af == match->si_af
|
|
+ && si.si_socktype == match->si_socktype
|
|
+ && si.si_proto == match->si_proto)
|
|
+ return nconf;
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void
|
|
+init_transports_systemd()
|
|
+{
|
|
+ void *nc_handle = NULL;
|
|
+ int nfds, n;
|
|
+
|
|
+ if ((nfds = sd_listen_fds(0)) < 0) {
|
|
+ syslog(LOG_ERR, "failed to acquire systemd sockets: %s", strerror(-nfds));
|
|
+ exit(1);
|
|
+ }
|
|
+ if (nfds >= 16) {
|
|
+ syslog(LOG_ERR, "too many sockets passed by systemd (%u)", nfds);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ for (n = 0; n < nfds; ++n) {
|
|
+ struct netconfig *nconf;
|
|
+ struct __rpc_sockinfo si;
|
|
+ int fd;
|
|
+
|
|
+ fd = SD_LISTEN_FDS_START + n;
|
|
+
|
|
+ if (!__rpc_fd2sockinfo(fd, &si)) {
|
|
+ syslog(LOG_ERR, "cannot get socket information for fd %d", fd);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ /* Now find the netconfig entry matching this transport */
|
|
+ if ((nconf = sockinfo2nconf(&nc_handle, &si)) == NULL) {
|
|
+ syslog(LOG_ERR, "not netconfig for socket fd %d", fd);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ if (rpcbind_init_endpoint(nconf, NULL, fd) <= 0) {
|
|
+ syslog(LOG_ERR, "unable to create transport for socket fd %d", fd);
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (nc_handle)
|
|
+ endnetconfig(nc_handle);
|
|
+}
|
|
+#endif
|
|
+
|
|
+static void
|
|
rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
|
|
struct netbuf *addr)
|
|
{
|
|
diff --git a/systemd/.gitignore b/systemd/.gitignore
|
|
new file mode 100644
|
|
index 0000000..b7b4561
|
|
--- /dev/null
|
|
+++ b/systemd/.gitignore
|
|
@@ -0,0 +1 @@
|
|
+rpcbind.service
|
|
diff --git a/systemd/rpcbind.service.in b/systemd/rpcbind.service.in
|
|
new file mode 100644
|
|
index 0000000..58ae5de
|
|
--- /dev/null
|
|
+++ b/systemd/rpcbind.service.in
|
|
@@ -0,0 +1,9 @@
|
|
+[Unit]
|
|
+Description=RPC Bind
|
|
+
|
|
+[Service]
|
|
+ExecStart=@bindir@/rpcbind -w -f
|
|
+
|
|
+[Install]
|
|
+WantedBy=multi-user.target
|
|
+Also=rpcbind.socket
|
|
diff --git a/systemd/rpcbind.socket b/systemd/rpcbind.socket
|
|
new file mode 100644
|
|
index 0000000..ad5fd62
|
|
--- /dev/null
|
|
+++ b/systemd/rpcbind.socket
|
|
@@ -0,0 +1,12 @@
|
|
+[Unit]
|
|
+Description=RPCbind Server Activation Socket
|
|
+Wants=rpcbind.target
|
|
+Before=rpcbind.target
|
|
+
|
|
+[Socket]
|
|
+ListenStream=/var/run/rpcbind.sock
|
|
+ListenStream=111
|
|
+ListenDatagram=111
|
|
+
|
|
+[Install]
|
|
+WantedBy=sockets.target
|
|
--
|
|
1.7.12.4
|
|
|