if.c revision 1.4 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
35 /*static char sccsid[] = "from: @(#)if.c 5.15 (Berkeley) 3/1/91";*/
36 static char rcsid[] = "$Id: if.c,v 1.4 1994/02/22 04:19:37 cgd Exp $";
37 #endif /* not lint */
38
39 #include <sys/types.h>
40 #include <sys/socket.h>
41
42 #include <net/if.h>
43 #include <net/if_dl.h>
44 #include <netinet/in.h>
45 #include <netinet/in_var.h>
46
47 #ifdef NS
48 #include <netns/ns.h>
49 #include <netns/ns_if.h>
50 #endif /* NS */
51
52 #ifdef ISO
53 #include <netiso/iso.h>
54 #include <netiso/iso_var.h>
55 #endif /* ISO */
56
57 #include <stdio.h>
58 #include <signal.h>
59
60 #define YES 1
61 #define NO 0
62
63 extern int tflag;
64 extern int dflag;
65 extern int nflag;
66 extern char *interface;
67 extern int unit;
68 extern char *routename(), *netname(), *ns_phost();
69 char *index();
70
71 /*
72 * Print a description of the network interfaces.
73 */
74 intpr(interval, ifnetaddr)
75 int interval;
76 off_t ifnetaddr;
77 {
78 struct ifnet ifnet;
79 union {
80 struct ifaddr ifa;
81 struct in_ifaddr in;
82 #ifdef NS
83 struct ns_ifaddr ns;
84 #endif
85 #ifdef ISO
86 struct iso_ifaddr iso;
87 #endif
88 } ifaddr;
89 off_t ifaddraddr;
90 struct sockaddr *sa;
91 char name[16];
92
93 if (ifnetaddr == 0) {
94 printf("ifnet: symbol not defined\n");
95 return;
96 }
97 if (interval) {
98 sidewaysintpr((unsigned)interval, ifnetaddr);
99 return;
100 }
101 kvm_read(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr);
102 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s",
103 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs",
104 "Opkts", "Oerrs");
105 printf(" %5s", "Coll");
106 if (tflag)
107 printf(" %s", "Time");
108 if (dflag)
109 printf(" %s", "Drop");
110 putchar('\n');
111 ifaddraddr = 0;
112 while (ifnetaddr || ifaddraddr) {
113 struct sockaddr_in *sin;
114 #ifdef ISO
115 struct sockaddr_iso *siso;
116 #endif
117 register char *cp;
118 int n, m;
119 struct in_addr inet_makeaddr();
120
121 if (ifaddraddr == 0) {
122 kvm_read(ifnetaddr, (char *)&ifnet, sizeof ifnet);
123 kvm_read((off_t)ifnet.if_name, name, 16);
124 name[15] = '\0';
125 ifnetaddr = (off_t) ifnet.if_next;
126 if (interface != 0 &&
127 (strcmp(name, interface) != 0 || unit != ifnet.if_unit))
128 continue;
129 cp = index(name, '\0');
130 cp += sprintf(cp, "%d", ifnet.if_unit);
131 if ((ifnet.if_flags&IFF_UP) == 0)
132 *cp++ = '*';
133 *cp = '\0';
134 ifaddraddr = (off_t)ifnet.if_addrlist;
135 }
136 printf("%-5.5s %-5d ", name, ifnet.if_mtu);
137 if (ifaddraddr == 0) {
138 printf("%-11.11s ", "none");
139 printf("%-15.15s ", "none");
140 } else {
141 kvm_read(ifaddraddr, (char *)&ifaddr, sizeof ifaddr);
142 #define CP(x) ((char *)(x))
143 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
144 CP(&ifaddr); sa = (struct sockaddr *)cp;
145 switch (sa->sa_family) {
146 case AF_UNSPEC:
147 printf("%-11.11s ", "none");
148 printf("%-15.15s ", "none");
149 break;
150 case AF_INET:
151 sin = (struct sockaddr_in *)sa;
152 #ifdef notdef
153 /* can't use inet_makeaddr because kernel
154 * keeps nets unshifted.
155 */
156 in = inet_makeaddr(ifaddr.in.ia_subnet,
157 INADDR_ANY);
158 printf("%-11.11s ", netname(in));
159 #else
160 printf("%-11.11s ",
161 netname(htonl(ifaddr.in.ia_subnet),
162 ifaddr.in.ia_subnetmask));
163 #endif
164 printf("%-15.15s ", routename(sin->sin_addr));
165 break;
166 #ifdef NS
167 case AF_NS:
168 {
169 struct sockaddr_ns *sns =
170 (struct sockaddr_ns *)sa;
171 u_long net;
172 char netnum[8];
173 char *ns_phost();
174
175 *(union ns_net *) &net = sns->sns_addr.x_net;
176 sprintf(netnum, "%lxH", ntohl(net));
177 upHex(netnum);
178 printf("ns:%-8s ", netnum);
179 printf("%-15s ", ns_phost(sns));
180 }
181 break;
182 #endif
183 case AF_LINK:
184 {
185 struct sockaddr_dl *sdl =
186 (struct sockaddr_dl *)sa;
187 cp = (char *)LLADDR(sdl);
188 n = sdl->sdl_alen;
189 }
190 m = printf("%-11.11s ","<Link>");
191 goto hexprint;
192 #ifdef ISO
193 case AF_ISO:
194 siso = (struct sockaddr_iso *)sa;
195 if(nflag) {
196 printf("%27s ",
197 iso_ntoa(&siso->siso_addr));
198 } else {
199 /* This will probably truncate the */
200 /* NSAP prefix */
201 printf("%-11.11s ",
202 iso_ntoa(&siso->siso_addr));
203 printf("%-15.15s ",
204 iso_idtoa(&siso->siso_addr));
205 }
206 break;
207 #endif
208 default:
209 m = printf("(%d)", sa->sa_family);
210 for (cp = sa->sa_len + (char *)sa;
211 --cp > sa->sa_data && (*cp == 0);) {}
212 n = cp - sa->sa_data + 1;
213 cp = sa->sa_data;
214 hexprint:
215 while (--n >= 0)
216 m += printf("%x%c", *cp++ & 0xff,
217 n > 0 ? '.' : ' ');
218 m = 28 - m;
219 while (m-- > 0)
220 putchar(' ');
221 break;
222 }
223 ifaddraddr = (off_t)ifaddr.ifa.ifa_next;
224 }
225 printf("%8d %5d %8d %5d %5d",
226 ifnet.if_ipackets, ifnet.if_ierrors,
227 ifnet.if_opackets, ifnet.if_oerrors,
228 ifnet.if_collisions);
229 if (tflag)
230 printf(" %3d", ifnet.if_timer);
231 if (dflag)
232 printf(" %3d", ifnet.if_snd.ifq_drops);
233 putchar('\n');
234 }
235 }
236
237 #define MAXIF 10
238 struct iftot {
239 char ift_name[16]; /* interface name */
240 int ift_ip; /* input packets */
241 int ift_ie; /* input errors */
242 int ift_op; /* output packets */
243 int ift_oe; /* output errors */
244 int ift_co; /* collisions */
245 int ift_dr; /* drops */
246 } iftot[MAXIF];
247
248 u_char signalled; /* set if alarm goes off "early" */
249
250 /*
251 * Print a running summary of interface statistics.
252 * Repeat display every interval seconds, showing statistics
253 * collected over that interval. Assumes that interval is non-zero.
254 * First line printed at top of screen is always cumulative.
255 */
256 sidewaysintpr(interval, off)
257 unsigned interval;
258 off_t off;
259 {
260 struct ifnet ifnet;
261 off_t firstifnet;
262 register struct iftot *ip, *total;
263 register int line;
264 struct iftot *lastif, *sum, *interesting;
265 int oldmask;
266 void catchalarm();
267
268 kvm_read(off, (char *)&firstifnet, sizeof (off_t));
269 lastif = iftot;
270 sum = iftot + MAXIF - 1;
271 total = sum - 1;
272 interesting = iftot;
273 for (off = firstifnet, ip = iftot; off;) {
274 char *cp;
275
276 kvm_read(off, (char *)&ifnet, sizeof ifnet);
277 ip->ift_name[0] = '(';
278 kvm_read((off_t)ifnet.if_name, ip->ift_name + 1, 15);
279 if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
280 unit == ifnet.if_unit)
281 interesting = ip;
282 ip->ift_name[15] = '\0';
283 cp = index(ip->ift_name, '\0');
284 sprintf(cp, "%d)", ifnet.if_unit);
285 ip++;
286 if (ip >= iftot + MAXIF - 2)
287 break;
288 off = (off_t) ifnet.if_next;
289 }
290 lastif = ip;
291
292 (void)signal(SIGALRM, catchalarm);
293 signalled = NO;
294 (void)alarm(interval);
295 banner:
296 printf(" input %-6.6s output ", interesting->ift_name);
297 if (lastif - iftot > 0) {
298 if (dflag)
299 printf(" ");
300 printf(" input (Total) output");
301 }
302 for (ip = iftot; ip < iftot + MAXIF; ip++) {
303 ip->ift_ip = 0;
304 ip->ift_ie = 0;
305 ip->ift_op = 0;
306 ip->ift_oe = 0;
307 ip->ift_co = 0;
308 ip->ift_dr = 0;
309 }
310 putchar('\n');
311 printf("%8.8s %5.5s %8.8s %5.5s %5.5s ",
312 "packets", "errs", "packets", "errs", "colls");
313 if (dflag)
314 printf("%5.5s ", "drops");
315 if (lastif - iftot > 0)
316 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
317 "packets", "errs", "packets", "errs", "colls");
318 if (dflag)
319 printf(" %5.5s", "drops");
320 putchar('\n');
321 fflush(stdout);
322 line = 0;
323 loop:
324 sum->ift_ip = 0;
325 sum->ift_ie = 0;
326 sum->ift_op = 0;
327 sum->ift_oe = 0;
328 sum->ift_co = 0;
329 sum->ift_dr = 0;
330 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
331 kvm_read(off, (char *)&ifnet, sizeof ifnet);
332 if (ip == interesting) {
333 printf("%8d %5d %8d %5d %5d",
334 ifnet.if_ipackets - ip->ift_ip,
335 ifnet.if_ierrors - ip->ift_ie,
336 ifnet.if_opackets - ip->ift_op,
337 ifnet.if_oerrors - ip->ift_oe,
338 ifnet.if_collisions - ip->ift_co);
339 if (dflag)
340 printf(" %5d",
341 ifnet.if_snd.ifq_drops - ip->ift_dr);
342 }
343 ip->ift_ip = ifnet.if_ipackets;
344 ip->ift_ie = ifnet.if_ierrors;
345 ip->ift_op = ifnet.if_opackets;
346 ip->ift_oe = ifnet.if_oerrors;
347 ip->ift_co = ifnet.if_collisions;
348 ip->ift_dr = ifnet.if_snd.ifq_drops;
349 sum->ift_ip += ip->ift_ip;
350 sum->ift_ie += ip->ift_ie;
351 sum->ift_op += ip->ift_op;
352 sum->ift_oe += ip->ift_oe;
353 sum->ift_co += ip->ift_co;
354 sum->ift_dr += ip->ift_dr;
355 off = (off_t) ifnet.if_next;
356 }
357 if (lastif - iftot > 0) {
358 printf(" %8d %5d %8d %5d %5d",
359 sum->ift_ip - total->ift_ip,
360 sum->ift_ie - total->ift_ie,
361 sum->ift_op - total->ift_op,
362 sum->ift_oe - total->ift_oe,
363 sum->ift_co - total->ift_co);
364 if (dflag)
365 printf(" %5d", sum->ift_dr - total->ift_dr);
366 }
367 *total = *sum;
368 putchar('\n');
369 fflush(stdout);
370 line++;
371 oldmask = sigblock(sigmask(SIGALRM));
372 if (! signalled) {
373 sigpause(0);
374 }
375 sigsetmask(oldmask);
376 signalled = NO;
377 (void)alarm(interval);
378 if (line == 21)
379 goto banner;
380 goto loop;
381 /*NOTREACHED*/
382 }
383
384 /*
385 * Called if an interval expires before sidewaysintpr has completed a loop.
386 * Sets a flag to not wait for the alarm.
387 */
388 void
389 catchalarm()
390 {
391 signalled = YES;
392 }
393