if.c revision 1.13
1/*	$NetBSD: if.c,v 1.13 1995/10/03 21:42:36 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1983, 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37#if 0
38static char sccsid[] = "from: @(#)if.c	8.2 (Berkeley) 2/21/94";
39#else
40static char *rcsid = "$NetBSD: if.c,v 1.13 1995/10/03 21:42:36 thorpej Exp $";
41#endif
42#endif /* not lint */
43
44#include <sys/types.h>
45#include <sys/protosw.h>
46#include <sys/socket.h>
47
48#include <net/if.h>
49#include <net/if_dl.h>
50#include <netinet/in.h>
51#include <netinet/in_var.h>
52#include <netns/ns.h>
53#include <netns/ns_if.h>
54#include <netiso/iso.h>
55#include <netiso/iso_var.h>
56#include <arpa/inet.h>
57
58#include <signal.h>
59#include <stdio.h>
60#include <string.h>
61#include <unistd.h>
62
63#include "netstat.h"
64
65#define	YES	1
66#define	NO	0
67
68static void sidewaysintpr __P((u_int, u_long));
69static void catchalarm __P((int));
70
71/*
72 * Print a description of the network interfaces.
73 */
74void
75intpr(interval, ifnetaddr)
76	int interval;
77	u_long ifnetaddr;
78{
79	struct ifnet ifnet;
80	union {
81		struct ifaddr ifa;
82		struct in_ifaddr in;
83		struct ns_ifaddr ns;
84		struct iso_ifaddr iso;
85	} ifaddr;
86	u_long ifaddraddr;
87	struct sockaddr *sa;
88	char name[16];
89
90	if (ifnetaddr == 0) {
91		printf("ifnet: symbol not defined\n");
92		return;
93	}
94	if (interval) {
95		sidewaysintpr((unsigned)interval, ifnetaddr);
96		return;
97	}
98	if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr))
99		return;
100	printf("%-5.5s %-5.5s %-11.11s %-15.15s %10.10s %5.5s %8.8s %5.5s",
101		"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
102		"Opkts", "Oerrs");
103	printf(" %5s", "Coll");
104	if (tflag)
105		printf(" %s", "Time");
106	if (dflag)
107		printf(" %s", "Drop");
108	putchar('\n');
109	ifaddraddr = 0;
110	while (ifnetaddr || ifaddraddr) {
111		struct sockaddr_in *sin;
112		register char *cp;
113		int n, m;
114
115		if (ifaddraddr == 0) {
116			if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
117			    kread((u_long)ifnet.if_name, name, 16))
118				return;
119			name[15] = '\0';
120			ifnetaddr = (u_long)ifnet.if_list.tqe_next;
121			if (interface != 0 && (strcmp(name, interface) != 0 ||
122			    unit != ifnet.if_unit))
123				continue;
124			cp = index(name, '\0');
125			cp += sprintf(cp, "%d", ifnet.if_unit);
126			if ((ifnet.if_flags & IFF_UP) == 0)
127				*cp++ = '*';
128			*cp = '\0';
129			ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first;
130		}
131		printf("%-5.5s %-5d ", name, ifnet.if_mtu);
132		if (ifaddraddr == 0) {
133			printf("%-11.11s ", "none");
134			printf("%-15.15s ", "none");
135		} else {
136			if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
137				ifaddraddr = 0;
138				continue;
139			}
140#define CP(x) ((char *)(x))
141			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
142				CP(&ifaddr); sa = (struct sockaddr *)cp;
143			switch (sa->sa_family) {
144			case AF_UNSPEC:
145				printf("%-11.11s ", "none");
146				printf("%-17.17s ", "none");
147				break;
148			case AF_INET:
149				sin = (struct sockaddr_in *)sa;
150#ifdef notdef
151				/* can't use inet_makeaddr because kernel
152				 * keeps nets unshifted.
153				 */
154				in = inet_makeaddr(ifaddr.in.ia_subnet,
155					INADDR_ANY);
156				printf("%-11.11s ", netname(in.s_addr,
157				    ifaddr.in.ia_subnetmask));
158#else
159				printf("%-11.11s ",
160				    netname(ifaddr.in.ia_subnet,
161				    ifaddr.in.ia_subnetmask));
162#endif
163				printf("%-17.17s ",
164				    routename(sin->sin_addr.s_addr));
165
166				if (aflag) {
167					u_long multiaddr;
168					struct in_multi inm;
169
170					multiaddr = (u_long)ifaddr.in.ia_multiaddrs.lh_first;
171					while (multiaddr != 0) {
172						kread(multiaddr, (char *)&inm,
173						    sizeof inm);
174						printf("\n%23s %-15.15s ", "",
175						    routename(inm.inm_addr.s_addr));
176						multiaddr = (u_long)inm.inm_list.le_next;
177					}
178				}
179				break;
180			case AF_NS:
181				{
182				struct sockaddr_ns *sns =
183					(struct sockaddr_ns *)sa;
184				u_long net;
185				char netnum[8];
186
187				*(union ns_net *) &net = sns->sns_addr.x_net;
188		sprintf(netnum, "%lxH", ntohl(net));
189				upHex(netnum);
190				printf("ns:%-8s ", netnum);
191				printf("%-17s ",
192				    ns_phost((struct sockaddr *)sns));
193				}
194				break;
195			case AF_LINK:
196				{
197				struct sockaddr_dl *sdl =
198					(struct sockaddr_dl *)sa;
199				    cp = (char *)LLADDR(sdl);
200				    n = sdl->sdl_alen;
201				}
202				m = printf("%-11.11s ", "<Link>");
203				goto hexprint;
204			default:
205				m = printf("(%d)", sa->sa_family);
206				for (cp = sa->sa_len + (char *)sa;
207					--cp > sa->sa_data && (*cp == 0);) {}
208				n = cp - sa->sa_data + 1;
209				cp = sa->sa_data;
210			hexprint:
211				while (--n >= 0)
212					m += printf("%x%c", *cp++ & 0xff,
213						    n > 0 ? '.' : ' ');
214				m = 30 - m;
215				while (m-- > 0)
216					putchar(' ');
217				break;
218			}
219			ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next;
220		}
221		printf("%8d %5d %8d %5d %5d",
222		    ifnet.if_ipackets, ifnet.if_ierrors,
223		    ifnet.if_opackets, ifnet.if_oerrors,
224		    ifnet.if_collisions);
225		if (tflag)
226			printf(" %3d", ifnet.if_timer);
227		if (dflag)
228			printf(" %3d", ifnet.if_snd.ifq_drops);
229		putchar('\n');
230	}
231}
232
233#define	MAXIF	10
234struct	iftot {
235	char	ift_name[16];		/* interface name */
236	int	ift_ip;			/* input packets */
237	int	ift_ie;			/* input errors */
238	int	ift_op;			/* output packets */
239	int	ift_oe;			/* output errors */
240	int	ift_co;			/* collisions */
241	int	ift_dr;			/* drops */
242} iftot[MAXIF];
243
244u_char	signalled;			/* set if alarm goes off "early" */
245
246/*
247 * Print a running summary of interface statistics.
248 * Repeat display every interval seconds, showing statistics
249 * collected over that interval.  Assumes that interval is non-zero.
250 * First line printed at top of screen is always cumulative.
251 */
252static void
253sidewaysintpr(interval, off)
254	unsigned interval;
255	u_long off;
256{
257	struct ifnet ifnet;
258	u_long firstifnet;
259	register struct iftot *ip, *total;
260	register int line;
261	struct iftot *lastif, *sum, *interesting;
262	int oldmask;
263
264	if (kread(off, (char *)&firstifnet, sizeof (u_long)))
265		return;
266	lastif = iftot;
267	sum = iftot + MAXIF - 1;
268	total = sum - 1;
269	interesting = iftot;
270	for (off = firstifnet, ip = iftot; off;) {
271		char *cp;
272
273		if (kread(off, (char *)&ifnet, sizeof ifnet))
274			break;
275		ip->ift_name[0] = '(';
276		if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15))
277			break;
278		if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
279		    unit == ifnet.if_unit)
280			interesting = ip;
281		ip->ift_name[15] = '\0';
282		cp = index(ip->ift_name, '\0');
283		sprintf(cp, "%d)", ifnet.if_unit);
284		ip++;
285		if (ip >= iftot + MAXIF - 2)
286			break;
287		off = (u_long)ifnet.if_list.tqe_next;
288	}
289	lastif = ip;
290
291	(void)signal(SIGALRM, catchalarm);
292	signalled = NO;
293	(void)alarm(interval);
294banner:
295	printf("   input    %-6.6s    output       ", interesting->ift_name);
296	if (lastif - iftot > 0) {
297		if (dflag)
298			printf("      ");
299		printf("     input   (Total)    output");
300	}
301	for (ip = iftot; ip < iftot + MAXIF; ip++) {
302		ip->ift_ip = 0;
303		ip->ift_ie = 0;
304		ip->ift_op = 0;
305		ip->ift_oe = 0;
306		ip->ift_co = 0;
307		ip->ift_dr = 0;
308	}
309	putchar('\n');
310	printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
311		"packets", "errs", "packets", "errs", "colls");
312	if (dflag)
313		printf("%5.5s ", "drops");
314	if (lastif - iftot > 0)
315		printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
316			"packets", "errs", "packets", "errs", "colls");
317	if (dflag)
318		printf(" %5.5s", "drops");
319	putchar('\n');
320	fflush(stdout);
321	line = 0;
322loop:
323	sum->ift_ip = 0;
324	sum->ift_ie = 0;
325	sum->ift_op = 0;
326	sum->ift_oe = 0;
327	sum->ift_co = 0;
328	sum->ift_dr = 0;
329	for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
330		if (kread(off, (char *)&ifnet, sizeof ifnet)) {
331			off = 0;
332			continue;
333		}
334		if (ip == interesting) {
335			printf("%8d %5d %8d %5d %5d",
336				ifnet.if_ipackets - ip->ift_ip,
337				ifnet.if_ierrors - ip->ift_ie,
338				ifnet.if_opackets - ip->ift_op,
339				ifnet.if_oerrors - ip->ift_oe,
340				ifnet.if_collisions - ip->ift_co);
341			if (dflag)
342				printf(" %5d",
343				    ifnet.if_snd.ifq_drops - ip->ift_dr);
344		}
345		ip->ift_ip = ifnet.if_ipackets;
346		ip->ift_ie = ifnet.if_ierrors;
347		ip->ift_op = ifnet.if_opackets;
348		ip->ift_oe = ifnet.if_oerrors;
349		ip->ift_co = ifnet.if_collisions;
350		ip->ift_dr = ifnet.if_snd.ifq_drops;
351		sum->ift_ip += ip->ift_ip;
352		sum->ift_ie += ip->ift_ie;
353		sum->ift_op += ip->ift_op;
354		sum->ift_oe += ip->ift_oe;
355		sum->ift_co += ip->ift_co;
356		sum->ift_dr += ip->ift_dr;
357		off = (u_long)ifnet.if_list.tqe_next;
358	}
359	if (lastif - iftot > 0) {
360		printf("  %8d %5d %8d %5d %5d",
361			sum->ift_ip - total->ift_ip,
362			sum->ift_ie - total->ift_ie,
363			sum->ift_op - total->ift_op,
364			sum->ift_oe - total->ift_oe,
365			sum->ift_co - total->ift_co);
366		if (dflag)
367			printf(" %5d", sum->ift_dr - total->ift_dr);
368	}
369	*total = *sum;
370	putchar('\n');
371	fflush(stdout);
372	line++;
373	oldmask = sigblock(sigmask(SIGALRM));
374	if (! signalled) {
375		sigpause(0);
376	}
377	sigsetmask(oldmask);
378	signalled = NO;
379	(void)alarm(interval);
380	if (line == 21)
381		goto banner;
382	goto loop;
383	/*NOTREACHED*/
384}
385
386/*
387 * Called if an interval expires before sidewaysintpr has completed a loop.
388 * Sets a flag to not wait for the alarm.
389 */
390static void
391catchalarm(signo)
392	int signo;
393{
394	signalled = YES;
395}
396