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