Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 118 additions & 121 deletions tool/viz/getifaddrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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<UP,BROADCAST,RUNNING,MULTICAST>
inet6 fe80::fc54:ff:fefe:70d prefixlen 64 flags<128> class 0x20<link> ifidx 38
vnet1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
inet6 fe80::fc54:ff:fe6a:6545 prefixlen 64 flags<128> class 0x20<link> ifidx 44
enp51s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
inet6 fe80::ce3f:bd13:34ea:c170 prefixlen 64 flags<128> class 0x20<link> ifidx 43
inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255
wlp0s20f3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
inet6 fe80::9e1f:6462:15e2:2bf7 prefixlen 64 flags<128> class 0x20<link> ifidx 3
inet 192.168.1.95 netmask 255.255.255.0 broadcast 192.168.1.255
lo: flags=73<UP,RUNNING,LOOPBACK>
inet6 ::1 prefixlen 128 flags<128> class 0x10<host>
inet 127.0.0.1 netmask 255.0.0.0
virbr1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
inet 192.168.121.1 netmask 255.255.255.0 broadcast 192.168.121.255
virbr0: flags=4099<UP,BROADCAST,MULTICAST>
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) {
Expand All @@ -53,133 +62,121 @@ const char *sockaddr2str(const struct sockaddr *sa, char *buf, size_t size) {
}
}

int main(int argc, char *argv[]) {

// get network interface list
struct ifaddrs *ifaddrs;
if (getifaddrs(&ifaddrs)) {
perror("getifaddrs");
exit(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];
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, "addr: ", buf, "\n", NULL);
tinyprint(1, " inet ", buf, NULL);
}
if (sockaddr2str(ifa->ifa_netmask, buf, sizeof(buf))) {
tinyprint(1, "netmask: ", buf, "\n", NULL);
tinyprint(1, " netmask ", buf, NULL);
}
if ((ifa->ifa_flags & IFF_BROADCAST) &&
sockaddr2str(ifa->ifa_broadaddr, buf, sizeof(buf))) {
tinyprint(1, "broadcast: ", buf, "\n", NULL);
tinyprint(1, " broadcast ", buf, NULL);
} else if ((ifa->ifa_flags & IFF_POINTOPOINT) &&
sockaddr2str(ifa->ifa_dstaddr, buf, sizeof(buf))) {
tinyprint(1, "dstaddr: ", buf, "\n", NULL);
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);
}

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
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));
}

// #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);
FormatUint64(buf, prefixlen);
tinyprint(1, " prefixlen ", buf, 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);
}
int aflags = ((int *)ifa->ifa_data)[1];
FormatUint64(buf, aflags);
tinyprint(1, " flags<", buf, ">", 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);
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);
}
if (ifa->ifa_flags & IFF_ALLMULTI) {
tinyprint(1, " IFF_ALLMULTI", 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);
}
if (ifa->ifa_flags & IFF_NOARP) {
tinyprint(1, " IFF_NOARP", NULL);
}
tinyprint(1, ">\n", NULL);
}

int main(int argc, char *argv[]) {
// get network interface list
struct ifaddrs *ifaddrs;
if (getifaddrs(&ifaddrs)) {
perror("getifaddrs");
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
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 (ifa->ifa_flags & IFF_PROMISC) {
tinyprint(1, " IFF_PROMISC", 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);
}
tinyprint(1, "\n", NULL);

tinyprint(1, "\n", NULL);
ifa = ifa->ifa_next;
}

// perform cleanup
Expand Down