xref: /freebsd/tools/tools/ifinfo/ifinfo.c (revision d84870d90bafe75eb87759df0ab41ff0214c866e)
1 /*
2  * Copyright 1996 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and
5  * its documentation for any purpose and without fee is hereby
6  * granted, provided that both the above copyright notice and this
7  * permission notice appear in all copies, that both the above
8  * copyright notice and this permission notice appear in all
9  * supporting documentation, and that the name of M.I.T. not be used
10  * in advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.  M.I.T. makes
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 #include <sys/types.h>
30 #include <sys/socket.h>		/* for PF_LINK */
31 #include <sys/sysctl.h>
32 #include <sys/time.h>
33 #include <sys/mbuf.h>
34 
35 #include <err.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sysexits.h>
41 #include <unistd.h>
42 #include <stdbool.h>
43 #include <ctype.h>
44 
45 #include <net/if.h>
46 #include <net/if_types.h>
47 #include <net/if_mib.h>
48 
49 #include "ifinfo.h"
50 
51 static void printit(const struct ifmibdata *, const char *);
52 static const char *iftype(int);
53 static int isit(int, char **, const char *);
54 static printfcn findlink(int);
55 
56 static void
usage(const char * argv0)57 usage(const char *argv0)
58 {
59 	fprintf(stderr, "%s: usage:\n\t%s [-l]\n", argv0, argv0);
60 	exit(EX_USAGE);
61 }
62 
63 int
main(int argc,char ** argv)64 main(int argc, char **argv)
65 {
66 	int i, maxifno, retval;
67 	struct ifmibdata ifmd;
68 	int name[6];
69 	size_t len;
70 	int c;
71 	int dolink = 0;
72 	void *linkmib;
73 	size_t linkmiblen;
74 	printfcn pf;
75 	char *dname;
76 
77 	while ((c = getopt(argc, argv, "l")) != -1) {
78 		switch(c) {
79 		case 'l':
80 			dolink = 1;
81 			break;
82 		default:
83 			usage(argv[0]);
84 		}
85 	}
86 
87 	retval = 1;
88 
89 	name[0] = CTL_NET;
90 	name[1] = PF_LINK;
91 	name[2] = NETLINK_GENERIC;
92 	name[3] = IFMIB_SYSTEM;
93 	name[4] = IFMIB_IFCOUNT;
94 
95 	len = sizeof maxifno;
96 	if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0)
97 		err(EX_OSERR, "sysctl(net.link.generic.system.ifcount)");
98 
99 	for (i = 1; i <= maxifno; i++) {
100 		len = sizeof ifmd;
101 		name[3] = IFMIB_IFDATA;
102 		name[4] = i;
103 		name[5] = IFDATA_GENERAL;
104 		if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) {
105 			if (errno == ENOENT)
106 				continue;
107 
108 			err(EX_OSERR, "sysctl(net.link.ifdata.%d.general)",
109 			    i);
110 		}
111 
112 		if (!isit(argc - optind, argv + optind, ifmd.ifmd_name))
113 			continue;
114 
115 		dname = NULL;
116 		len = 0;
117 		name[5] = IFDATA_DRIVERNAME;
118 		if (sysctl(name, 6, NULL, &len, 0, 0) < 0) {
119 			warn("sysctl(net.link.ifdata.%d.drivername)", i);
120 		} else {
121 			if ((dname = malloc(len)) == NULL)
122 				err(EX_OSERR, NULL);
123 			if (sysctl(name, 6, dname, &len, 0, 0) < 0) {
124 				warn("sysctl(net.link.ifdata.%d.drivername)",
125 				    i);
126 				free(dname);
127 				dname = NULL;
128 			}
129 		}
130 		printit(&ifmd, dname);
131 		free(dname);
132 		if (dolink && (pf = findlink(ifmd.ifmd_data.ifi_type))) {
133 			name[5] = IFDATA_LINKSPECIFIC;
134 			if (sysctl(name, 6, 0, &linkmiblen, 0, 0) < 0)
135 				err(EX_OSERR,
136 				    "sysctl(net.link.ifdata.%d.linkspec) size",
137 				    i);
138 			linkmib = malloc(linkmiblen);
139 			if (!linkmib)
140 				err(EX_OSERR, "malloc(%lu)",
141 				    (u_long)linkmiblen);
142 			if (sysctl(name, 6, linkmib, &linkmiblen, 0, 0) < 0)
143 				err(EX_OSERR,
144 				    "sysctl(net.link.ifdata.%d.linkspec)",
145 				    i);
146 			pf(linkmib, linkmiblen);
147 			free(linkmib);
148 		}
149 		retval = 0;
150 	}
151 
152 	return retval;
153 }
154 
155 /* code after this line copied or based on code from src/sys/kern/subr_prf.c */
156 static inline bool
isbitpos(char c)157 isbitpos(char c)
158 {
159 	return (c != '\0' && (c <= ' ' || (c & 0x80) != 0));
160 }
161 
162 static inline bool
isprintnospace(char c)163 isprintnospace(char c)
164 {
165 	return (isprint(c) && c != ' ');
166 }
167 
168 static void
print_bits(uintmax_t num,const char * bitstring)169 print_bits(uintmax_t num, const char *bitstring)
170 {
171 	bool first;
172 	const char *c;
173 	int shift;
174 
175 	c = ++bitstring;
176 	first = true;
177 	while (isbitpos(*c)) {
178 		if ((*c & 0x80) != 0)
179 			shift = *c++ & 0x7f;
180 		else
181 			shift = *c++ - 1;
182 		if (num & (1ULL << shift)) {
183 			putchar(first ? (first = false, '<') : ',');
184 			for (; isprintnospace(*c); ++c)
185 				putchar(*c);
186 		} else
187 			for (; isprintnospace(*c); ++c)
188 				continue;
189 	}
190 	if (!first) {
191 		putchar('>');
192 	}
193 }
194 /* code before this line copied or based on code from src/sys/kern/subr_prf.c */
195 
196 static void
printit(const struct ifmibdata * ifmd,const char * dname)197 printit(const struct ifmibdata *ifmd, const char *dname)
198 {
199 	printf("Interface %.*s", IFNAMSIZ, ifmd->ifmd_name);
200 	if (dname != NULL)
201 		printf(" (%s)", dname);
202 	printf(":\n");
203 	printf("\tflags: %x\n", ifmd->ifmd_flags);
204 	printf("\tpromiscuous listeners: %d\n", ifmd->ifmd_pcount);
205 	printf("\tsend queue length: %d\n", ifmd->ifmd_snd_len);
206 	printf("\tsend queue max length: %d\n", ifmd->ifmd_snd_maxlen);
207 	printf("\tsend queue drops: %d\n", ifmd->ifmd_snd_drops);
208 	printf("\ttype: %s\n", iftype(ifmd->ifmd_data.ifi_type));
209 	printf("\taddress length: %d\n", ifmd->ifmd_data.ifi_addrlen);
210 	printf("\theader length: %d\n", ifmd->ifmd_data.ifi_hdrlen);
211 	printf("\tlink state: %u\n", ifmd->ifmd_data.ifi_link_state);
212 	printf("\tvhid: %u\n", ifmd->ifmd_data.ifi_vhid);
213 	printf("\tdatalen: %u\n", ifmd->ifmd_data.ifi_datalen);
214 	printf("\tmtu: %u\n", ifmd->ifmd_data.ifi_mtu);
215 	printf("\tmetric: %u\n", ifmd->ifmd_data.ifi_metric);
216 	printf("\tline rate: %lu bit/s\n", ifmd->ifmd_data.ifi_baudrate);
217 	printf("\tpackets received: %lu\n", ifmd->ifmd_data.ifi_ipackets);
218 	printf("\tinput errors: %lu\n", ifmd->ifmd_data.ifi_ierrors);
219 	printf("\tpackets transmitted: %lu\n", ifmd->ifmd_data.ifi_opackets);
220 	printf("\toutput errors: %lu\n", ifmd->ifmd_data.ifi_oerrors);
221 	printf("\tcollisions: %lu\n", ifmd->ifmd_data.ifi_collisions);
222 	printf("\tbytes received: %lu\n", ifmd->ifmd_data.ifi_ibytes);
223 	printf("\tbytes transmitted: %lu\n", ifmd->ifmd_data.ifi_obytes);
224 	printf("\tmulticasts received: %lu\n", ifmd->ifmd_data.ifi_imcasts);
225 	printf("\tmulticasts transmitted: %lu\n", ifmd->ifmd_data.ifi_omcasts);
226 	printf("\tinput queue drops: %lu\n", ifmd->ifmd_data.ifi_iqdrops);
227 	printf("\tpackets for unknown protocol: %lu\n",
228 	       ifmd->ifmd_data.ifi_noproto);
229 	printf("\tHW offload capabilities: 0x%lx",
230 	    ifmd->ifmd_data.ifi_hwassist);
231 	print_bits(ifmd->ifmd_data.ifi_hwassist, CSUM_BITS);
232 	printf("\n");
233 	printf("\tuptime at attach or stat reset: %lu\n",
234 	    ifmd->ifmd_data.ifi_epoch);
235 #ifdef notdef
236 	printf("\treceive timing: %lu usec\n", ifmd->ifmd_data.ifi_recvtiming);
237 	printf("\ttransmit timing: %lu usec\n",
238 	       ifmd->ifmd_data.ifi_xmittiming);
239 #endif
240 }
241 
242 static const char *const if_types[] = {
243 	"reserved",
244 	"other",
245 	"BBN 1822",
246 	"HDH 1822",
247 	"X.25 DDN",
248 	"X.25",
249 	"Ethernet",
250 	"ISO 8802-3 CSMA/CD",
251 	"ISO 8802-4 Token Bus",
252 	"ISO 8802-5 Token Ring",
253 	"ISO 8802-6 DQDB MAN",
254 	"StarLAN",
255 	"Proteon proNET-10",
256 	"Proteon proNET-80",
257 	"HyperChannel",
258 	"FDDI",
259 	"LAP-B",
260 	"SDLC",
261 	"T-1",
262 	"CEPT",
263 	"Basic rate ISDN",
264 	"Primary rate ISDN",
265 	"Proprietary P2P",
266 	"PPP",
267 	"Loopback",
268 	"ISO CLNP over IP",
269 	"Experimental Ethernet",
270 	"XNS over IP",
271 	"SLIP",
272 	"Ultra Technologies",
273 	"DS-3",
274 	"SMDS",
275 	"Frame Relay",
276 	"RS-232 serial",
277 	"Parallel printer port",
278 	"ARCNET",
279 	"ARCNET+",
280 	"ATM",
281 	"MIOX25",
282 	"SONET/SDH",
283 	"X25PLE",
284 	"ISO 8802-2 LLC",
285 	"LocalTalk",
286 	"SMDSDXI",
287 	"Frame Relay DCE",
288 	"V.35",
289 	"HSSI",
290 	"HIPPI",
291 	"Generic Modem",
292 	"ATM AAL5",
293 	"SONETPATH",
294 	"SONETVT",
295 	"SMDS InterCarrier Interface",
296 	"Proprietary virtual interface",
297 	"Proprietary multiplexing",
298 	"Generic tunnel interface",
299 	"IPv6-to-IPv4 TCP relay capturing interface",
300 	"6to4 tunnel interface"
301 };
302 #define	NIFTYPES (int)((sizeof if_types)/(sizeof if_types[0]))
303 
304 static const char *
iftype(int type)305 iftype(int type)
306 {
307 	static char buf[256];
308 
309 	if (type <= 0 || type >= NIFTYPES) {
310 		sprintf(buf, "unknown type %d", type);
311 		return buf;
312 	}
313 
314 	return if_types[type];
315 }
316 
317 static int
isit(int argc,char ** argv,const char * name)318 isit(int argc, char **argv, const char *name)
319 {
320 	if (argc == 0)
321 		return 1;
322 	for (argc = 0; argv[argc]; argc++) {
323 		if (strncmp(argv[argc], name, IFNAMSIZ) == 0)
324 			return 1;
325 	}
326 	return 0;
327 }
328 
329 static printfcn
findlink(int type)330 findlink(int type)
331 {
332 	switch(type) {
333 	case IFT_ETHER:
334 	case IFT_ISO88023:
335 	case IFT_STARLAN:
336 		return print_1650;
337 	}
338 
339 	return 0;
340 }
341