This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.bin / netstat / if.c
CommitLineData
15637ed4
RG
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, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
49f80972
GW
35/* From: static char sccsid[] = "@(#)if.c 5.15 (Berkeley) 3/1/91"; */
36static const char if_c_rcsid[] =
ebef094c 37 "$Id: if.c,v 1.2 1993/11/17 20:19:19 wollman Exp $";
15637ed4
RG
38#endif /* not lint */
39
40#include <sys/types.h>
41#include <sys/socket.h>
42
43#include <net/if.h>
44#include <net/if_dl.h>
45#include <netinet/in.h>
46#include <netinet/in_var.h>
47
48#ifdef NS
49#include <netns/ns.h>
50#include <netns/ns_if.h>
51#endif /* NS */
52
53#ifdef ISO
54#include <netiso/iso.h>
55#include <netiso/iso_var.h>
56#endif /* ISO */
57
58#include <stdio.h>
59#include <signal.h>
60
61#define YES 1
62#define NO 0
63
64extern int tflag;
65extern int dflag;
66extern int nflag;
67extern char *interface;
68extern int unit;
69extern char *routename(), *netname(), *ns_phost();
70char *index();
71
72/*
73 * Print a description of the network interfaces.
74 */
75intpr(interval, ifnetaddr)
76 int interval;
77 off_t ifnetaddr;
78{
79 struct ifnet ifnet;
80 union {
81 struct ifaddr ifa;
82 struct in_ifaddr in;
83#ifdef NS
84 struct ns_ifaddr ns;
85#endif
86#ifdef ISO
87 struct iso_ifaddr iso;
88#endif
89 } ifaddr;
90 off_t ifaddraddr;
91 struct sockaddr *sa;
92 char name[16];
93
94 if (ifnetaddr == 0) {
95 printf("ifnet: symbol not defined\n");
96 return;
97 }
98 if (interval) {
99 sidewaysintpr((unsigned)interval, ifnetaddr);
100 return;
101 }
102 kvm_read(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr);
103 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s",
104 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
105 "Opkts", "Oerrs");
106 printf(" %5s", "Coll");
107 if (tflag)
108 printf(" %s", "Time");
109 if (dflag)
110 printf(" %s", "Drop");
111 putchar('\n');
112 ifaddraddr = 0;
113 while (ifnetaddr || ifaddraddr) {
114 struct sockaddr_in *sin;
115 register char *cp;
116 int n, m;
117 struct in_addr inet_makeaddr();
118
119 if (ifaddraddr == 0) {
120 kvm_read(ifnetaddr, (char *)&ifnet, sizeof ifnet);
121 kvm_read((off_t)ifnet.if_name, name, 16);
122 name[15] = '\0';
123 ifnetaddr = (off_t) ifnet.if_next;
124 if (interface != 0 &&
125 (strcmp(name, interface) != 0 || unit != ifnet.if_unit))
126 continue;
127 cp = index(name, '\0');
ebef094c 128 cp += sprintf(cp, "%d", ifnet.if_unit);
15637ed4
RG
129 if ((ifnet.if_flags&IFF_UP) == 0)
130 *cp++ = '*';
131 *cp = '\0';
132 ifaddraddr = (off_t)ifnet.if_addrlist;
133 }
134 printf("%-5.5s %-5d ", name, ifnet.if_mtu);
135 if (ifaddraddr == 0) {
136 printf("%-11.11s ", "none");
137 printf("%-15.15s ", "none");
138 } else {
139 kvm_read(ifaddraddr, (char *)&ifaddr, sizeof ifaddr);
140#define CP(x) ((char *)(x))
141 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
142 CP(&ifaddr); sa = (struct sockaddr *)cp;
143 switch (sa->sa_family) {
144 case AF_UNSPEC:
145 printf("%-11.11s ", "none");
146 printf("%-15.15s ", "none");
147 break;
148 case AF_INET:
149 sin = (struct sockaddr_in *)sa;
150#ifdef notdef
151 /* can't use inet_makeaddr because kernel
152 * keeps nets unshifted.
153 */
154 in = inet_makeaddr(ifaddr.in.ia_subnet,
155 INADDR_ANY);
156 printf("%-11.11s ", netname(in));
157#else
158 printf("%-11.11s ",
159 netname(htonl(ifaddr.in.ia_subnet),
160 ifaddr.in.ia_subnetmask));
161#endif
162 printf("%-15.15s ", routename(sin->sin_addr));
163 break;
164#ifdef NS
165 case AF_NS:
166 {
167 struct sockaddr_ns *sns =
168 (struct sockaddr_ns *)sa;
169 u_long net;
170 char netnum[8];
171 char *ns_phost();
172
173 *(union ns_net *) &net = sns->sns_addr.x_net;
174 sprintf(netnum, "%lxH", ntohl(net));
175 upHex(netnum);
176 printf("ns:%-8s ", netnum);
177 printf("%-15s ", ns_phost(sns));
178 }
179 break;
180#endif
181 case AF_LINK:
182 {
183 struct sockaddr_dl *sdl =
184 (struct sockaddr_dl *)sa;
185 cp = (char *)LLADDR(sdl);
186 n = sdl->sdl_alen;
187 }
188 m = printf("<Link>");
189 goto hexprint;
190 default:
191 m = printf("(%d)", sa->sa_family);
192 for (cp = sa->sa_len + (char *)sa;
193 --cp > sa->sa_data && (*cp == 0);) {}
194 n = cp - sa->sa_data + 1;
195 cp = sa->sa_data;
196 hexprint:
197 while (--n >= 0)
198 m += printf("%x%c", *cp++ & 0xff,
199 n > 0 ? '.' : ' ');
200 m = 28 - m;
201 while (m-- > 0)
202 putchar(' ');
203 break;
204 }
205 ifaddraddr = (off_t)ifaddr.ifa.ifa_next;
206 }
207 printf("%8d %5d %8d %5d %5d",
208 ifnet.if_ipackets, ifnet.if_ierrors,
209 ifnet.if_opackets, ifnet.if_oerrors,
210 ifnet.if_collisions);
211 if (tflag)
212 printf(" %3d", ifnet.if_timer);
213 if (dflag)
214 printf(" %3d", ifnet.if_snd.ifq_drops);
215 putchar('\n');
216 }
217}
218
219#define MAXIF 10
220struct iftot {
221 char ift_name[16]; /* interface name */
222 int ift_ip; /* input packets */
223 int ift_ie; /* input errors */
224 int ift_op; /* output packets */
225 int ift_oe; /* output errors */
226 int ift_co; /* collisions */
227 int ift_dr; /* drops */
228} iftot[MAXIF];
229
230u_char signalled; /* set if alarm goes off "early" */
231
232/*
233 * Print a running summary of interface statistics.
234 * Repeat display every interval seconds, showing statistics
235 * collected over that interval. Assumes that interval is non-zero.
236 * First line printed at top of screen is always cumulative.
237 */
238sidewaysintpr(interval, off)
239 unsigned interval;
240 off_t off;
241{
242 struct ifnet ifnet;
243 off_t firstifnet;
244 register struct iftot *ip, *total;
245 register int line;
246 struct iftot *lastif, *sum, *interesting;
247 int oldmask;
248 void catchalarm();
249
250 kvm_read(off, (char *)&firstifnet, sizeof (off_t));
251 lastif = iftot;
252 sum = iftot + MAXIF - 1;
253 total = sum - 1;
254 interesting = iftot;
255 for (off = firstifnet, ip = iftot; off;) {
256 char *cp;
257
258 kvm_read(off, (char *)&ifnet, sizeof ifnet);
259 ip->ift_name[0] = '(';
260 kvm_read((off_t)ifnet.if_name, ip->ift_name + 1, 15);
261 if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
262 unit == ifnet.if_unit)
263 interesting = ip;
264 ip->ift_name[15] = '\0';
265 cp = index(ip->ift_name, '\0');
266 sprintf(cp, "%d)", ifnet.if_unit);
267 ip++;
268 if (ip >= iftot + MAXIF - 2)
269 break;
270 off = (off_t) ifnet.if_next;
271 }
272 lastif = ip;
273
274 (void)signal(SIGALRM, catchalarm);
275 signalled = NO;
276 (void)alarm(interval);
277banner:
278 printf(" input %-6.6s output ", interesting->ift_name);
279 if (lastif - iftot > 0) {
280 if (dflag)
281 printf(" ");
282 printf(" input (Total) output");
283 }
284 for (ip = iftot; ip < iftot + MAXIF; ip++) {
285 ip->ift_ip = 0;
286 ip->ift_ie = 0;
287 ip->ift_op = 0;
288 ip->ift_oe = 0;
289 ip->ift_co = 0;
290 ip->ift_dr = 0;
291 }
292 putchar('\n');
293 printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
294 "packets", "errs", "packets", "errs", "colls");
295 if (dflag)
296 printf("%5.5s ", "drops");
297 if (lastif - iftot > 0)
298 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
299 "packets", "errs", "packets", "errs", "colls");
300 if (dflag)
301 printf(" %5.5s", "drops");
302 putchar('\n');
303 fflush(stdout);
304 line = 0;
305loop:
306 sum->ift_ip = 0;
307 sum->ift_ie = 0;
308 sum->ift_op = 0;
309 sum->ift_oe = 0;
310 sum->ift_co = 0;
311 sum->ift_dr = 0;
312 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
313 kvm_read(off, (char *)&ifnet, sizeof ifnet);
314 if (ip == interesting) {
315 printf("%8d %5d %8d %5d %5d",
316 ifnet.if_ipackets - ip->ift_ip,
317 ifnet.if_ierrors - ip->ift_ie,
318 ifnet.if_opackets - ip->ift_op,
319 ifnet.if_oerrors - ip->ift_oe,
320 ifnet.if_collisions - ip->ift_co);
321 if (dflag)
322 printf(" %5d",
323 ifnet.if_snd.ifq_drops - ip->ift_dr);
324 }
325 ip->ift_ip = ifnet.if_ipackets;
326 ip->ift_ie = ifnet.if_ierrors;
327 ip->ift_op = ifnet.if_opackets;
328 ip->ift_oe = ifnet.if_oerrors;
329 ip->ift_co = ifnet.if_collisions;
330 ip->ift_dr = ifnet.if_snd.ifq_drops;
331 sum->ift_ip += ip->ift_ip;
332 sum->ift_ie += ip->ift_ie;
333 sum->ift_op += ip->ift_op;
334 sum->ift_oe += ip->ift_oe;
335 sum->ift_co += ip->ift_co;
336 sum->ift_dr += ip->ift_dr;
337 off = (off_t) ifnet.if_next;
338 }
339 if (lastif - iftot > 0) {
340 printf(" %8d %5d %8d %5d %5d",
341 sum->ift_ip - total->ift_ip,
342 sum->ift_ie - total->ift_ie,
343 sum->ift_op - total->ift_op,
344 sum->ift_oe - total->ift_oe,
345 sum->ift_co - total->ift_co);
346 if (dflag)
347 printf(" %5d", sum->ift_dr - total->ift_dr);
348 }
349 *total = *sum;
350 putchar('\n');
351 fflush(stdout);
352 line++;
353 oldmask = sigblock(sigmask(SIGALRM));
354 if (! signalled) {
355 sigpause(0);
356 }
357 sigsetmask(oldmask);
358 signalled = NO;
359 (void)alarm(interval);
360 if (line == 21)
361 goto banner;
362 goto loop;
363 /*NOTREACHED*/
364}
365
366/*
367 * Called if an interval expires before sidewaysintpr has completed a loop.
368 * Sets a flag to not wait for the alarm.
369 */
370void
371catchalarm()
372{
373 signalled = YES;
374}