<div dir="ltr">the xinetd REMOTE_IP is a fedora extension so I think we should avoid it.</div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Mar 8, 2015 at 4:24 PM, Shawn Landden <span dir="ltr"><<a href="mailto:shawn@churchofgit.com" target="_blank">shawn@churchofgit.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">---<br>
 TODO                   |  2 --<br>
 man/systemd.socket.xml |  6 +++++-<br>
 src/core/service.c     | 47 +++++++++++++++++++++++++++++++++++++++++++++++<br>
 3 files changed, 52 insertions(+), 3 deletions(-)<br>
<br>
diff --git a/TODO b/TODO<br>
index ae32388..780084a 100644<br>
--- a/TODO<br>
+++ b/TODO<br>
@@ -164,8 +164,6 @@ Features:<br>
 * as soon as we have kdbus, and sender timestamps, revisit coalescing multiple parallel daemon reloads:<br>
   <a href="http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html" target="_blank">http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html</a><br>
<br>
-* 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<br>
-<br>
 * the install state probably shouldn't get confused by generated units, think dbus1/kdbus compat!<br>
<br>
 * in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column<br>
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml<br>
index 3938345..20f1e0c 100644<br>
--- a/man/systemd.socket.xml<br>
+++ b/man/systemd.socket.xml<br>
@@ -357,7 +357,11 @@<br>
         daemons designed for usage with<br>
         <citerefentry><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry><br>
         to work unmodified with systemd socket<br>
-        activation.</para></listitem><br>
+        activation.</para><br>
+        <para>For IPv4 and IPv6 connections the <varname>REMOTE_ADDR</varname><br>
+        environment variable will be set with remote IP, and <varname>REMOTE_PORT</varname><br>
+        environment variable set to the remote port, similar to CGI<br>
+        (for SOCK_RAW the port is the IP protocol).</para></listitem><br>
       </varlistentry><br>
<br>
       <varlistentry><br>
diff --git a/src/core/service.c b/src/core/service.c<br>
index cc4ea19..6a690ac 100644<br>
--- a/src/core/service.c<br>
+++ b/src/core/service.c<br>
@@ -22,6 +22,7 @@<br>
 #include <errno.h><br>
 #include <signal.h><br>
 #include <unistd.h><br>
+#include <arpa/inet.h><br>
<br>
 #include "async.h"<br>
 #include "manager.h"<br>
@@ -1119,6 +1120,52 @@ static int service_spawn(<br>
                         goto fail;<br>
                 }<br>
<br>
+        if (s->accept_socket.unit) {<br>
+                union sockaddr_union sa;<br>
+                socklen_t salen = sizeof(sa);<br>
+                _cleanup_free_ char *remote_addr = NULL;<br>
+                char a[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];<br>
+<br>
+                r = getpeername(s->socket_fd, &<a href="http://sa.sa" target="_blank">sa.sa</a>, &salen);<br>
+                if (r < 0) {<br>
+                        r = -errno;<br>
+                        goto fail;<br>
+                }<br>
+<br>
+                if (sa.sa.sa_family == AF_INET ||<br>
+                    sa.sa.sa_family == AF_INET6) {<br>
+                        if (inet_ntop(sa.sa.sa_family,<br>
+                                      /* this field of the API is kinda braindead,<br>
+                                       * should take head of struct so it can be passed the union...*/<br>
+                                      sa.sa.sa_family == AF_INET6 ?<br>
+                                        &sa.in6.sin6_addr :<br>
+                                        &sa.in.sin_addr,<br>
+                                      a, sizeof(a)) == NULL) {<br>
+                                r = -errno;<br>
+                                goto fail;<br>
+                        }<br>
+<br>
+                        if (asprintf(our_env + n_env++,<br>
+                                     "REMOTE_ADDR=%s",<br>
+                                     /* musl and glibc inet_ntop() present v4-mapped addresses in ::ffff:a.b.c.d form */<br>
+                                     sa.sa.sa_family == AF_INET6 && strchr(a, '.') ?<br>
+                                       strempty(startswith(a, "::ffff:")) :<br>
+                                       a) < 0) {<br>
+                                r = -ENOMEM;<br>
+                                goto fail;<br>
+                        }<br>
+<br>
+                        if (asprintf(our_env + n_env++,<br>
+                                     "REMOTE_PORT=%u",<br>
+                                     ntohs(sa.sa.sa_family == AF_INET6 ?<br>
+                                             sa.in6.sin6_port :<br>
+                                             sa.in.sin_port)) < 0) {<br>
+                                r = -ENOMEM;<br>
+                                goto fail;<br>
+                        }<br>
+                }<br>
+        }<br>
+<br>
         final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);<br>
         if (!final_env) {<br>
                 r = -ENOMEM;<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.2.1.209.g41e5f3a<br>
<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Shawn Landden</div>
</div>