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