From 99b069c11b47590f76681d410cf0b2f662127812 Mon Sep 17 00:00:00 2001 From: Hugues Morisset Date: Sun, 10 Aug 2025 17:17:27 +0200 Subject: [PATCH] Make tools/getifaddrs output closer to ifconfig This is easier to read with a lots of addresses and give more infos --- tool/viz/getifaddrs.c | 251 +++++++++++++++++++++--------------------- 1 file changed, 124 insertions(+), 127 deletions(-) diff --git a/tool/viz/getifaddrs.c b/tool/viz/getifaddrs.c index 142e8005e..30b00a671 100644 --- a/tool/viz/getifaddrs.c +++ b/tool/viz/getifaddrs.c @@ -18,6 +18,9 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/fmt/itoa.h" +#include "libc/intrin/bsr.h" +#include "libc/intrin/newbie.h" +#include "libc/limits.h" #include "libc/runtime/runtime.h" #include "libc/sock/ifaddrs.h" #include "libc/sock/sock.h" @@ -29,17 +32,23 @@ #include "libc/sysv/consts/iff.h" /* example output: - - eth0 - addr: 10.10.10.237 - netmask: 255.255.255.0 - broadcast: 10.10.10.255 - flags: IFF_UP IFF_BROADCAST IFF_MULTICAST IFF_RUNNING - - lo - addr: 127.0.0.1 - netmask: 255.0.0.0 - flags: IFF_UP IFF_LOOPBACK IFF_RUNNING */ +vnet0: flags=4163 + inet6 fe80::fc54:ff:fefe:70d prefixlen 64 flags<128> class 0x20 ifidx 38 +vnet1: flags=4163 + inet6 fe80::fc54:ff:fe6a:6545 prefixlen 64 flags<128> class 0x20 ifidx 44 +enp51s0: flags=4163 + inet6 fe80::ce3f:bd13:34ea:c170 prefixlen 64 flags<128> class 0x20 ifidx 43 + inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255 +wlp0s20f3: flags=4163 + inet6 fe80::9e1f:6462:15e2:2bf7 prefixlen 64 flags<128> class 0x20 ifidx 3 + inet 192.168.1.95 netmask 255.255.255.0 broadcast 192.168.1.255 +lo: flags=73 + inet6 ::1 prefixlen 128 flags<128> class 0x10 + inet 127.0.0.1 netmask 255.0.0.0 +virbr1: flags=4163 + inet 192.168.121.1 netmask 255.255.255.0 broadcast 192.168.121.255 +virbr0: flags=4099 + inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 */ const char *sockaddr2str(const struct sockaddr *sa, char *buf, size_t size) { if (sa->sa_family == AF_INET) { @@ -53,8 +62,84 @@ const char *sockaddr2str(const struct sockaddr *sa, char *buf, size_t size) { } } -int main(int argc, char *argv[]) { +void print_ifaddr(struct ifaddrs *ifa) { + char buf[128]; + if (ifa->ifa_addr->sa_family == AF_INET) { + if (sockaddr2str(ifa->ifa_addr, buf, sizeof(buf))) { + tinyprint(1, " inet ", buf, NULL); + } + if (sockaddr2str(ifa->ifa_netmask, buf, sizeof(buf))) { + tinyprint(1, " netmask ", buf, NULL); + } + if ((ifa->ifa_flags & IFF_BROADCAST) && + sockaddr2str(ifa->ifa_broadaddr, buf, sizeof(buf))) { + tinyprint(1, " broadcast ", buf, NULL); + } else if ((ifa->ifa_flags & IFF_POINTOPOINT) && + sockaddr2str(ifa->ifa_dstaddr, buf, sizeof(buf))) { + tinyprint(1, " dstaddr ", buf, NULL); + } + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + if (sockaddr2str(ifa->ifa_addr, buf, sizeof(buf))) { + tinyprint(1, " inet6 ", buf, NULL); + } + uint128_t netmask = ~be128toh(*((uint128_t *)(&( + ((const struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr)))); + int prefixlen = 128; + if (netmask > 0) { + uint64_t hi = (uint64_t)(netmask >> 64); + prefixlen = (hi > 0) ? (63 - bsrl(hi)) : (127 - bsrl((uint64_t)netmask)); + } + + FormatUint64(buf, prefixlen); + tinyprint(1, " prefixlen ", buf, NULL); + + int aflags = ((int *)ifa->ifa_data)[1]; + FormatUint64(buf, aflags); + tinyprint(1, " flags<", buf, ">", NULL); + + int scope = ((((int *)ifa->ifa_data)[0]) / 16) % 5; + // #define IPV6_ADDR_GLOBAL 0x0000U + // #define IPV6_ADDR_LOOPBACK 0x0010U + // #define IPV6_ADDR_LINKLOCAL 0x0020U + // #define IPV6_ADDR_SITELOCAL 0x0040U + char *addr_types[] = {"global", "host", "link", "??", "site"}; + buf[0] = '0' + scope; + buf[1] = '\0'; + tinyprint(1, " class 0x", buf, "0<", addr_types[scope], ">", NULL); + + if (scope == 2 || scope == 4) { // linklocal or sitelocal + FormatUint64(buf, + ((const struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id); + tinyprint(1, " ifidx ", buf, NULL); + } + } + tinyprint(1, "\n", NULL); +} +void print_iface(struct ifaddrs *ifa) { + char buf[32]; + FormatUint64(buf, ifa->ifa_flags); + tinyprint(1, ifa->ifa_name, ": flags=", buf, "<", NULL); + char *sflags[] = {"UP", "BROADCAST", "POINTOPOINT", "RUNNING", + "DEBUG", "LOOPBACK", "MULTICAST", "ALLMULTI", + "NOARP", "IPROMISC"}; + int iflags[] = {IFF_UP, IFF_BROADCAST, IFF_POINTOPOINT, IFF_RUNNING, + IFF_DEBUG, IFF_LOOPBACK, IFF_MULTICAST, IFF_ALLMULTI, + IFF_NOARP, IFF_PROMISC}; + int first = 1; + for (int i = 0; i < (sizeof(sflags) / sizeof(*sflags)); i++) { + if (ifa->ifa_flags & iflags[i]) { + if (!first) { + tinyprint(1, ",", NULL); + } + first = 0; + tinyprint(1, sflags[i], NULL); + } + } + tinyprint(1, ">\n", NULL); +} + +int main(int argc, char *argv[]) { // get network interface list struct ifaddrs *ifaddrs; if (getifaddrs(&ifaddrs)) { @@ -62,124 +147,36 @@ int main(int argc, char *argv[]) { exit(1); } + struct ifaddrs *ifaddrs_next_if = ifaddrs; + struct ifaddrs *ifaddrs_curr_if = NULL; + struct ifaddrs *ifa = NULL; + int first = 1; // print network interface list - for (struct ifaddrs *ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { - tinyprint(1, ifa->ifa_name, "\n", NULL); - - char buf[128]; - if (sockaddr2str(ifa->ifa_addr, buf, sizeof(buf))) { - tinyprint(1, "addr: ", buf, "\n", NULL); + while (ifa || ifaddrs_next_if) { + if (!ifa) { + if (!first) { + tinyprint(1, "\n", NULL); + first = 0; + } + ifaddrs_curr_if = ifaddrs_next_if; + ifa = ifaddrs_next_if; + ifaddrs_next_if = NULL; + print_iface(ifa); } - if (sockaddr2str(ifa->ifa_netmask, buf, sizeof(buf))) { - tinyprint(1, "netmask: ", buf, "\n", NULL); + if (strcmp(ifa->ifa_name, ifaddrs_curr_if->ifa_name)) { + if (!ifaddrs_next_if) { + struct ifaddrs *ifa2 = ifaddrs; + while (ifa2 != ifa && strcmp(ifa->ifa_name, ifa2->ifa_name)) { + ifa2 = ifa2->ifa_next; + } + if (ifa2 == ifa) { + ifaddrs_next_if = ifa; + } + } + } else { + print_ifaddr(ifa); } - if ((ifa->ifa_flags & IFF_BROADCAST) && - sockaddr2str(ifa->ifa_broadaddr, buf, sizeof(buf))) { - tinyprint(1, "broadcast: ", buf, "\n", NULL); - } else if ((ifa->ifa_flags & IFF_POINTOPOINT) && - sockaddr2str(ifa->ifa_dstaddr, buf, sizeof(buf))) { - tinyprint(1, "dstaddr: ", buf, "\n", NULL); - } - - if (ifa->ifa_addr->sa_family == AF_INET6) { - int scope = ((int *)ifa->ifa_data)[0]; - int aflags = ((int *)ifa->ifa_data)[1]; - // #define IPV6_ADDR_LOOPBACK 0x0010U - // #define IPV6_ADDR_LINKLOCAL 0x0020U - // #define IPV6_ADDR_SITELOCAL 0x0040U - - // #define IFA_F_TEMPORARY 0x01 - // #define IFA_F_NODAD 0x02 - // #define IFA_F_OPTIMISTIC 0x04 - // #define IFA_F_DADFAILED 0x08 - // #define IFA_F_HOMEADDRESS 0x10 - // #define IFA_F_DEPRECATED 0x20 - // #define IFA_F_TENTATIVE 0x40 - // #define IFA_F_PERMANENT 0x80 - // #define IFA_F_MANAGETEMPADDR 0x100 - // #define IFA_F_NOPREFIXROUTE 0x200 - // #define IFA_F_MCAUTOJOIN 0x400 - // #define IFA_F_STABLE_PRIVACY 0x800 - tinyprint(1, "scope:", NULL); - if (scope == 0x10) { - tinyprint(1, " loopback", NULL); - } - if (scope == 0x20) { - tinyprint(1, " linklocal", NULL); - } - if (scope == 0x40) { - tinyprint(1, " sitelocal", NULL); - } - if (scope == 0x00) { - tinyprint(1, " global", NULL); - } - tinyprint(1, "\n", NULL); - - tinyprint(1, "addr flags:", NULL); - if (aflags & 0x01) { - tinyprint(1, " temporary", NULL); - } - if (aflags & 0x02) { - tinyprint(1, " nodad", NULL); - } - if (aflags & 0x04) { - tinyprint(1, " optimistic", NULL); - } - if (aflags & 0x08) { - tinyprint(1, " dadfailed", NULL); - } - if (aflags & 0x10) { - tinyprint(1, " homeaddress", NULL); - } - if (aflags & 0x20) { - tinyprint(1, " deprecated", NULL); - } - if (aflags & 0x40) { - tinyprint(1, " tentative", NULL); - } - if (aflags & 0x80) { - tinyprint(1, " permanent", NULL); - } - if (aflags & 0x100) { - tinyprint(1, " managetempaddr", NULL); - } - if (aflags & 0x200) { - tinyprint(1, " noprefixroute", NULL); - } - if (aflags & 0x400) { - tinyprint(1, " mcautojoin", NULL); - } - if (aflags & 0x800) { - tinyprint(1, " stable_privacy", NULL); - } - tinyprint(1, "\n", NULL); - } - - tinyprint(1, "flags:", NULL); - if (ifa->ifa_flags & IFF_UP) { - tinyprint(1, " IFF_UP", NULL); - } - if (ifa->ifa_flags & IFF_DEBUG) { - tinyprint(1, " IFF_DEBUG", NULL); - } - if (ifa->ifa_flags & IFF_LOOPBACK) { - tinyprint(1, " IFF_LOOPBACK", NULL); - } - if (ifa->ifa_flags & IFF_MULTICAST) { - tinyprint(1, " IFF_MULTICAST", NULL); - } - if (ifa->ifa_flags & IFF_ALLMULTI) { - tinyprint(1, " IFF_ALLMULTI", NULL); - } - if (ifa->ifa_flags & IFF_NOARP) { - tinyprint(1, " IFF_NOARP", NULL); - } - if (ifa->ifa_flags & IFF_PROMISC) { - tinyprint(1, " IFF_PROMISC", NULL); - } - tinyprint(1, "\n", NULL); - - tinyprint(1, "\n", NULL); + ifa = ifa->ifa_next; } // perform cleanup