diff options
-rw-r--r-- | include/socket.h | 6 | ||||
-rw-r--r-- | src/socket.cpp | 37 |
2 files changed, 43 insertions, 0 deletions
diff --git a/include/socket.h b/include/socket.h index 593550018..d3a45475d 100644 --- a/include/socket.h +++ b/include/socket.h @@ -115,6 +115,12 @@ namespace irc * @return true if the conversion was successful, false if unknown address family */ CoreExport bool satoap(const irc::sockets::sockaddrs* sa, std::string& addr, int &port); + /** Convert a binary sockaddr to a user-readable string. + * This means IPv6 addresses are written as [::1]:6667, and *:6668 is used for 0.0.0.0:6668 + * @param sa The structure to convert + * @return The string; "<unknown>" if not a valid address + */ + CoreExport std::string satouser(const irc::sockets::sockaddrs* sa); } } diff --git a/src/socket.cpp b/src/socket.cpp index c4f8baee6..2eb8aeb7e 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -258,6 +258,43 @@ bool irc::sockets::satoap(const irc::sockets::sockaddrs* sa, std::string& addr, return false; } +static const char all_zero[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; + +std::string irc::sockets::satouser(const irc::sockets::sockaddrs* sa) { + char buffer[MAXBUF]; + if (sa->sa.sa_family == AF_INET) + { + if (sa->in4.sin_addr.s_addr == 0) + { + sprintf(buffer, "*:%u", ntohs(sa->in4.sin_port)); + } + else + { + const uint8_t* bits = reinterpret_cast<const uint8_t*>(&sa->in4.sin_addr); + sprintf(buffer, "%d.%d.%d.%d:%u", bits[0], bits[1], bits[2], bits[3], ntohs(sa->in4.sin_port)); + } + } + else if (sa->sa.sa_family == AF_INET6) + { + if (!memcmp(all_zero, &sa->in6.sin6_addr, 16)) + { + sprintf(buffer, "*:%u", ntohs(sa->in6.sin6_port)); + } + else + { + buffer[0] = '['; + if (!inet_ntop(AF_INET6, &sa->in6.sin6_addr, buffer+1, MAXBUF - 10)) + return "<unknown>"; // should never happen, buffer is large enough + int len = strlen(buffer); + // no need for snprintf, buffer has at least 9 chars left, max short len = 5 + sprintf(buffer + len, "]:%u", ntohs(sa->in6.sin6_port)); + } + } + else + return "<unknown>"; + return std::string(buffer); +} + int irc::sockets::sa_size(irc::sockets::sockaddrs& sa) { if (sa.sa.sa_family == AF_INET) |