4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / netstat / if.c
CommitLineData
5ff67f98 1/*
2839532b
KB
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
ee3f90a5 4 *
87198c0c 5 * %sccs.include.redist.c%
5ff67f98
DF
6 */
7
55bef820 8#ifndef lint
2839532b 9static char sccsid[] = "@(#)if.c 8.1 (Berkeley) %G%";
b36fc510 10#endif /* not lint */
55bef820
SL
11
12#include <sys/types.h>
6e549c8f 13#include <sys/protosw.h>
55bef820 14#include <sys/socket.h>
55bef820 15#include <net/if.h>
7eeb8bb9 16#include <net/if_dl.h>
44906619 17#include <netinet/in.h>
cab3a575 18#include <netinet/in_var.h>
f1fbb01b 19#include <netns/ns.h>
3e117255 20#include <netns/ns_if.h>
c34ecf77
KS
21#include <netiso/iso.h>
22#include <netiso/iso_var.h>
44906619 23
6e549c8f 24#include <arpa/inet.h>
90cb8200 25#include <stdio.h>
6e549c8f 26#include <string.h>
39fef23d 27#include <signal.h>
27788811 28#include <unistd.h>
6e549c8f 29#include "netstat.h"
39fef23d
MK
30
31#define YES 1
32#define NO 0
55bef820 33
d1cfb820 34static void sidewaysintpr __P((unsigned, u_long));
6e549c8f 35static void catchalarm __P(());
55bef820
SL
36
37/*
38 * Print a description of the network interfaces.
55bef820 39 */
6e549c8f 40void
55bef820
SL
41intpr(interval, ifnetaddr)
42 int interval;
d1cfb820 43 u_long ifnetaddr;
55bef820
SL
44{
45 struct ifnet ifnet;
cab3a575
MK
46 union {
47 struct ifaddr ifa;
48 struct in_ifaddr in;
3e117255 49 struct ns_ifaddr ns;
c34ecf77 50 struct iso_ifaddr iso;
cab3a575 51 } ifaddr;
d1cfb820 52 u_long ifaddraddr;
3e117255 53 struct sockaddr *sa;
55bef820
SL
54 char name[16];
55
56 if (ifnetaddr == 0) {
57 printf("ifnet: symbol not defined\n");
58 return;
59 }
60 if (interval) {
39fef23d 61 sidewaysintpr((unsigned)interval, ifnetaddr);
55bef820
SL
62 return;
63 }
6e549c8f
KS
64 if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr))
65 return;
1ecc0948 66 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s",
55bef820
SL
67 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
68 "Opkts", "Oerrs");
1ecc0948 69 printf(" %5s", "Coll");
55bef820 70 if (tflag)
1ecc0948 71 printf(" %s", "Time");
2ebaad6c
MK
72 if (dflag)
73 printf(" %s", "Drop");
55bef820 74 putchar('\n');
cab3a575
MK
75 ifaddraddr = 0;
76 while (ifnetaddr || ifaddraddr) {
55bef820
SL
77 struct sockaddr_in *sin;
78 register char *cp;
7eeb8bb9 79 int n, m;
55bef820 80
cab3a575 81 if (ifaddraddr == 0) {
6e549c8f 82 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
d1cfb820 83 kread((u_long)ifnet.if_name, name, 16))
6e549c8f 84 return;
cab3a575 85 name[15] = '\0';
d1cfb820 86 ifnetaddr = (u_long) ifnet.if_next;
cab3a575
MK
87 if (interface != 0 &&
88 (strcmp(name, interface) != 0 || unit != ifnet.if_unit))
89 continue;
90 cp = index(name, '\0');
91 *cp++ = ifnet.if_unit + '0';
92 if ((ifnet.if_flags&IFF_UP) == 0)
93 *cp++ = '*';
94 *cp = '\0';
d1cfb820 95 ifaddraddr = (u_long)ifnet.if_addrlist;
cab3a575 96 }
55bef820 97 printf("%-5.5s %-5d ", name, ifnet.if_mtu);
cab3a575 98 if (ifaddraddr == 0) {
1ecc0948
MK
99 printf("%-11.11s ", "none");
100 printf("%-15.15s ", "none");
cab3a575 101 } else {
6e549c8f
KS
102 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
103 ifaddraddr = 0;
104 continue;
105 }
3e117255
MT
106#define CP(x) ((char *)(x))
107 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
108 CP(&ifaddr); sa = (struct sockaddr *)cp;
109 switch (sa->sa_family) {
cab3a575 110 case AF_UNSPEC:
1ecc0948
MK
111 printf("%-11.11s ", "none");
112 printf("%-15.15s ", "none");
cab3a575
MK
113 break;
114 case AF_INET:
3e117255 115 sin = (struct sockaddr_in *)sa;
cab3a575
MK
116#ifdef notdef
117 /* can't use inet_makeaddr because kernel
118 * keeps nets unshifted.
119 */
120 in = inet_makeaddr(ifaddr.in.ia_subnet,
121 INADDR_ANY);
6e549c8f
KS
122 printf("%-11.11s ", netname(in.s_addr,
123 ifaddr.in.ia_subnetmask));
cab3a575 124#else
1ecc0948 125 printf("%-11.11s ",
6e549c8f
KS
126 netname(htonl(ifaddr.in.ia_subnet),
127 ifaddr.in.ia_subnetmask));
cab3a575 128#endif
6e549c8f
KS
129 printf("%-15.15s ",
130 routename(sin->sin_addr.s_addr));
cab3a575 131 break;
f1fbb01b
KS
132 case AF_NS:
133 {
134 struct sockaddr_ns *sns =
3e117255 135 (struct sockaddr_ns *)sa;
39fef23d 136 u_long net;
1ecc0948 137 char netnum[8];
39fef23d 138
2ff355d6 139 *(union ns_net *) &net = sns->sns_addr.x_net;
3e117255 140 sprintf(netnum, "%lxH", ntohl(net));
1ecc0948
MK
141 upHex(netnum);
142 printf("ns:%-8s ", netnum);
6e549c8f
KS
143 printf("%-15s ",
144 ns_phost((struct sockaddr *)sns));
f1fbb01b
KS
145 }
146 break;
7eeb8bb9
KS
147 case AF_LINK:
148 {
149 struct sockaddr_dl *sdl =
150 (struct sockaddr_dl *)sa;
80b7fcad
KS
151 cp = (char *)LLADDR(sdl);
152 n = sdl->sdl_alen;
7eeb8bb9 153 }
80b7fcad
KS
154 m = printf("<Link>");
155 goto hexprint;
cab3a575 156 default:
80b7fcad
KS
157 m = printf("(%d)", sa->sa_family);
158 for (cp = sa->sa_len + (char *)sa;
159 --cp > sa->sa_data && (*cp == 0);) {}
3e117255
MT
160 n = cp - sa->sa_data + 1;
161 cp = sa->sa_data;
7eeb8bb9 162 hexprint:
80b7fcad
KS
163 while (--n >= 0)
164 m += printf("%x%c", *cp++ & 0xff,
165 n > 0 ? '.' : ' ');
166 m = 28 - m;
7eeb8bb9
KS
167 while (m-- > 0)
168 putchar(' ');
cab3a575
MK
169 break;
170 }
d1cfb820 171 ifaddraddr = (u_long)ifaddr.ifa.ifa_next;
cab3a575 172 }
1ecc0948 173 printf("%8d %5d %8d %5d %5d",
55bef820
SL
174 ifnet.if_ipackets, ifnet.if_ierrors,
175 ifnet.if_opackets, ifnet.if_oerrors,
176 ifnet.if_collisions);
177 if (tflag)
1ecc0948 178 printf(" %3d", ifnet.if_timer);
2ebaad6c
MK
179 if (dflag)
180 printf(" %3d", ifnet.if_snd.ifq_drops);
55bef820 181 putchar('\n');
55bef820
SL
182 }
183}
184
90cb8200
SL
185#define MAXIF 10
186struct iftot {
187 char ift_name[16]; /* interface name */
188 int ift_ip; /* input packets */
189 int ift_ie; /* input errors */
190 int ift_op; /* output packets */
191 int ift_oe; /* output errors */
192 int ift_co; /* collisions */
2ebaad6c 193 int ift_dr; /* drops */
90cb8200
SL
194} iftot[MAXIF];
195
39fef23d
MK
196u_char signalled; /* set if alarm goes off "early" */
197
90cb8200
SL
198/*
199 * Print a running summary of interface statistics.
39fef23d
MK
200 * Repeat display every interval seconds, showing statistics
201 * collected over that interval. Assumes that interval is non-zero.
202 * First line printed at top of screen is always cumulative.
90cb8200 203 */
6e549c8f 204static void
55bef820 205sidewaysintpr(interval, off)
39fef23d 206 unsigned interval;
d1cfb820 207 u_long off;
55bef820
SL
208{
209 struct ifnet ifnet;
d1cfb820 210 u_long firstifnet;
90cb8200
SL
211 register struct iftot *ip, *total;
212 register int line;
213 struct iftot *lastif, *sum, *interesting;
39fef23d 214 int oldmask;
55bef820 215
d1cfb820 216 if (kread(off, (char *)&firstifnet, sizeof (u_long)))
6e549c8f 217 return;
90cb8200
SL
218 lastif = iftot;
219 sum = iftot + MAXIF - 1;
220 total = sum - 1;
79ddba48 221 interesting = iftot;
90cb8200
SL
222 for (off = firstifnet, ip = iftot; off;) {
223 char *cp;
55bef820 224
6e549c8f
KS
225 if (kread(off, (char *)&ifnet, sizeof ifnet))
226 break;
90cb8200 227 ip->ift_name[0] = '(';
d1cfb820 228 if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15))
6e549c8f 229 break;
79ddba48
EW
230 if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
231 unit == ifnet.if_unit)
232 interesting = ip;
90cb8200
SL
233 ip->ift_name[15] = '\0';
234 cp = index(ip->ift_name, '\0');
235 sprintf(cp, "%d)", ifnet.if_unit);
236 ip++;
237 if (ip >= iftot + MAXIF - 2)
238 break;
d1cfb820 239 off = (u_long) ifnet.if_next;
90cb8200
SL
240 }
241 lastif = ip;
39fef23d
MK
242
243 (void)signal(SIGALRM, catchalarm);
244 signalled = NO;
245 (void)alarm(interval);
90cb8200 246banner:
2ebaad6c
MK
247 printf(" input %-6.6s output ", interesting->ift_name);
248 if (lastif - iftot > 0) {
249 if (dflag)
250 printf(" ");
251 printf(" input (Total) output");
252 }
90cb8200
SL
253 for (ip = iftot; ip < iftot + MAXIF; ip++) {
254 ip->ift_ip = 0;
255 ip->ift_ie = 0;
256 ip->ift_op = 0;
257 ip->ift_oe = 0;
258 ip->ift_co = 0;
2ebaad6c 259 ip->ift_dr = 0;
90cb8200
SL
260 }
261 putchar('\n');
1ecc0948 262 printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
90cb8200 263 "packets", "errs", "packets", "errs", "colls");
2ebaad6c
MK
264 if (dflag)
265 printf("%5.5s ", "drops");
90cb8200 266 if (lastif - iftot > 0)
2ebaad6c 267 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
90cb8200 268 "packets", "errs", "packets", "errs", "colls");
2ebaad6c
MK
269 if (dflag)
270 printf(" %5.5s", "drops");
90cb8200
SL
271 putchar('\n');
272 fflush(stdout);
273 line = 0;
274loop:
275 sum->ift_ip = 0;
276 sum->ift_ie = 0;
277 sum->ift_op = 0;
278 sum->ift_oe = 0;
279 sum->ift_co = 0;
2ebaad6c 280 sum->ift_dr = 0;
90cb8200 281 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
6e549c8f
KS
282 if (kread(off, (char *)&ifnet, sizeof ifnet)) {
283 off = 0;
284 continue;
285 }
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;
d1cfb820 309 off = (u_long) ifnet.if_next;
55bef820 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 */
6e549c8f 342static void
39fef23d
MK
343catchalarm()
344{
345 signalled = YES;
346}