1818╚─────────────────────────────────────────────────────────────────────────────*/
1919#include "libc/calls/calls.h"
2020#include "libc/fmt/itoa.h"
21+ #include "libc/intrin/bsr.h"
22+ #include "libc/intrin/newbie.h"
23+ #include "libc/limits.h"
2124#include "libc/runtime/runtime.h"
2225#include "libc/sock/ifaddrs.h"
2326#include "libc/sock/sock.h"
2932#include "libc/sysv/consts/iff.h"
3033
3134/* example output:
32-
33- eth0
34- addr: 10.10.10.237
35- netmask: 255.255.255.0
36- broadcast: 10.10.10.255
37- flags: IFF_UP IFF_BROADCAST IFF_MULTICAST IFF_RUNNING
38-
39- lo
40- addr: 127.0.0.1
41- netmask: 255.0.0.0
42- flags: IFF_UP IFF_LOOPBACK IFF_RUNNING */
35+ vnet0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
36+ inet6 fe80::fc54:ff:fefe:70d prefixlen 64 flags<128> class 0x20<link> ifidx 38
37+ vnet1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
38+ inet6 fe80::fc54:ff:fe6a:6545 prefixlen 64 flags<128> class 0x20<link> ifidx 44
39+ enp51s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
40+ inet6 fe80::ce3f:bd13:34ea:c170 prefixlen 64 flags<128> class 0x20<link> ifidx 43
41+ inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255
42+ wlp0s20f3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
43+ inet6 fe80::9e1f:6462:15e2:2bf7 prefixlen 64 flags<128> class 0x20<link> ifidx 3
44+ inet 192.168.1.95 netmask 255.255.255.0 broadcast 192.168.1.255
45+ lo: flags=73<UP,RUNNING,LOOPBACK>
46+ inet6 ::1 prefixlen 128 flags<128> class 0x10<host>
47+ inet 127.0.0.1 netmask 255.0.0.0
48+ virbr1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>
49+ inet 192.168.121.1 netmask 255.255.255.0 broadcast 192.168.121.255
50+ virbr0: flags=4099<UP,BROADCAST,MULTICAST>
51+ inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 */
4352
4453const char * sockaddr2str (const struct sockaddr * sa , char * buf , size_t size ) {
4554 if (sa -> sa_family == AF_INET ) {
@@ -53,133 +62,121 @@ const char *sockaddr2str(const struct sockaddr *sa, char *buf, size_t size) {
5362 }
5463}
5564
56- int main (int argc , char * argv []) {
57-
58- // get network interface list
59- struct ifaddrs * ifaddrs ;
60- if (getifaddrs (& ifaddrs )) {
61- perror ("getifaddrs" );
62- exit (1 );
63- }
64-
65- // print network interface list
66- for (struct ifaddrs * ifa = ifaddrs ; ifa ; ifa = ifa -> ifa_next ) {
67- tinyprint (1 , ifa -> ifa_name , "\n" , NULL );
68-
69- char buf [128 ];
65+ void print_ifaddr (struct ifaddrs * ifa ) {
66+ char buf [128 ];
67+ if (ifa -> ifa_addr -> sa_family == AF_INET ) {
7068 if (sockaddr2str (ifa -> ifa_addr , buf , sizeof (buf ))) {
71- tinyprint (1 , "addr: " , buf , "\n" , NULL );
69+ tinyprint (1 , " inet " , buf , NULL );
7270 }
7371 if (sockaddr2str (ifa -> ifa_netmask , buf , sizeof (buf ))) {
74- tinyprint (1 , "netmask: " , buf , "\n" , NULL );
72+ tinyprint (1 , " netmask " , buf , NULL );
7573 }
7674 if ((ifa -> ifa_flags & IFF_BROADCAST ) &&
7775 sockaddr2str (ifa -> ifa_broadaddr , buf , sizeof (buf ))) {
78- tinyprint (1 , "broadcast: " , buf , "\n" , NULL );
76+ tinyprint (1 , " broadcast " , buf , NULL );
7977 } else if ((ifa -> ifa_flags & IFF_POINTOPOINT ) &&
8078 sockaddr2str (ifa -> ifa_dstaddr , buf , sizeof (buf ))) {
81- tinyprint (1 , "dstaddr: " , buf , "\n" , NULL );
79+ tinyprint (1 , " dstaddr " , buf , NULL );
80+ }
81+ } else if (ifa -> ifa_addr -> sa_family == AF_INET6 ) {
82+ if (sockaddr2str (ifa -> ifa_addr , buf , sizeof (buf ))) {
83+ tinyprint (1 , " inet6 " , buf , NULL );
8284 }
8385
84- if (ifa -> ifa_addr -> sa_family == AF_INET6 ) {
85- int scope = ((int * )ifa -> ifa_data )[0 ];
86- int aflags = ((int * )ifa -> ifa_data )[1 ];
87- // #define IPV6_ADDR_LOOPBACK 0x0010U
88- // #define IPV6_ADDR_LINKLOCAL 0x0020U
89- // #define IPV6_ADDR_SITELOCAL 0x0040U
86+ uint128_t netmask = ~be128toh (* ((uint128_t * )(& (
87+ ((const struct sockaddr_in6 * )ifa -> ifa_netmask )-> sin6_addr ))));
88+ int prefixlen = 128 ;
89+ if (netmask > 0 ) {
90+ uint64_t hi = (uint64_t )(netmask >> 64 );
91+ prefixlen = (hi > 0 ) ? (63 - bsrl (hi )) : (127 - bsrl ((uint64_t )netmask ));
92+ }
9093
91- // #define IFA_F_TEMPORARY 0x01
92- // #define IFA_F_NODAD 0x02
93- // #define IFA_F_OPTIMISTIC 0x04
94- // #define IFA_F_DADFAILED 0x08
95- // #define IFA_F_HOMEADDRESS 0x10
96- // #define IFA_F_DEPRECATED 0x20
97- // #define IFA_F_TENTATIVE 0x40
98- // #define IFA_F_PERMANENT 0x80
99- // #define IFA_F_MANAGETEMPADDR 0x100
100- // #define IFA_F_NOPREFIXROUTE 0x200
101- // #define IFA_F_MCAUTOJOIN 0x400
102- // #define IFA_F_STABLE_PRIVACY 0x800
103- tinyprint (1 , "scope:" , NULL );
104- if (scope == 0x10 ) {
105- tinyprint (1 , " loopback" , NULL );
106- }
107- if (scope == 0x20 ) {
108- tinyprint (1 , " linklocal" , NULL );
109- }
110- if (scope == 0x40 ) {
111- tinyprint (1 , " sitelocal" , NULL );
112- }
113- if (scope == 0x00 ) {
114- tinyprint (1 , " global" , NULL );
115- }
116- tinyprint (1 , "\n" , NULL );
94+ FormatUint64 (buf , prefixlen );
95+ tinyprint (1 , " prefixlen " , buf , NULL );
11796
118- tinyprint (1 , "addr flags:" , NULL );
119- if (aflags & 0x01 ) {
120- tinyprint (1 , " temporary" , NULL );
121- }
122- if (aflags & 0x02 ) {
123- tinyprint (1 , " nodad" , NULL );
124- }
125- if (aflags & 0x04 ) {
126- tinyprint (1 , " optimistic" , NULL );
127- }
128- if (aflags & 0x08 ) {
129- tinyprint (1 , " dadfailed" , NULL );
130- }
131- if (aflags & 0x10 ) {
132- tinyprint (1 , " homeaddress" , NULL );
133- }
134- if (aflags & 0x20 ) {
135- tinyprint (1 , " deprecated" , NULL );
136- }
137- if (aflags & 0x40 ) {
138- tinyprint (1 , " tentative" , NULL );
139- }
140- if (aflags & 0x80 ) {
141- tinyprint (1 , " permanent" , NULL );
142- }
143- if (aflags & 0x100 ) {
144- tinyprint (1 , " managetempaddr" , NULL );
145- }
146- if (aflags & 0x200 ) {
147- tinyprint (1 , " noprefixroute" , NULL );
148- }
149- if (aflags & 0x400 ) {
150- tinyprint (1 , " mcautojoin" , NULL );
151- }
152- if (aflags & 0x800 ) {
153- tinyprint (1 , " stable_privacy" , NULL );
154- }
155- tinyprint (1 , "\n" , NULL );
156- }
97+ int aflags = ((int * )ifa -> ifa_data )[1 ];
98+ FormatUint64 (buf , aflags );
99+ tinyprint (1 , " flags<" , buf , ">" , NULL );
157100
158- tinyprint (1 , "flags:" , NULL );
159- if (ifa -> ifa_flags & IFF_UP ) {
160- tinyprint (1 , " IFF_UP" , NULL );
161- }
162- if (ifa -> ifa_flags & IFF_DEBUG ) {
163- tinyprint (1 , " IFF_DEBUG" , NULL );
164- }
165- if (ifa -> ifa_flags & IFF_LOOPBACK ) {
166- tinyprint (1 , " IFF_LOOPBACK" , NULL );
167- }
168- if (ifa -> ifa_flags & IFF_MULTICAST ) {
169- tinyprint (1 , " IFF_MULTICAST" , NULL );
101+ int scope = ((((int * )ifa -> ifa_data )[0 ]) / 16 ) % 5 ;
102+ // #define IPV6_ADDR_GLOBAL 0x0000U
103+ // #define IPV6_ADDR_LOOPBACK 0x0010U
104+ // #define IPV6_ADDR_LINKLOCAL 0x0020U
105+ // #define IPV6_ADDR_SITELOCAL 0x0040U
106+ char * addr_types [] = {"global" , "host" , "link" , "??" , "site" };
107+ buf [0 ] = '0' + scope ;
108+ buf [1 ] = '\0' ;
109+ tinyprint (1 , " class 0x" , buf , "0<" , addr_types [scope ], ">" , NULL );
110+
111+ if (scope == 2 || scope == 4 ) { // linklocal or sitelocal
112+ FormatUint64 (buf ,
113+ ((const struct sockaddr_in6 * )ifa -> ifa_addr )-> sin6_scope_id );
114+ tinyprint (1 , " ifidx " , buf , NULL );
170115 }
171- if (ifa -> ifa_flags & IFF_ALLMULTI ) {
172- tinyprint (1 , " IFF_ALLMULTI" , NULL );
116+ }
117+ tinyprint (1 , "\n" , NULL );
118+ }
119+ void print_iface (struct ifaddrs * ifa ) {
120+ char buf [32 ];
121+ FormatUint64 (buf , ifa -> ifa_flags );
122+ tinyprint (1 , ifa -> ifa_name , ": flags=" , buf , "<" , NULL );
123+ char * sflags [] = {"UP" , "BROADCAST" , "POINTOPOINT" , "RUNNING" ,
124+ "DEBUG" , "LOOPBACK" , "MULTICAST" , "ALLMULTI" ,
125+ "NOARP" , "IPROMISC" };
126+ int iflags [] = {IFF_UP , IFF_BROADCAST , IFF_POINTOPOINT , IFF_RUNNING ,
127+ IFF_DEBUG , IFF_LOOPBACK , IFF_MULTICAST , IFF_ALLMULTI ,
128+ IFF_NOARP , IFF_PROMISC };
129+ int first = 1 ;
130+ for (int i = 0 ; i < (sizeof (sflags ) / sizeof (* sflags )); i ++ ) {
131+ if (ifa -> ifa_flags & iflags [i ]) {
132+ if (!first ) {
133+ tinyprint (1 , "," , NULL );
134+ }
135+ first = 0 ;
136+ tinyprint (1 , sflags [i ], NULL );
173137 }
174- if (ifa -> ifa_flags & IFF_NOARP ) {
175- tinyprint (1 , " IFF_NOARP" , NULL );
138+ }
139+ tinyprint (1 , ">\n" , NULL );
140+ }
141+
142+ int main (int argc , char * argv []) {
143+ // get network interface list
144+ struct ifaddrs * ifaddrs ;
145+ if (getifaddrs (& ifaddrs )) {
146+ perror ("getifaddrs" );
147+ exit (1 );
148+ }
149+
150+ struct ifaddrs * ifaddrs_next_if = ifaddrs ;
151+ struct ifaddrs * ifaddrs_curr_if = NULL ;
152+ struct ifaddrs * ifa = NULL ;
153+ int first = 1 ;
154+ // print network interface list
155+ while (ifa || ifaddrs_next_if ) {
156+ if (!ifa ) {
157+ if (!first ) {
158+ tinyprint (1 , "\n" , NULL );
159+ first = 0 ;
160+ }
161+ ifaddrs_curr_if = ifaddrs_next_if ;
162+ ifa = ifaddrs_next_if ;
163+ ifaddrs_next_if = NULL ;
164+ print_iface (ifa );
176165 }
177- if (ifa -> ifa_flags & IFF_PROMISC ) {
178- tinyprint (1 , " IFF_PROMISC" , NULL );
166+ if (strcmp (ifa -> ifa_name , ifaddrs_curr_if -> ifa_name )) {
167+ if (!ifaddrs_next_if ) {
168+ struct ifaddrs * ifa2 = ifaddrs ;
169+ while (ifa2 != ifa && strcmp (ifa -> ifa_name , ifa2 -> ifa_name )) {
170+ ifa2 = ifa2 -> ifa_next ;
171+ }
172+ if (ifa2 == ifa ) {
173+ ifaddrs_next_if = ifa ;
174+ }
175+ }
176+ } else {
177+ print_ifaddr (ifa );
179178 }
180- tinyprint (1 , "\n" , NULL );
181-
182- tinyprint (1 , "\n" , NULL );
179+ ifa = ifa -> ifa_next ;
183180 }
184181
185182 // perform cleanup
0 commit comments