xref: /dragonfly/test/ifconf/ifconf.c (revision 1975d09e)
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