xref: /freebsd/tools/tools/ifinfo/ifinfo.c (revision 9768746b)
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 int isit(int, char **, const char *);
53 static printfcn findlink(int);
54 
55 static void
56 usage(const char *argv0)
57 {
58 	fprintf(stderr, "%s: usage:\n\t%s [-l]\n", argv0, argv0);
59 	exit(EX_USAGE);
60 }
61 
62 int
63 main(int argc, char **argv)
64 {
65 	int i, maxifno, retval;
66 	struct ifmibdata ifmd;
67 	int name[6];
68 	size_t len;
69 	int c;
70 	int dolink = 0;
71 	void *linkmib;
72 	size_t linkmiblen;
73 	printfcn pf;
74 	char *dname;
75 
76 	while ((c = getopt(argc, argv, "l")) != -1) {
77 		switch(c) {
78 		case 'l':
79 			dolink = 1;
80 			break;
81 		default:
82 			usage(argv[0]);
83 		}
84 	}
85 
86 	retval = 1;
87 
88 	name[0] = CTL_NET;
89 	name[1] = PF_LINK;
90 	name[2] = NETLINK_GENERIC;
91 	name[3] = IFMIB_SYSTEM;
92 	name[4] = IFMIB_IFCOUNT;
93 
94 	len = sizeof maxifno;
95 	if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0)
96 		err(EX_OSERR, "sysctl(net.link.generic.system.ifcount)");
97 
98 	for (i = 1; i <= maxifno; i++) {
99 		len = sizeof ifmd;
100 		name[3] = IFMIB_IFDATA;
101 		name[4] = i;
102 		name[5] = IFDATA_GENERAL;
103 		if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) {
104 			if (errno == ENOENT)
105 				continue;
106 
107 			err(EX_OSERR, "sysctl(net.link.ifdata.%d.general)",
108 			    i);
109 		}
110 
111 		if (!isit(argc - optind, argv + optind, ifmd.ifmd_name))
112 			continue;
113 
114 		dname = NULL;
115 		len = 0;
116 		name[5] = IFDATA_DRIVERNAME;
117 		if (sysctl(name, 6, NULL, &len, 0, 0) < 0) {
118 			warn("sysctl(net.link.ifdata.%d.drivername)", i);
119 		} else {
120 			if ((dname = malloc(len)) == NULL)
121 				err(EX_OSERR, NULL);
122 			if (sysctl(name, 6, dname, &len, 0, 0) < 0) {
123 				warn("sysctl(net.link.ifdata.%d.drivername)",
124 				    i);
125 				free(dname);
126 				dname = NULL;
127 			}
128 		}
129 		printit(&ifmd, dname);
130 		free(dname);
131 		if (dolink && (pf = findlink(ifmd.ifmd_data.ifi_type))) {
132 			name[5] = IFDATA_LINKSPECIFIC;
133 			if (sysctl(name, 6, 0, &linkmiblen, 0, 0) < 0)
134 				err(EX_OSERR,
135 				    "sysctl(net.link.ifdata.%d.linkspec) size",
136 				    i);
137 			linkmib = malloc(linkmiblen);
138 			if (!linkmib)
139 				err(EX_OSERR, "malloc(%lu)",
140 				    (u_long)linkmiblen);
141 			if (sysctl(name, 6, linkmib, &linkmiblen, 0, 0) < 0)
142 				err(EX_OSERR,
143 				    "sysctl(net.link.ifdata.%d.linkspec)",
144 				    i);
145 			pf(linkmib, linkmiblen);
146 			free(linkmib);
147 		}
148 		retval = 0;
149 	}
150 
151 	return retval;
152 }
153 
154 static void
155 printit(const struct ifmibdata *ifmd, const char *dname)
156 {
157 	printf("Interface %.*s", IFNAMSIZ, ifmd->ifmd_name);
158 	if (dname != NULL)
159 		printf(" (%s)", dname);
160 	printf(":\n");
161 	printf("\tflags: %x\n", ifmd->ifmd_flags);
162 	printf("\tpromiscuous listeners: %d\n", ifmd->ifmd_pcount);
163 	printf("\tsend queue length: %d\n", ifmd->ifmd_snd_len);
164 	printf("\tsend queue max length: %d\n", ifmd->ifmd_snd_maxlen);
165 	printf("\tsend queue drops: %d\n", ifmd->ifmd_snd_drops);
166 	printf("\ttype: %s\n", iftype(ifmd->ifmd_data.ifi_type));
167 	printf("\taddress length: %d\n", ifmd->ifmd_data.ifi_addrlen);
168 	printf("\theader length: %d\n", ifmd->ifmd_data.ifi_hdrlen);
169 	printf("\tlink state: %u\n", ifmd->ifmd_data.ifi_link_state);
170 	printf("\tvhid: %u\n", ifmd->ifmd_data.ifi_vhid);
171 	printf("\tdatalen: %u\n", ifmd->ifmd_data.ifi_datalen);
172 	printf("\tmtu: %u\n", ifmd->ifmd_data.ifi_mtu);
173 	printf("\tmetric: %u\n", ifmd->ifmd_data.ifi_metric);
174 	printf("\tline rate: %lu bit/s\n", ifmd->ifmd_data.ifi_baudrate);
175 	printf("\tpackets received: %lu\n", ifmd->ifmd_data.ifi_ipackets);
176 	printf("\tinput errors: %lu\n", ifmd->ifmd_data.ifi_ierrors);
177 	printf("\tpackets transmitted: %lu\n", ifmd->ifmd_data.ifi_opackets);
178 	printf("\toutput errors: %lu\n", ifmd->ifmd_data.ifi_oerrors);
179 	printf("\tcollisions: %lu\n", ifmd->ifmd_data.ifi_collisions);
180 	printf("\tbytes received: %lu\n", ifmd->ifmd_data.ifi_ibytes);
181 	printf("\tbytes transmitted: %lu\n", ifmd->ifmd_data.ifi_obytes);
182 	printf("\tmulticasts received: %lu\n", ifmd->ifmd_data.ifi_imcasts);
183 	printf("\tmulticasts transmitted: %lu\n", ifmd->ifmd_data.ifi_omcasts);
184 	printf("\tinput queue drops: %lu\n", ifmd->ifmd_data.ifi_iqdrops);
185 	printf("\tpackets for unknown protocol: %lu\n",
186 	       ifmd->ifmd_data.ifi_noproto);
187 	printf("\tHW offload capabilities: 0x%lx\n",
188 	    ifmd->ifmd_data.ifi_hwassist);
189 	printf("\tuptime at attach or stat reset: %lu\n",
190 	    ifmd->ifmd_data.ifi_epoch);
191 #ifdef notdef
192 	printf("\treceive timing: %lu usec\n", ifmd->ifmd_data.ifi_recvtiming);
193 	printf("\ttransmit timing: %lu usec\n",
194 	       ifmd->ifmd_data.ifi_xmittiming);
195 #endif
196 }
197 
198 static const char *const if_types[] = {
199 	"reserved",
200 	"other",
201 	"BBN 1822",
202 	"HDH 1822",
203 	"X.25 DDN",
204 	"X.25",
205 	"Ethernet",
206 	"ISO 8802-3 CSMA/CD",
207 	"ISO 8802-4 Token Bus",
208 	"ISO 8802-5 Token Ring",
209 	"ISO 8802-6 DQDB MAN",
210 	"StarLAN",
211 	"Proteon proNET-10",
212 	"Proteon proNET-80",
213 	"HyperChannel",
214 	"FDDI",
215 	"LAP-B",
216 	"SDLC",
217 	"T-1",
218 	"CEPT",
219 	"Basic rate ISDN",
220 	"Primary rate ISDN",
221 	"Proprietary P2P",
222 	"PPP",
223 	"Loopback",
224 	"ISO CLNP over IP",
225 	"Experimental Ethernet",
226 	"XNS over IP",
227 	"SLIP",
228 	"Ultra Technologies",
229 	"DS-3",
230 	"SMDS",
231 	"Frame Relay",
232 	"RS-232 serial",
233 	"Parallel printer port",
234 	"ARCNET",
235 	"ARCNET+",
236 	"ATM",
237 	"MIOX25",
238 	"SONET/SDH",
239 	"X25PLE",
240 	"ISO 8802-2 LLC",
241 	"LocalTalk",
242 	"SMDSDXI",
243 	"Frame Relay DCE",
244 	"V.35",
245 	"HSSI",
246 	"HIPPI",
247 	"Generic Modem",
248 	"ATM AAL5",
249 	"SONETPATH",
250 	"SONETVT",
251 	"SMDS InterCarrier Interface",
252 	"Proprietary virtual interface",
253 	"Proprietary multiplexing",
254 	"Generic tunnel interface",
255 	"IPv6-to-IPv4 TCP relay capturing interface",
256 	"6to4 tunnel interface"
257 };
258 #define	NIFTYPES (int)((sizeof if_types)/(sizeof if_types[0]))
259 
260 static const char *
261 iftype(int type)
262 {
263 	static char buf[256];
264 
265 	if (type <= 0 || type >= NIFTYPES) {
266 		sprintf(buf, "unknown type %d", type);
267 		return buf;
268 	}
269 
270 	return if_types[type];
271 }
272 
273 static int
274 isit(int argc, char **argv, const char *name)
275 {
276 	if (argc == 0)
277 		return 1;
278 	for (argc = 0; argv[argc]; argc++) {
279 		if (strncmp(argv[argc], name, IFNAMSIZ) == 0)
280 			return 1;
281 	}
282 	return 0;
283 }
284 
285 static printfcn
286 findlink(int type)
287 {
288 	switch(type) {
289 	case IFT_ETHER:
290 	case IFT_ISO88023:
291 	case IFT_STARLAN:
292 		return print_1650;
293 	}
294 
295 	return 0;
296 }
297