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