4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / netstat / if.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
9static char sccsid[] = "@(#)if.c 8.1 (Berkeley) %G%";
10#endif /* not lint */
11
12#include <sys/types.h>
13#include <sys/protosw.h>
14#include <sys/socket.h>
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 <arpa/inet.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29#include "netstat.h"
30
31#define YES 1
32#define NO 0
33
34static void sidewaysintpr __P((unsigned, u_long));
35static void catchalarm __P(());
36
37/*
38 * Print a description of the network interfaces.
39 */
40void
41intpr(interval, ifnetaddr)
42 int interval;
43 u_long ifnetaddr;
44{
45 struct ifnet ifnet;
46 union {
47 struct ifaddr ifa;
48 struct in_ifaddr in;
49 struct ns_ifaddr ns;
50 struct iso_ifaddr iso;
51 } ifaddr;
52 u_long ifaddraddr;
53 struct sockaddr *sa;
54 char name[16];
55
56 if (ifnetaddr == 0) {
57 printf("ifnet: symbol not defined\n");
58 return;
59 }
60 if (interval) {
61 sidewaysintpr((unsigned)interval, ifnetaddr);
62 return;
63 }
64 if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr))
65 return;
66 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s",
67 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
68 "Opkts", "Oerrs");
69 printf(" %5s", "Coll");
70 if (tflag)
71 printf(" %s", "Time");
72 if (dflag)
73 printf(" %s", "Drop");
74 putchar('\n');
75 ifaddraddr = 0;
76 while (ifnetaddr || ifaddraddr) {
77 struct sockaddr_in *sin;
78 register char *cp;
79 int n, m;
80
81 if (ifaddraddr == 0) {
82 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
83 kread((u_long)ifnet.if_name, name, 16))
84 return;
85 name[15] = '\0';
86 ifnetaddr = (u_long) ifnet.if_next;
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';
95 ifaddraddr = (u_long)ifnet.if_addrlist;
96 }
97 printf("%-5.5s %-5d ", name, ifnet.if_mtu);
98 if (ifaddraddr == 0) {
99 printf("%-11.11s ", "none");
100 printf("%-15.15s ", "none");
101 } else {
102 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
103 ifaddraddr = 0;
104 continue;
105 }
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) {
110 case AF_UNSPEC:
111 printf("%-11.11s ", "none");
112 printf("%-15.15s ", "none");
113 break;
114 case AF_INET:
115 sin = (struct sockaddr_in *)sa;
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);
122 printf("%-11.11s ", netname(in.s_addr,
123 ifaddr.in.ia_subnetmask));
124#else
125 printf("%-11.11s ",
126 netname(htonl(ifaddr.in.ia_subnet),
127 ifaddr.in.ia_subnetmask));
128#endif
129 printf("%-15.15s ",
130 routename(sin->sin_addr.s_addr));
131 break;
132 case AF_NS:
133 {
134 struct sockaddr_ns *sns =
135 (struct sockaddr_ns *)sa;
136 u_long net;
137 char netnum[8];
138
139 *(union ns_net *) &net = sns->sns_addr.x_net;
140 sprintf(netnum, "%lxH", ntohl(net));
141 upHex(netnum);
142 printf("ns:%-8s ", netnum);
143 printf("%-15s ",
144 ns_phost((struct sockaddr *)sns));
145 }
146 break;
147 case AF_LINK:
148 {
149 struct sockaddr_dl *sdl =
150 (struct sockaddr_dl *)sa;
151 cp = (char *)LLADDR(sdl);
152 n = sdl->sdl_alen;
153 }
154 m = printf("<Link>");
155 goto hexprint;
156 default:
157 m = printf("(%d)", sa->sa_family);
158 for (cp = sa->sa_len + (char *)sa;
159 --cp > sa->sa_data && (*cp == 0);) {}
160 n = cp - sa->sa_data + 1;
161 cp = sa->sa_data;
162 hexprint:
163 while (--n >= 0)
164 m += printf("%x%c", *cp++ & 0xff,
165 n > 0 ? '.' : ' ');
166 m = 28 - m;
167 while (m-- > 0)
168 putchar(' ');
169 break;
170 }
171 ifaddraddr = (u_long)ifaddr.ifa.ifa_next;
172 }
173 printf("%8d %5d %8d %5d %5d",
174 ifnet.if_ipackets, ifnet.if_ierrors,
175 ifnet.if_opackets, ifnet.if_oerrors,
176 ifnet.if_collisions);
177 if (tflag)
178 printf(" %3d", ifnet.if_timer);
179 if (dflag)
180 printf(" %3d", ifnet.if_snd.ifq_drops);
181 putchar('\n');
182 }
183}
184
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 */
193 int ift_dr; /* drops */
194} iftot[MAXIF];
195
196u_char signalled; /* set if alarm goes off "early" */
197
198/*
199 * Print a running summary of interface statistics.
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.
203 */
204static void
205sidewaysintpr(interval, off)
206 unsigned interval;
207 u_long off;
208{
209 struct ifnet ifnet;
210 u_long firstifnet;
211 register struct iftot *ip, *total;
212 register int line;
213 struct iftot *lastif, *sum, *interesting;
214 int oldmask;
215
216 if (kread(off, (char *)&firstifnet, sizeof (u_long)))
217 return;
218 lastif = iftot;
219 sum = iftot + MAXIF - 1;
220 total = sum - 1;
221 interesting = iftot;
222 for (off = firstifnet, ip = iftot; off;) {
223 char *cp;
224
225 if (kread(off, (char *)&ifnet, sizeof ifnet))
226 break;
227 ip->ift_name[0] = '(';
228 if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15))
229 break;
230 if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
231 unit == ifnet.if_unit)
232 interesting = ip;
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;
239 off = (u_long) ifnet.if_next;
240 }
241 lastif = ip;
242
243 (void)signal(SIGALRM, catchalarm);
244 signalled = NO;
245 (void)alarm(interval);
246banner:
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 }
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;
259 ip->ift_dr = 0;
260 }
261 putchar('\n');
262 printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
263 "packets", "errs", "packets", "errs", "colls");
264 if (dflag)
265 printf("%5.5s ", "drops");
266 if (lastif - iftot > 0)
267 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
268 "packets", "errs", "packets", "errs", "colls");
269 if (dflag)
270 printf(" %5.5s", "drops");
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;
280 sum->ift_dr = 0;
281 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
282 if (kread(off, (char *)&ifnet, sizeof ifnet)) {
283 off = 0;
284 continue;
285 }
286 if (ip == interesting) {
287 printf("%8d %5d %8d %5d %5d",
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);
293 if (dflag)
294 printf(" %5d",
295 ifnet.if_snd.ifq_drops - ip->ift_dr);
296 }
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;
302 ip->ift_dr = ifnet.if_snd.ifq_drops;
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;
308 sum->ift_dr += ip->ift_dr;
309 off = (u_long) ifnet.if_next;
310 }
311 if (lastif - iftot > 0) {
312 printf(" %8d %5d %8d %5d %5d",
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);
318 if (dflag)
319 printf(" %5d", sum->ift_dr - total->ift_dr);
320 }
321 *total = *sum;
322 putchar('\n');
323 fflush(stdout);
324 line++;
325 oldmask = sigblock(sigmask(SIGALRM));
326 if (! signalled) {
327 sigpause(0);
328 }
329 sigsetmask(oldmask);
330 signalled = NO;
331 (void)alarm(interval);
332 if (line == 21)
333 goto banner;
334 goto loop;
335 /*NOTREACHED*/
336}
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 */
342static void
343catchalarm()
344{
345 signalled = YES;
346}