xref: /freebsd/tools/tools/ifinfo/ifinfo.c (revision b0b1dbdd)
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  * $FreeBSD$
30  */
31 #include <sys/types.h>
32 #include <sys/socket.h>		/* for PF_LINK */
33 #include <sys/sysctl.h>
34 #include <sys/time.h>
35 
36 #include <err.h>
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sysexits.h>
42 #include <unistd.h>
43 
44 #include <net/if.h>
45 #include <net/if_types.h>
46 #include <net/if_mib.h>
47 
48 #include "ifinfo.h"
49 
50 static void printit(const struct ifmibdata *, const char *);
51 static const char *iftype(int);
52 static const char *ifphys(int, int);
53 static int isit(int, char **, const char *);
54 static printfcn findlink(int);
55 
56 static void
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
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 static void
156 printit(const struct ifmibdata *ifmd, const char *dname)
157 {
158 	printf("Interface %.*s", IFNAMSIZ, ifmd->ifmd_name);
159 	if (dname != NULL)
160 		printf(" (%s)", dname);
161 	printf(":\n");
162 	printf("\tflags: %x\n", ifmd->ifmd_flags);
163 	printf("\tpromiscuous listeners: %d\n", ifmd->ifmd_pcount);
164 	printf("\tsend queue length: %d\n", ifmd->ifmd_snd_len);
165 	printf("\tsend queue max length: %d\n", ifmd->ifmd_snd_maxlen);
166 	printf("\tsend queue drops: %d\n", ifmd->ifmd_snd_drops);
167 	printf("\ttype: %s\n", iftype(ifmd->ifmd_data.ifi_type));
168 	printf("\tphysical: %s\n", ifphys(ifmd->ifmd_data.ifi_type,
169 					  ifmd->ifmd_data.ifi_physical));
170 	printf("\taddress length: %d\n", ifmd->ifmd_data.ifi_addrlen);
171 	printf("\theader length: %d\n", ifmd->ifmd_data.ifi_hdrlen);
172 	printf("\tlink state: %u\n", ifmd->ifmd_data.ifi_link_state);
173 	printf("\tvhid: %u\n", ifmd->ifmd_data.ifi_vhid);
174 	printf("\tdatalen: %u\n", ifmd->ifmd_data.ifi_datalen);
175 	printf("\tmtu: %lu\n", ifmd->ifmd_data.ifi_mtu);
176 	printf("\tmetric: %lu\n", ifmd->ifmd_data.ifi_metric);
177 	printf("\tline rate: %lu bit/s\n", ifmd->ifmd_data.ifi_baudrate);
178 	printf("\tpackets received: %lu\n", ifmd->ifmd_data.ifi_ipackets);
179 	printf("\tinput errors: %lu\n", ifmd->ifmd_data.ifi_ierrors);
180 	printf("\tpackets transmitted: %lu\n", ifmd->ifmd_data.ifi_opackets);
181 	printf("\toutput errors: %lu\n", ifmd->ifmd_data.ifi_oerrors);
182 	printf("\tcollisions: %lu\n", ifmd->ifmd_data.ifi_collisions);
183 	printf("\tbytes received: %lu\n", ifmd->ifmd_data.ifi_ibytes);
184 	printf("\tbytes transmitted: %lu\n", ifmd->ifmd_data.ifi_obytes);
185 	printf("\tmulticasts received: %lu\n", ifmd->ifmd_data.ifi_imcasts);
186 	printf("\tmulticasts transmitted: %lu\n", ifmd->ifmd_data.ifi_omcasts);
187 	printf("\tinput queue drops: %lu\n", ifmd->ifmd_data.ifi_iqdrops);
188 	printf("\tpackets for unknown protocol: %lu\n",
189 	       ifmd->ifmd_data.ifi_noproto);
190 	printf("\tHW offload capabilities: 0x%lx\n",
191 	    ifmd->ifmd_data.ifi_hwassist);
192 	printf("\tuptime at attach or stat reset: %lu\n",
193 	    ifmd->ifmd_data.ifi_epoch);
194 #ifdef notdef
195 	printf("\treceive timing: %lu usec\n", ifmd->ifmd_data.ifi_recvtiming);
196 	printf("\ttransmit timing: %lu usec\n",
197 	       ifmd->ifmd_data.ifi_xmittiming);
198 #endif
199 }
200 
201 static const char *const if_types[] = {
202 	"reserved",
203 	"other",
204 	"BBN 1822",
205 	"HDH 1822",
206 	"X.25 DDN",
207 	"X.25",
208 	"Ethernet",
209 	"ISO 8802-3 CSMA/CD",
210 	"ISO 8802-4 Token Bus",
211 	"ISO 8802-5 Token Ring",
212 	"ISO 8802-6 DQDB MAN",
213 	"StarLAN",
214 	"Proteon proNET-10",
215 	"Proteon proNET-80",
216 	"HyperChannel",
217 	"FDDI",
218 	"LAP-B",
219 	"SDLC",
220 	"T-1",
221 	"CEPT",
222 	"Basic rate ISDN",
223 	"Primary rate ISDN",
224 	"Proprietary P2P",
225 	"PPP",
226 	"Loopback",
227 	"ISO CLNP over IP",
228 	"Experimental Ethernet",
229 	"XNS over IP",
230 	"SLIP",
231 	"Ultra Technologies",
232 	"DS-3",
233 	"SMDS",
234 	"Frame Relay",
235 	"RS-232 serial",
236 	"Parallel printer port",
237 	"ARCNET",
238 	"ARCNET+",
239 	"ATM",
240 	"MIOX25",
241 	"SONET/SDH",
242 	"X25PLE",
243 	"ISO 8802-2 LLC",
244 	"LocalTalk",
245 	"SMDSDXI",
246 	"Frame Relay DCE",
247 	"V.35",
248 	"HSSI",
249 	"HIPPI",
250 	"Generic Modem",
251 	"ATM AAL5",
252 	"SONETPATH",
253 	"SONETVT",
254 	"SMDS InterCarrier Interface",
255 	"Proprietary virtual interface",
256 	"Proprietary multiplexing",
257 	"Generic tunnel interface",
258 	"IPv6-to-IPv4 TCP relay capturing interface",
259 	"6to4 tunnel interface"
260 };
261 #define	NIFTYPES ((sizeof if_types)/(sizeof if_types[0]))
262 
263 static const char *
264 iftype(int type)
265 {
266 	static char buf[256];
267 
268 	if (type <= 0 || type >= NIFTYPES) {
269 		sprintf(buf, "unknown type %d", type);
270 		return buf;
271 	}
272 
273 	return if_types[type];
274 }
275 
276 static const char *
277 ifphys(int type, int phys)
278 {
279 	static char buf[256];
280 
281 	sprintf(buf, "unknown physical %d", phys);
282 	return buf;
283 }
284 
285 static int
286 isit(int argc, char **argv, const char *name)
287 {
288 	if (argc == 0)
289 		return 1;
290 	for (argc = 0; argv[argc]; argc++) {
291 		if (strncmp(argv[argc], name, IFNAMSIZ) == 0)
292 			return 1;
293 	}
294 	return 0;
295 }
296 
297 static printfcn
298 findlink(int type)
299 {
300 	switch(type) {
301 	case IFT_ETHER:
302 	case IFT_ISO88023:
303 	case IFT_STARLAN:
304 		return print_1650;
305 	}
306 
307 	return 0;
308 }
309