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