diff --git a/src/net/SocketAddress.cxx b/src/net/SocketAddress.cxx index 8b28832f8..70175a29f 100644 --- a/src/net/SocketAddress.cxx +++ b/src/net/SocketAddress.cxx @@ -29,9 +29,14 @@ #include "config.h" #include "SocketAddress.hxx" +#include "util/StringView.hxx" #include +#ifdef HAVE_UN +#include +#endif + #ifdef HAVE_TCP #ifdef _WIN32 #include @@ -46,6 +51,28 @@ SocketAddress::operator==(SocketAddress other) const noexcept return size == other.size && memcmp(address, other.address, size) == 0; } +#ifdef HAVE_UN + +StringView +SocketAddress::GetLocalRaw() const noexcept +{ + if (IsNull() || GetFamily() != AF_LOCAL) + /* not applicable */ + return nullptr; + + const auto sun = (const struct sockaddr_un *)GetAddress(); + const auto start = (const char *)sun; + const auto path = sun->sun_path; + const size_t header_size = path - start; + if (size < header_size) + /* malformed address */ + return nullptr; + + return {path, size - header_size}; +} + +#endif + #ifdef HAVE_TCP bool diff --git a/src/net/SocketAddress.hxx b/src/net/SocketAddress.hxx index 6a75352ac..b83cbf5b0 100644 --- a/src/net/SocketAddress.hxx +++ b/src/net/SocketAddress.hxx @@ -41,6 +41,8 @@ #include #endif +struct StringView; + /** * An OO wrapper for struct sockaddr. */ @@ -94,6 +96,17 @@ public: return GetFamily() != AF_UNSPEC; } +#ifdef HAVE_UN + /** + * Extract the local socket path (which may begin with a null + * byte, denoting an "abstract" socket). The return value's + * "size" attribute includes the null terminator. Returns + * nullptr if not applicable. + */ + gcc_pure + StringView GetLocalRaw() const noexcept; +#endif + #ifdef HAVE_TCP /** * Is this the IPv6 wildcard address (in6addr_any)?