summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-11-06 22:40:54 +0100
committerLennart Poettering <lennart@poettering.net>2013-11-06 23:03:12 +0100
commit8569a77629949b7818d00eba8eea1d05e2d1fc32 (patch)
tree0f807b151ed4649032012084c83a8ed95669e8ca /src/shared
parent175a3d25d0e8596d4ba0759aea3f89ee228e7d6d (diff)
socket-proxyd: rework to support multiple sockets and splice()-based zero-copy network IO
This also drops --ignore-env, which can't really work anymore if we allow multiple fds. Also adds support for pretty printing of peer identities for debug purposes, and abstract namespace UNIX sockets. Also ensures that we never take more connections than a certain limit.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/socket-util.c83
-rw-r--r--src/shared/socket-util.h2
2 files changed, 85 insertions, 0 deletions
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index 1175795d7c..0097f011bb 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -568,6 +568,89 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
return false;
}
+int getpeername_pretty(int fd, char **ret) {
+
+ union {
+ struct sockaddr sa;
+ struct sockaddr_un un;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage storage;
+ } sa;
+
+ socklen_t salen;
+ char *p;
+
+ assert(fd >= 0);
+ assert(ret);
+
+ salen = sizeof(sa);
+ if (getpeername(fd, &sa.sa, &salen) < 0)
+ return -errno;
+
+ switch (sa.sa.sa_family) {
+
+ case AF_INET: {
+ uint32_t a;
+
+ a = ntohl(sa.in.sin_addr.s_addr);
+
+ if (asprintf(&p,
+ "%u.%u.%u.%u:%u",
+ a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
+ ntohs(sa.in.sin_port)) < 0)
+ return -ENOMEM;
+
+ break;
+ }
+
+ case AF_INET6: {
+ static const unsigned char ipv4_prefix[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
+ };
+
+ if (memcmp(&sa.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
+ const uint8_t *a = sa.in6.sin6_addr.s6_addr+12;
+
+ if (asprintf(&p,
+ "%u.%u.%u.%u:%u",
+ a[0], a[1], a[2], a[3],
+ ntohs(sa.in6.sin6_port)) < 0)
+ return -ENOMEM;
+ } else {
+ char a[INET6_ADDRSTRLEN];
+
+ if (asprintf(&p,
+ "%s:%u",
+ inet_ntop(AF_INET6, &sa.in6.sin6_addr, a, sizeof(a)),
+ ntohs(sa.in6.sin6_port)) < 0)
+ return -ENOMEM;
+ }
+
+ break;
+ }
+
+ case AF_UNIX: {
+ struct ucred ucred;
+
+ salen = sizeof(ucred);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &salen) < 0)
+ return -errno;
+
+ if (asprintf(&p, "PID %lu/UID %lu", (unsigned long) ucred.pid, (unsigned long) ucred.pid) < 0)
+ return -ENOMEM;
+
+ break;
+ }
+
+ default:
+ return -ENOTSUP;
+ }
+
+ *ret = p;
+ return 0;
+}
+
static const char* const netlink_family_table[] = {
[NETLINK_ROUTE] = "route",
[NETLINK_FIREWALL] = "firewall",
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
index 0b9bf2fefc..13566f9691 100644
--- a/src/shared/socket-util.h
+++ b/src/shared/socket-util.h
@@ -99,3 +99,5 @@ int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s);
bool socket_ipv6_is_supported(void);
+
+int getpeername_pretty(int fd, char **ret);