--- TODO | 2 -- man/systemd.socket.xml | 6 +++++- src/core/service.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/TODO b/TODO index ae32388..780084a 100644 --- a/TODO +++ b/TODO @@ -164,8 +164,6 @@ Features: * as soon as we have kdbus, and sender timestamps, revisit coalescing multiple parallel daemon reloads: http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html -* set $REMOTE_IP (or $REMOTE_ADDR/$REMOTE_PORT) environment variable when doing per-connection socket activation. use format introduced by xinetd or CGI for this - * the install state probably shouldn't get confused by generated units, think dbus1/kdbus compat! * in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 3938345..20f1e0c 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -357,7 +357,11 @@ daemons designed for usage with <citerefentry><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry> to work unmodified with systemd socket - activation.</para></listitem> + activation.</para> + <para>For IPv4 and IPv6 connections the <varname>REMOTE_ADDR</varname> + environment variable will be set with remote IP, and <varname>REMOTE_PORT</varname> + environment variable set to the remote port, similar to CGI + (for SOCK_RAW the port is the IP protocol).</para></listitem> </varlistentry> <varlistentry> diff --git a/src/core/service.c b/src/core/service.c index cc4ea19..6a690ac 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -22,6 +22,7 @@ #include <errno.h> #include <signal.h> #include <unistd.h> +#include <arpa/inet.h> #include "async.h" #include "manager.h" @@ -1119,6 +1120,52 @@ static int service_spawn( goto fail; } + if (s->accept_socket.unit) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + _cleanup_free_ char *remote_addr = NULL; + char a[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)]; + + r = getpeername(s->socket_fd, &sa.sa, &salen); + if (r < 0) { + r = -errno; + goto fail; + } + + if (sa.sa.sa_family == AF_INET || + sa.sa.sa_family == AF_INET6) { + if (inet_ntop(sa.sa.sa_family, + /* this field of the API is kinda braindead, + * should take head of struct so it can be passed the union...*/ + sa.sa.sa_family == AF_INET6 ? + &sa.in6.sin6_addr : + &sa.in.sin_addr, + a, sizeof(a)) == NULL) { + r = -errno; + goto fail; + } + + if (asprintf(our_env + n_env++, + "REMOTE_ADDR=%s", + /* musl and glibc inet_ntop() present v4-mapped addresses in ::ffff:a.b.c.d form */ + sa.sa.sa_family == AF_INET6 && strchr(a, '.') ? + strempty(startswith(a, "::ffff:")) : + a) < 0) { + r = -ENOMEM; + goto fail; + } + + if (asprintf(our_env + n_env++, + "REMOTE_PORT=%u", + ntohs(sa.sa.sa_family == AF_INET6 ? + sa.in6.sin6_port : + sa.in.sin_port)) < 0) { + r = -ENOMEM; + goto fail; + } + } + } + final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL); if (!final_env) { r = -ENOMEM; -- 2.2.1.209.g41e5f3a _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel