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