[systemd-devel] [PATCH] core/socket: Add REMOTE_IP environment variable for Accept=true
Shawn Landden
shawn at churchofgit.com
Wed Mar 4 15:18:43 PST 2015
Fix handling of abstract unix domain sockets too.
v2
---
TODO | 2 --
man/systemd.socket.xml | 5 ++++-
src/core/service.c | 24 ++++++++++++++++++++++++
src/shared/socket-util.c | 25 +++++++++++++++++++------
4 files changed, 47 insertions(+), 9 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..8796d7b 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -357,7 +357,10 @@
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_IP</varname>
+ environment variable will be set with remote IP and port seperated by a
+ colon (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 a89ff3f..2ee4e11 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1119,6 +1119,30 @@ static int service_spawn(
goto fail;
}
+ if (s->accept_socket.unit) {
+ union sockaddr_union pn;
+ socklen_t pnlen = sizeof(pn);
+ _cleanup_free_ char *remote_addr = NULL;
+
+ r = getpeername(s->socket_fd, &pn.sa, &pnlen);
+ if (r < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ if (pn.in.sin_family == AF_INET ||
+ pn.in.sin_family == AF_INET6) {
+ r = sockaddr_pretty(&pn.sa, pnlen, true, &remote_addr);
+ if (r < 0)
+ goto fail;
+
+ if (asprintf(our_env + n_env++, "REMOTE_IP=%s", remote_addr) < 0) {
+ r = -ENOMEM;
+ goto fail;
+ }
+ }
+ }
+
final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);
if (!final_env) {
r = -ENOMEM;
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index 74d90fa..dbe2bf7 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -522,19 +522,32 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
return -ENOMEM;
} else if (sa->un.sun_path[0] == 0) {
+ void *i;
/* abstract */
- /* FIXME: We assume we can print the
- * socket path here and that it hasn't
- * more than one NUL byte. That is
- * actually an invalid assumption */
-
+ /* see unix(7), abstract is wierd */
+ i = memchr(&sa->un.sun_path + 1, '\0', sizeof(sa->un.sun_path) - 1);
+ if (i)
+ for (i = (char *)i + 1;
+ (char *)i < &sa->un.sun_path[sizeof(sa->un.sun_path)];
+ i = (char *)i + 1)
+ if (*(char *)i != '\0') {
+ p = strdup("<abstract unprintable>");
+ if (!p)
+ return -ENOMEM;
+
+ goto end;
+ }
+
+ /* no non-NUL bytes after second NUL (if any) */
p = new(char, sizeof(sa->un.sun_path)+1);
if (!p)
return -ENOMEM;
p[0] = '@';
memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
+
+ /* make printable if there was no second NUL (i == NULL) */
p[sizeof(sa->un.sun_path)] = 0;
} else {
@@ -549,7 +562,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
return -ENOTSUP;
}
-
+end:
*ret = p;
return 0;
}
--
2.2.1.209.g41e5f3a
More information about the systemd-devel
mailing list