Merge branch 'vendor/OPENRESOLV' with the following changes:
[dragonfly.git] / test / ifconf / ifconf.c
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 }