diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/socket-util.c | 83 | ||||
-rw-r--r-- | src/shared/socket-util.h | 2 |
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); |