From 5d84373c69d2c0dbb0234c47920b02443b37421c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 11 Jan 2016 21:30:07 -0800 Subject: [PATCH] Add a getifaddrs(3) debugging tool. ...disguised as a test, because that's the easiest way to keep an eye on it. Change-Id: Iec2531183790d12aec561d27645e5d400f69efbf --- tests/ifaddrs_test.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/ifaddrs_test.cpp b/tests/ifaddrs_test.cpp index bbaaec350..8159710b1 100644 --- a/tests/ifaddrs_test.cpp +++ b/tests/ifaddrs_test.cpp @@ -19,6 +19,9 @@ #include #include +#include +#include +#include #include TEST(ifaddrs, freeifaddrs_null) { @@ -61,3 +64,63 @@ TEST(ifaddrs, getifaddrs_smoke) { freeifaddrs(addrs); } + +static void print_sockaddr_ll(const char* what, const sockaddr* p) { + const sockaddr_ll* s = reinterpret_cast(p); + printf("\t%s\t", what); + for (int i = 0; i < s->sll_halen; ++i) { + if (i > 0) printf(":"); + printf("%02X", s->sll_addr[i]); + } + printf(" (%d bytes)\n", s->sll_halen); +} + +static void print_sockaddr_inet(const char* what, const sockaddr* addr) { + char host[NI_MAXHOST]; + int family = addr->sa_family; + int error = getnameinfo(addr, + (family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6), + host, NI_MAXHOST, nullptr, 0, NI_NUMERICHOST); + if (error != 0) { + printf("%d getnameinfo() failed: %s\n", family, gai_strerror(error)); + strcpy(host, "???"); + } + printf("\t%s: <%s>\n", what, host); +} + +static const char* family_to_name(int family) { + if (family == AF_INET) return "AF_INET"; + if (family == AF_INET6) return "AF_INET6"; + if (family == AF_PACKET) return "AF_PACKET"; + if (family == AF_UNSPEC) return "AF_UNSPEC"; + return "?"; +} + +// Not really a test, but a useful debugging tool. +TEST(ifaddrs, dump) { + ifaddrs* addrs; + ASSERT_EQ(0, getifaddrs(&addrs)); + + for (ifaddrs* ifa = addrs; ifa != nullptr; ifa = ifa->ifa_next) { + int family = ifa->ifa_addr ? ifa->ifa_addr->sa_family : + ifa->ifa_broadaddr ? ifa->ifa_broadaddr->sa_family : AF_UNSPEC; + + printf("%s\n\t%s (%d) flags=%#x\n", + ifa->ifa_name, family_to_name(family), family, ifa->ifa_flags); + + if (family == AF_PACKET) { + if (ifa->ifa_addr) print_sockaddr_ll("hwaddr", ifa->ifa_addr); + if (ifa->ifa_broadaddr) print_sockaddr_ll("hwbroad", ifa->ifa_addr); + } else if (family == AF_INET || family == AF_INET6) { + if (ifa->ifa_addr) print_sockaddr_inet("address", ifa->ifa_addr); + if (ifa->ifa_broadaddr && (ifa->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) != 0) { + print_sockaddr_inet((ifa->ifa_flags & IFF_BROADCAST) ? "broadcast" : "destination", + ifa->ifa_broadaddr); + } + } + + fflush(stdout); + } + + freeifaddrs(addrs); +}