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
48static void printit(const struct ifmibdata *, const char *);
49static const char *iftype(int);
50static int isit(int, char **, const char *);
51static printfcn findlink(int);
52
53static void
54usage(const char *argv0)
55{
56	fprintf(stderr, "%s: usage:\n\t%s [-l]\n", argv0, argv0);
57	exit(EX_USAGE);
58}
59
60int
61main(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
152static void
153printit(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
196static 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
258static const char *
259iftype(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
271static int
272isit(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
283static printfcn
284findlink(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