if.c revision 1.3
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
35/*static char sccsid[] = "from: @(#)if.c	5.15 (Berkeley) 3/1/91";*/
36static char rcsid[] = "$Id: if.c,v 1.3 1993/08/01 18:10:53 mycroft Exp $";
37#endif /* not lint */
38
39#include <sys/types.h>
40#include <sys/socket.h>
41
42#include <net/if.h>
43#include <net/if_dl.h>
44#include <netinet/in.h>
45#include <netinet/in_var.h>
46
47#ifdef NS
48#include <netns/ns.h>
49#include <netns/ns_if.h>
50#endif /* NS */
51
52#ifdef ISO
53#include <netiso/iso.h>
54#include <netiso/iso_var.h>
55#endif /* ISO */
56
57#include <stdio.h>
58#include <signal.h>
59
60#define	YES	1
61#define	NO	0
62
63extern	int tflag;
64extern	int dflag;
65extern	int nflag;
66extern	char *interface;
67extern	int unit;
68extern	char *routename(), *netname(), *ns_phost();
69char *index();
70
71/*
72 * Print a description of the network interfaces.
73 */
74intpr(interval, ifnetaddr)
75	int interval;
76	off_t ifnetaddr;
77{
78	struct ifnet ifnet;
79	union {
80		struct ifaddr ifa;
81		struct in_ifaddr in;
82#ifdef NS
83		struct ns_ifaddr ns;
84#endif
85#ifdef ISO
86		struct iso_ifaddr iso;
87#endif
88	} ifaddr;
89	off_t ifaddraddr;
90	struct sockaddr *sa;
91	char name[16];
92
93	if (ifnetaddr == 0) {
94		printf("ifnet: symbol not defined\n");
95		return;
96	}
97	if (interval) {
98		sidewaysintpr((unsigned)interval, ifnetaddr);
99		return;
100	}
101	kvm_read(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr);
102	printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s",
103		"Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
104		"Opkts", "Oerrs");
105	printf(" %5s", "Coll");
106	if (tflag)
107		printf(" %s", "Time");
108	if (dflag)
109		printf(" %s", "Drop");
110	putchar('\n');
111	ifaddraddr = 0;
112	while (ifnetaddr || ifaddraddr) {
113		struct sockaddr_in *sin;
114#ifdef ISO
115		struct sockaddr_iso *siso;
116#endif
117		register char *cp;
118		int n, m;
119		struct in_addr inet_makeaddr();
120
121		if (ifaddraddr == 0) {
122			kvm_read(ifnetaddr, (char *)&ifnet, sizeof ifnet);
123			kvm_read((off_t)ifnet.if_name, name, 16);
124			name[15] = '\0';
125			ifnetaddr = (off_t) ifnet.if_next;
126			if (interface != 0 &&
127			    (strcmp(name, interface) != 0 || unit != ifnet.if_unit))
128				continue;
129			cp = index(name, '\0');
130			*cp++ = ifnet.if_unit + '0';
131			if ((ifnet.if_flags&IFF_UP) == 0)
132				*cp++ = '*';
133			*cp = '\0';
134			ifaddraddr = (off_t)ifnet.if_addrlist;
135		}
136		printf("%-5.5s %-5d ", name, ifnet.if_mtu);
137		if (ifaddraddr == 0) {
138			printf("%-11.11s ", "none");
139			printf("%-15.15s ", "none");
140		} else {
141			kvm_read(ifaddraddr, (char *)&ifaddr, sizeof ifaddr);
142#define CP(x) ((char *)(x))
143			cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
144				CP(&ifaddr); sa = (struct sockaddr *)cp;
145			switch (sa->sa_family) {
146			case AF_UNSPEC:
147				printf("%-11.11s ", "none");
148				printf("%-15.15s ", "none");
149				break;
150			case AF_INET:
151				sin = (struct sockaddr_in *)sa;
152#ifdef notdef
153				/* can't use inet_makeaddr because kernel
154				 * keeps nets unshifted.
155				 */
156				in = inet_makeaddr(ifaddr.in.ia_subnet,
157					INADDR_ANY);
158				printf("%-11.11s ", netname(in));
159#else
160				printf("%-11.11s ",
161					netname(htonl(ifaddr.in.ia_subnet),
162						ifaddr.in.ia_subnetmask));
163#endif
164				printf("%-15.15s ", routename(sin->sin_addr));
165				break;
166#ifdef NS
167			case AF_NS:
168				{
169				struct sockaddr_ns *sns =
170					(struct sockaddr_ns *)sa;
171				u_long net;
172				char netnum[8];
173				char *ns_phost();
174
175				*(union ns_net *) &net = sns->sns_addr.x_net;
176		sprintf(netnum, "%lxH", ntohl(net));
177				upHex(netnum);
178				printf("ns:%-8s ", netnum);
179				printf("%-15s ", ns_phost(sns));
180				}
181				break;
182#endif
183			case AF_LINK:
184				{
185				struct sockaddr_dl *sdl =
186					(struct sockaddr_dl *)sa;
187				    cp = (char *)LLADDR(sdl);
188				    n = sdl->sdl_alen;
189				}
190				m = printf("%-11.11s ","<Link>");
191				goto hexprint;
192#ifdef ISO
193			case AF_ISO:
194				siso = (struct sockaddr_iso *)sa;
195				if(nflag) {
196					printf("%27s ",
197						iso_ntoa(&siso->siso_addr));
198				} else {
199					/* This will probably truncate the */
200					/* NSAP prefix */
201					printf("%-11.11s ",
202						iso_ntoa(&siso->siso_addr));
203					printf("%-15.15s ",
204						iso_idtoa(&siso->siso_addr));
205				}
206				break;
207#endif
208			default:
209				m = printf("(%d)", sa->sa_family);
210				for (cp = sa->sa_len + (char *)sa;
211					--cp > sa->sa_data && (*cp == 0);) {}
212				n = cp - sa->sa_data + 1;
213				cp = sa->sa_data;
214			hexprint:
215				while (--n >= 0)
216					m += printf("%x%c", *cp++ & 0xff,
217						    n > 0 ? '.' : ' ');
218				m = 28 - m;
219				while (m-- > 0)
220					putchar(' ');
221				break;
222			}
223			ifaddraddr = (off_t)ifaddr.ifa.ifa_next;
224		}
225		printf("%8d %5d %8d %5d %5d",
226		    ifnet.if_ipackets, ifnet.if_ierrors,
227		    ifnet.if_opackets, ifnet.if_oerrors,
228		    ifnet.if_collisions);
229		if (tflag)
230			printf(" %3d", ifnet.if_timer);
231		if (dflag)
232			printf(" %3d", ifnet.if_snd.ifq_drops);
233		putchar('\n');
234	}
235}
236
237#define	MAXIF	10
238struct	iftot {
239	char	ift_name[16];		/* interface name */
240	int	ift_ip;			/* input packets */
241	int	ift_ie;			/* input errors */
242	int	ift_op;			/* output packets */
243	int	ift_oe;			/* output errors */
244	int	ift_co;			/* collisions */
245	int	ift_dr;			/* drops */
246} iftot[MAXIF];
247
248u_char	signalled;			/* set if alarm goes off "early" */
249
250/*
251 * Print a running summary of interface statistics.
252 * Repeat display every interval seconds, showing statistics
253 * collected over that interval.  Assumes that interval is non-zero.
254 * First line printed at top of screen is always cumulative.
255 */
256sidewaysintpr(interval, off)
257	unsigned interval;
258	off_t off;
259{
260	struct ifnet ifnet;
261	off_t firstifnet;
262	register struct iftot *ip, *total;
263	register int line;
264	struct iftot *lastif, *sum, *interesting;
265	int oldmask;
266	void catchalarm();
267
268	kvm_read(off, (char *)&firstifnet, sizeof (off_t));
269	lastif = iftot;
270	sum = iftot + MAXIF - 1;
271	total = sum - 1;
272	interesting = iftot;
273	for (off = firstifnet, ip = iftot; off;) {
274		char *cp;
275
276		kvm_read(off, (char *)&ifnet, sizeof ifnet);
277		ip->ift_name[0] = '(';
278		kvm_read((off_t)ifnet.if_name, ip->ift_name + 1, 15);
279		if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
280		    unit == ifnet.if_unit)
281			interesting = ip;
282		ip->ift_name[15] = '\0';
283		cp = index(ip->ift_name, '\0');
284		sprintf(cp, "%d)", ifnet.if_unit);
285		ip++;
286		if (ip >= iftot + MAXIF - 2)
287			break;
288		off = (off_t) ifnet.if_next;
289	}
290	lastif = ip;
291
292	(void)signal(SIGALRM, catchalarm);
293	signalled = NO;
294	(void)alarm(interval);
295banner:
296	printf("   input    %-6.6s    output       ", interesting->ift_name);
297	if (lastif - iftot > 0) {
298		if (dflag)
299			printf("      ");
300		printf("     input   (Total)    output");
301	}
302	for (ip = iftot; ip < iftot + MAXIF; ip++) {
303		ip->ift_ip = 0;
304		ip->ift_ie = 0;
305		ip->ift_op = 0;
306		ip->ift_oe = 0;
307		ip->ift_co = 0;
308		ip->ift_dr = 0;
309	}
310	putchar('\n');
311	printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
312		"packets", "errs", "packets", "errs", "colls");
313	if (dflag)
314		printf("%5.5s ", "drops");
315	if (lastif - iftot > 0)
316		printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
317			"packets", "errs", "packets", "errs", "colls");
318	if (dflag)
319		printf(" %5.5s", "drops");
320	putchar('\n');
321	fflush(stdout);
322	line = 0;
323loop:
324	sum->ift_ip = 0;
325	sum->ift_ie = 0;
326	sum->ift_op = 0;
327	sum->ift_oe = 0;
328	sum->ift_co = 0;
329	sum->ift_dr = 0;
330	for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
331		kvm_read(off, (char *)&ifnet, sizeof ifnet);
332		if (ip == interesting) {
333			printf("%8d %5d %8d %5d %5d",
334				ifnet.if_ipackets - ip->ift_ip,
335				ifnet.if_ierrors - ip->ift_ie,
336				ifnet.if_opackets - ip->ift_op,
337				ifnet.if_oerrors - ip->ift_oe,
338				ifnet.if_collisions - ip->ift_co);
339			if (dflag)
340				printf(" %5d",
341				    ifnet.if_snd.ifq_drops - ip->ift_dr);
342		}
343		ip->ift_ip = ifnet.if_ipackets;
344		ip->ift_ie = ifnet.if_ierrors;
345		ip->ift_op = ifnet.if_opackets;
346		ip->ift_oe = ifnet.if_oerrors;
347		ip->ift_co = ifnet.if_collisions;
348		ip->ift_dr = ifnet.if_snd.ifq_drops;
349		sum->ift_ip += ip->ift_ip;
350		sum->ift_ie += ip->ift_ie;
351		sum->ift_op += ip->ift_op;
352		sum->ift_oe += ip->ift_oe;
353		sum->ift_co += ip->ift_co;
354		sum->ift_dr += ip->ift_dr;
355		off = (off_t) ifnet.if_next;
356	}
357	if (lastif - iftot > 0) {
358		printf("  %8d %5d %8d %5d %5d",
359			sum->ift_ip - total->ift_ip,
360			sum->ift_ie - total->ift_ie,
361			sum->ift_op - total->ift_op,
362			sum->ift_oe - total->ift_oe,
363			sum->ift_co - total->ift_co);
364		if (dflag)
365			printf(" %5d", sum->ift_dr - total->ift_dr);
366	}
367	*total = *sum;
368	putchar('\n');
369	fflush(stdout);
370	line++;
371	oldmask = sigblock(sigmask(SIGALRM));
372	if (! signalled) {
373		sigpause(0);
374	}
375	sigsetmask(oldmask);
376	signalled = NO;
377	(void)alarm(interval);
378	if (line == 21)
379		goto banner;
380	goto loop;
381	/*NOTREACHED*/
382}
383
384/*
385 * Called if an interval expires before sidewaysintpr has completed a loop.
386 * Sets a flag to not wait for the alarm.
387 */
388void
389catchalarm()
390{
391	signalled = YES;
392}
393