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