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