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