Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / network / common / C / netstat / if.c
blobe53591b5335ab98e5f0a08182839450cde80d7a6
1 /*
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 2006
5 * Pavel Fedin
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 /* "@(#)if.c 8.2 (Berkeley) 2/21/94" */
38 #include <devices/timer.h>
39 #include <dos/dos.h>
40 #include <proto/exec.h>
42 #include <sys/types.h>
43 #include <sys/protosw.h>
44 #include <sys/socket.h>
46 #include <net/if.h>
47 #include <net/if_dl.h>
48 #include <netinet/in.h>
49 #include <netinet/in_var.h>
50 #ifdef NETNS
51 #include <netns/ns.h>
52 #include <netns/ns_if.h>
53 #endif
54 #ifdef ISO
55 #include <netiso/iso.h>
56 #include <netiso/iso_var.h>
57 #endif
58 #include <arpa/inet.h>
60 #include <signal.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <unistd.h>
65 #include "netstat.h"
67 #define YES 1
68 #define NO 0
70 static void sidewaysintpr __P((u_int, u_long));
71 static void catchalarm __P((int));
74 * Print a description of the network interfaces.
76 void
77 intpr(interval, ifnetaddr)
78 int interval;
79 u_long ifnetaddr;
81 struct ifnet ifnet;
82 union {
83 struct ifaddr ifa;
84 struct in_ifaddr in;
85 #ifdef NETNS
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];
96 if (ifnetaddr == 0) {
97 printf("ifnet: symbol not defined\n");
98 return;
100 if (interval) {
101 sidewaysintpr((unsigned)interval, ifnetaddr);
102 return;
104 if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr))
105 return;
106 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s",
107 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
108 if (bflag)
109 printf(" %10.10s","Ibytes");
110 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
111 if (bflag)
112 printf(" %10.10s","Obytes");
113 printf(" %5s", "Coll");
114 if (tflag)
115 printf(" %s", "Time");
116 if (dflag)
117 printf(" %s", "Drop");
118 putchar('\n');
119 ifaddraddr = 0;
120 while (ifnetaddr || ifaddraddr) {
121 struct sockaddr_in *sin;
122 register char *cp;
123 int n, m;
125 if (ifaddraddr == 0) {
126 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) ||
127 kread((u_long)ifnet.if_name, name, 16))
128 return;
129 name[15] = '\0';
130 ifnetaddr = (u_long)ifnet.if_next;
131 if (interface != 0 && (strcmp(name, interface) != 0 ||
132 unit != ifnet.if_unit))
133 continue;
134 cp = index(name, '\0');
135 cp += sprintf(cp, "%d", ifnet.if_unit);
136 if ((ifnet.if_flags&IFF_UP) == 0)
137 *cp++ = '*';
138 *cp = '\0';
139 ifaddraddr = (u_long)ifnet.if_addrlist;
141 printf("%-5.5s %-5d ", name, ifnet.if_mtu);
142 if (ifaddraddr == 0) {
143 printf("%-11.11s ", "none");
144 printf("%-15.15s ", "none");
145 } else {
146 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) {
147 ifaddraddr = 0;
148 continue;
150 #define CP(x) ((char *)(x))
151 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
152 CP(&ifaddr); sa = (struct sockaddr *)cp;
153 switch (sa->sa_family) {
154 case AF_UNSPEC:
155 printf("%-11.11s ", "none");
156 printf("%-15.15s ", "none");
157 break;
158 case AF_INET:
159 sin = (struct sockaddr_in *)sa;
160 #ifdef notdef
161 /* can't use inet_makeaddr because kernel
162 * keeps nets unshifted.
164 in = inet_makeaddr(ifaddr.in.ia_subnet,
165 INADDR_ANY);
166 printf("%-11.11s ", netname(in.s_addr,
167 ifaddr.in.ia_subnetmask));
168 #else
169 printf("%-11.11s ",
170 netname(htonl(ifaddr.in.ia_subnet),
171 ifaddr.in.ia_subnetmask));
172 #endif
173 printf("%-15.15s ",
174 routename(sin->sin_addr.s_addr));
175 break;
176 #ifdef NETNS
177 case AF_NS:
179 struct sockaddr_ns *sns =
180 (struct sockaddr_ns *)sa;
181 u_long net;
182 char netnum[8];
184 *(union ns_net *) &net = sns->sns_addr.x_net;
185 sprintf(netnum, "%lxH", ntohl(net));
186 upHex(netnum);
187 printf("ns:%-8s ", netnum);
188 printf("%-15s ",
189 ns_phost((struct sockaddr *)sns));
191 break;
192 #endif
193 case AF_LINK:
195 struct sockaddr_dl *sdl =
196 (struct sockaddr_dl *)sa;
197 cp = (char *)LLADDR(sdl);
198 n = sdl->sdl_alen;
200 m = printf("<Link>");
201 goto hexprint;
202 default:
203 m = printf("(%d)", sa->sa_family);
204 for (cp = sa->sa_len + (char *)sa;
205 --cp > sa->sa_data && (*cp == 0);) {}
206 n = cp - sa->sa_data + 1;
207 cp = sa->sa_data;
208 hexprint:
209 while (--n >= 0)
210 m += printf("%02x%c", *cp++ & 0xff,
211 n > 0 ? '.' : ' ');
212 m = 28 - m;
213 while (m-- > 0)
214 putchar(' ');
215 break;
217 ifaddraddr = (u_long)ifaddr.ifa.ifa_next;
219 printf("%8d %5d ",
220 ifnet.if_ipackets, ifnet.if_ierrors);
221 if (bflag)
222 printf("%10d ", ifnet.if_ibytes);
223 printf("%8d %5d ",
224 ifnet.if_opackets, ifnet.if_oerrors);
225 if (bflag)
226 printf("%10d ", ifnet.if_obytes);
227 printf("%5d", ifnet.if_collisions);
228 if (tflag)
229 printf(" %3d", ifnet.if_timer);
230 if (dflag)
231 printf(" %3d", ifnet.if_snd.ifq_drops);
232 putchar('\n');
236 #define MAXIF 10
237 struct iftot {
238 char ift_name[16]; /* interface name */
239 u_int ift_ip; /* input packets */
240 u_int ift_ie; /* input errors */
241 u_int ift_op; /* output packets */
242 u_int ift_oe; /* output errors */
243 u_int ift_co; /* collisions */
244 u_int ift_dr; /* drops */
245 u_int ift_ib; /* input bytes */
246 u_int ift_ob; /* output bytes */
247 } iftot[MAXIF];
249 u_char signalled; /* set if alarm goes off "early" */
251 struct MsgPort *timerport;
252 struct timerequest *timerio;
254 void __chkabort()
258 void CleanupExit(rc)
260 if (timerio)
261 DeleteIORequest(timerio);
262 if (timerport)
263 DeleteMsgPort(timerport);
264 exit(rc);
268 * Print a running summary of interface statistics.
269 * Repeat display every interval seconds, showing statistics
270 * collected over that interval. Assumes that interval is non-zero.
271 * First line printed at top of screen is always cumulative.
273 static void
274 sidewaysintpr(interval, off)
275 unsigned interval;
276 u_long off;
278 struct ifnet ifnet;
279 u_long firstifnet;
280 register struct iftot *ip, *total;
281 register int line;
282 struct iftot *lastif, *sum, *interesting;
283 ULONG sigmask;
285 if (kread(off, (char *)&firstifnet, sizeof (u_long)))
286 return;
287 lastif = iftot;
288 sum = iftot + MAXIF - 1;
289 total = sum - 1;
290 interesting = iftot;
291 for (off = firstifnet, ip = iftot; off;) {
292 char *cp;
294 if (kread(off, (char *)&ifnet, sizeof ifnet))
295 break;
296 ip->ift_name[0] = '(';
297 if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15))
298 break;
299 if (interface && strcmp(ip->ift_name + 1, interface) == 0 &&
300 unit == ifnet.if_unit)
301 interesting = ip;
302 ip->ift_name[15] = '\0';
303 cp = index(ip->ift_name, '\0');
304 sprintf(cp, "%d)", ifnet.if_unit);
305 ip++;
306 if (ip >= iftot + MAXIF - 2)
307 break;
308 off = (u_long) ifnet.if_next;
310 lastif = ip;
312 timerport = CreateMsgPort();
313 if (!timerport) {
314 fprintf(stderr, "Unable to create timer message port\n");
315 exit(0);
317 sigmask = (1 << timerport->mp_SigBit) | SIGBREAKF_CTRL_C;
318 timerio = CreateIORequest(timerport, sizeof(struct timerequest));
319 if (!timerio) {
320 fprintf(stderr, "Unable to create timer I/O request\n");
321 CleanupExit(20);
323 if (OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)timerio, 0)) {
324 fprintf(stderr, "Unable to open timer.device\n");
325 CleanupExit(20);
327 timerio->tr_node.io_Command = TR_ADDREQUEST;
328 timerio->tr_time.tv_secs = interval;
329 timerio->tr_time.tv_micro = 0;
330 SendIO ((struct IORequest *)timerio);
331 banner:
332 printf(" input %s%-6.6s %soutput ", bflag ? " " : "",
333 interesting->ift_name, bflag ? " " : "");
334 if (lastif - iftot > 0) {
335 if (dflag)
336 printf(" ");
337 printf(" input %s(Total) %soutput", bflag ? " " : "",
338 bflag ? " " : "");
340 for (ip = iftot; ip < iftot + MAXIF; ip++) {
341 ip->ift_ip = 0;
342 ip->ift_ie = 0;
343 ip->ift_op = 0;
344 ip->ift_oe = 0;
345 ip->ift_co = 0;
346 ip->ift_dr = 0;
347 ip->ift_ib = 0;
348 ip->ift_ob = 0;
350 putchar('\n');
351 printf("%8.8s %5.5s ", "packets", "errs");
352 if (bflag)
353 printf("%10.10s ","bytes");
354 printf("%8.8s %5.5s ", "packets", "errs");
355 if (bflag)
356 printf("%10.10s ","bytes");
357 printf("%5.5s ", "colls");
358 if (dflag)
359 printf("%5.5s ", "drops");
360 if (lastif - iftot > 0) {
361 printf(" %8.8s %5.5s", "packets", "errs");
362 if (bflag)
363 printf(" %10.10s", "bytes");
364 printf(" %8.8s %5.5s", "packets", "errs");
365 if (bflag)
366 printf(" %10.10s", "bytes");
367 printf(" %5.5s", "colls");
368 if (dflag)
369 printf(" %5.5s", "drops");
371 putchar('\n');
372 fflush(stdout);
373 line = 0;
374 loop:
375 sum->ift_ip = 0;
376 sum->ift_ie = 0;
377 sum->ift_op = 0;
378 sum->ift_oe = 0;
379 sum->ift_co = 0;
380 sum->ift_dr = 0;
381 sum->ift_ib = 0;
382 sum->ift_ob = 0;
383 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) {
384 if (kread(off, (char *)&ifnet, sizeof ifnet)) {
385 off = 0;
386 continue;
388 if (ip == interesting) {
389 printf("%8d %5d ",
390 ifnet.if_ipackets - ip->ift_ip,
391 ifnet.if_ierrors - ip->ift_ie);
392 if (bflag)
393 printf("%10d ", ifnet.if_ibytes - ip->ift_ib);
394 printf("%8d %5d ",
395 ifnet.if_opackets - ip->ift_op,
396 ifnet.if_oerrors - ip->ift_oe);
397 if (bflag)
398 printf("%10d ", ifnet.if_obytes - ip->ift_ob);
399 printf("%5d", ifnet.if_collisions - ip->ift_co);
400 if (dflag)
401 printf(" %5d",
402 ifnet.if_snd.ifq_drops - ip->ift_dr);
404 ip->ift_ip = ifnet.if_ipackets;
405 ip->ift_ie = ifnet.if_ierrors;
406 ip->ift_op = ifnet.if_opackets;
407 ip->ift_oe = ifnet.if_oerrors;
408 ip->ift_co = ifnet.if_collisions;
409 ip->ift_dr = ifnet.if_snd.ifq_drops;
410 ip->ift_ib = ifnet.if_ibytes;
411 ip->ift_ob = ifnet.if_obytes;
412 sum->ift_ip += ip->ift_ip;
413 sum->ift_ie += ip->ift_ie;
414 sum->ift_op += ip->ift_op;
415 sum->ift_oe += ip->ift_oe;
416 sum->ift_co += ip->ift_co;
417 sum->ift_dr += ip->ift_dr;
418 sum->ift_ib += ip->ift_ib;
419 sum->ift_ob += ip->ift_ob;
420 off = (u_long) ifnet.if_next;
422 if (lastif - iftot > 0) {
423 printf(" %8d %5d",
424 sum->ift_ip - total->ift_ip,
425 sum->ift_ie - total->ift_ie);
426 if (bflag)
427 printf(" %10d", sum->ift_ib - total->ift_ib);
428 printf(" %8d %5d",
429 sum->ift_op - total->ift_op,
430 sum->ift_oe - total->ift_oe);
431 if (bflag)
432 printf(" %10d", sum->ift_ob - total->ift_ob);
433 printf(" %5d", sum->ift_co - total->ift_co);
434 if (dflag)
435 printf(" %5d", sum->ift_dr - total->ift_dr);
437 *total = *sum;
438 putchar('\n');
439 fflush(stdout);
440 line++;
441 if (Wait (sigmask) & SIGBREAKF_CTRL_C) {
442 AbortIO ((struct IORequest *)timerio);
443 WaitIO ((struct IORequest *)timerio);
444 CloseDevice ((struct IORequest *)timerio);
445 CleanupExit(0);
447 WaitIO ((struct IORequest *)timerio);
448 timerio->tr_node.io_Command = TR_ADDREQUEST;
449 timerio->tr_time.tv_secs = interval;
450 timerio->tr_time.tv_micro = 0;
451 SendIO ((struct IORequest *)timerio);
452 if (line == 21)
453 goto banner;
454 goto loop;
455 /*NOTREACHED*/
459 * Called if an interval expires before sidewaysintpr has completed a loop.
460 * Sets a flag to not wait for the alarm.
462 static void
463 catchalarm(signo)
464 int signo;
466 signalled = YES;