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