1 #include <sys/types.h> 2 #include <sys/ioctl.h> 3 #include <sys/socket.h> 4 5 #include <arpa/inet.h> 6 #include <netinet/in.h> 7 #include <net/if.h> 8 #include <net/if_dl.h> 9 10 #include <err.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 16 #define NADDRS 128 17 18 /* XXX _SIZEOF_ADDR_IFREQ should accept ptr */ 19 #define _SIZEOF_ADDR_IFREQ1(ifr) \ 20 ((ifr)->ifr_addr.sa_len > sizeof(struct sockaddr) ? \ 21 (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ 22 (ifr)->ifr_addr.sa_len) : sizeof(struct ifreq)) 23 24 static void 25 usage(const char *cmd) 26 { 27 fprintf(stderr, "%s [-n naddrs]\n", cmd); 28 exit(1); 29 } 30 31 int 32 main(int argc, char *argv[]) 33 { 34 struct ifconf ifc; 35 struct ifreq *ifr; 36 caddr_t pos; 37 int s, naddrs, opt; 38 39 naddrs = NADDRS; 40 41 while ((opt = getopt(argc, argv, "n:")) != -1) { 42 switch (opt) { 43 case 'n': 44 naddrs = strtol(optarg, NULL, 10); 45 break; 46 default: 47 usage(argv[0]); 48 } 49 } 50 if (naddrs <= 0) 51 usage(argv[0]); 52 53 s = socket(AF_INET, SOCK_DGRAM, 0); 54 if (s < 0) 55 err(2, "socket failed"); 56 57 memset(&ifc, 0, sizeof(ifc)); 58 ifc.ifc_len = sizeof(struct sockaddr_storage) * naddrs; 59 ifc.ifc_buf = malloc(ifc.ifc_len); 60 if (ifc.ifc_buf == NULL) 61 err(2, "malloc failed"); 62 63 if (ioctl(s, SIOCGIFCONF, &ifc, sizeof(ifc)) < 0) 64 err(2, "ioctl failed"); 65 66 pos = ifc.ifc_buf; 67 while (ifc.ifc_len >= (int)sizeof(*ifr)) { 68 int len; 69 70 ifr = (struct ifreq *)pos; 71 len = _SIZEOF_ADDR_IFREQ1(ifr); 72 if (ifc.ifc_len < len) 73 err(2, "invalid ifc.ifc_len"); 74 75 if (ifr->ifr_addr.sa_family == AF_UNSPEC) { 76 printf("%s: no address\n", ifr->ifr_name); 77 } else if (ifr->ifr_addr.sa_family == AF_INET || 78 ifr->ifr_addr.sa_family == AF_INET6) { 79 char addr_str[INET6_ADDRSTRLEN]; 80 const void *src; 81 const char *ret; 82 83 if (ifr->ifr_addr.sa_family == AF_INET) { 84 const struct sockaddr_in *in = 85 (const struct sockaddr_in *)&ifr->ifr_addr; 86 src = &in->sin_addr; 87 } else { 88 const struct sockaddr_in6 *in6 = 89 (const struct sockaddr_in6 *)&ifr->ifr_addr; 90 src = &in6->sin6_addr; 91 } 92 93 ret = inet_ntop(ifr->ifr_addr.sa_family, src, 94 addr_str, sizeof(addr_str)); 95 if (ret == NULL) 96 err(2, "inet_ntop failed"); 97 printf("%s: inet%c %s\n", ifr->ifr_name, 98 ifr->ifr_addr.sa_family == AF_INET ? '4' : '6', 99 ret); 100 } else if (ifr->ifr_addr.sa_family == AF_LINK) { 101 const struct sockaddr_dl *dl = 102 (const struct sockaddr_dl *)&ifr->ifr_addr; 103 104 printf("%s: link%d\n", ifr->ifr_name, dl->sdl_index); 105 } else { 106 printf("%s: unknown family %d\n", ifr->ifr_name, 107 ifr->ifr_addr.sa_family); 108 } 109 110 ifc.ifc_len -= len; 111 pos += len; 112 } 113 if (ifc.ifc_len != 0) 114 printf("ifc_len left %d\n", ifc.ifc_len); 115 116 exit(0); 117 } 118