and added files
[bcm963xx.git] / userapps / opensource / net-snmp / apps / snmpnetstat / if.c
1 /*****************************************************************
2         Copyright 1989, 1991, 1992 by Carnegie Mellon University
3
4                       All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and its 
7 documentation for any purpose and without fee is hereby granted, 
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in 
10 supporting documentation, and that the name of CMU not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.  
13
14 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21 ******************************************************************/
22 /*
23  * Copyright (c) 1983,1988 Regents of the University of California.
24  * All rights reserved.
25  *
26  * Redistribution and use in source and binary forms are permitted
27  * provided that this notice is preserved and that due credit is given
28  * to the University of California at Berkeley. The name of the University
29  * may not be used to endorse or promote products derived from this
30  * software without specific prior written permission. This software
31  * is provided ``as is'' without express or implied warranty.
32  */
33
34 #include <net-snmp/net-snmp-config.h>
35
36 #if HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #if HAVE_STRING_H
43 #include <string.h>
44 #else
45 #include <strings.h>
46 #endif
47
48 #include <sys/types.h>
49 #if TIME_WITH_SYS_TIME
50 # ifdef WIN32
51 #  include <sys/timeb.h>
52 # else
53 #  include <sys/time.h>
54 # endif
55 # include <time.h>
56 #else
57 # if HAVE_SYS_TIME_H
58 #  include <sys/time.h>
59 # else
60 #  include <time.h>
61 # endif
62 #endif
63 #if HAVE_SYS_SELECT_H
64 #include <sys/select.h>
65 #endif
66 #if HAVE_NETINET_IN_H
67 #include <netinet/in.h>
68 #endif
69
70 #include <stdio.h>
71 #include <signal.h>
72
73 #if HAVE_WINSOCK_H
74 #include <winsock.h>
75 #endif
76 #if HAVE_SYS_SOCKET_H
77 #include <sys/socket.h>
78 #endif
79 #if HAVE_NETDB_H
80 #include <netdb.h>
81 #endif
82
83 #include "main.h"
84 #include <net-snmp/net-snmp-includes.h>
85 #include "netstat.h"
86
87 #define YES     1
88 #define NO      0
89
90 static void     sidewaysintpr(unsigned int);
91 static void     timerSet(int interval_seconds);
92 static void     timerPause(void);
93
94 static oid      oid_ifname[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 2, 1 };
95 static oid      oid_ifinucastpkts[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 11, 1 };
96 static oid      oid_cfg_nnets[] = { 1, 3, 6, 1, 2, 1, 2, 1, 0 };
97 static oid      oid_ipadentaddr[] =
98     { 1, 3, 6, 1, 2, 1, 4, 20, 1, 1, 0, 0, 0, 0 };
99
100 #define IFINDEX         1
101 #define IFNAME          2
102 #define IFMTU           4
103 #define IFOPERSTATUS    8
104 #define INOCTETS        10
105 #define INUCASTPKTS     11
106 #define INNUCASTPKTS    12
107 #define INERRORS        14
108 #define OUTOCTETS       16
109 #define OUTUCASTPKTS    17
110 #define OUTNUCASTPKTS   18
111 #define OUTERRORS       20
112 #define OUTQLEN         21
113
114 #define IPADDR          1
115 #define IPIFINDEX       2
116 #define IPNETMASK       3
117
118
119 /*
120  * Print a description of the network interfaces.
121  */
122 void
123 intpr(int interval)
124 {
125     oid             varname[MAX_OID_LEN], *instance, *ifentry;
126     size_t          varname_len;
127     int             ifnum, cfg_nnets;
128     oid             curifip[4];
129     netsnmp_variable_list *var;
130     netsnmp_pdu    *request, *response;
131     int             status;
132     int             ifindex, oldindex = 0;
133     struct _if_info {
134         char            name[128];
135         char            ip[128], route[128];
136         int             mtu;
137         int             ifindex;
138         char            s_ipkts[20], s_ierrs[20], s_opkts[20], s_oerrs[20],
139             s_outq[20];
140         unsigned long   ipkts, opkts;
141         int             operstatus;
142         u_long          netmask;
143         struct in_addr  ifip, ifroute;
144     }              *if_table, *cur_if;
145     int             max_name = 4, max_ip = 7, max_route = 7, max_ipkts = 5,
146         max_ierrs = 5, max_opkts = 5, max_oerrs = 5, max_outq = 5;
147     int             i;
148
149     if (interval) {
150         sidewaysintpr((unsigned) interval);
151         return;
152     }
153     var =
154         getvarbyname(Session, oid_cfg_nnets,
155                      sizeof(oid_cfg_nnets) / sizeof(oid));
156     if (var && var->val.integer) {
157         cfg_nnets = *var->val.integer;
158         snmp_free_var(var);
159     } else {
160         fprintf(stderr,
161                 "No response when requesting number of interfaces.\n");
162         return;
163     }
164     DEBUGMSGTL(("netstat:if", "cfg_nnets = %d\n", cfg_nnets));
165
166     memset(curifip, 0, sizeof(curifip));
167     if_table = (struct _if_info *) calloc(cfg_nnets, sizeof(*if_table));
168     cur_if = if_table;
169
170     for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) {
171         register char  *cp;
172
173         request = snmp_pdu_create(SNMP_MSG_GETNEXT);
174         memmove(varname, oid_ipadentaddr, sizeof(oid_ipadentaddr));
175         varname_len = sizeof(oid_ipadentaddr) / sizeof(oid);
176         instance = varname + 9;
177         memmove(varname + 10, curifip, sizeof(curifip));
178         *instance = IPIFINDEX;
179         snmp_add_null_var(request, varname, varname_len);
180         *instance = IPADDR;
181         snmp_add_null_var(request, varname, varname_len);
182         *instance = IPNETMASK;
183         snmp_add_null_var(request, varname, varname_len);
184
185         status = snmp_synch_response(Session, request, &response);
186         if (status != STAT_SUCCESS
187             || response->errstat != SNMP_ERR_NOERROR) {
188             fprintf(stderr,
189                     "SNMP request failed after %d out of %d interfaces (IP)\n",
190                     ifnum, cfg_nnets);
191             if (snmp_get_do_debugging()) {
192                 fprintf(stderr,
193                         "status = %d, errstat = %ld, errindex = %ld\n",
194                         status, response->errstat, response->errindex);
195             }
196             cfg_nnets = ifnum;
197             break;
198         }
199         for (var = response->variables; var; var = var->next_variable) {
200             if (snmp_get_do_debugging()) {
201                 print_variable(var->name, var->name_length, var);
202             }
203             switch (var->name[9]) {
204             case IPIFINDEX:
205                 ifindex = *var->val.integer;
206                 for (cur_if = if_table;
207                      cur_if < (if_table + cfg_nnets) &&
208                      cur_if->ifindex != ifindex &&
209                      cur_if->ifindex != 0; cur_if++);
210                 if (cur_if >= (if_table + cfg_nnets)) {
211                     fprintf(stderr,
212                             "Inconsistent reponse from server. Aborting.\n");
213                     exit(0);
214                 }
215                 cur_if->ifindex = ifindex;
216                 break;
217             case IPADDR:
218                 memmove(curifip, var->name + 10, sizeof(curifip));
219                 memmove(&cur_if->ifip, var->val.string, sizeof(u_long));
220                 break;
221             case IPNETMASK:
222                 memmove(&cur_if->netmask, var->val.string, sizeof(u_long));
223             }
224         }
225         cur_if->ifroute.s_addr = cur_if->ifip.s_addr & cur_if->netmask;
226         if (cur_if->ifroute.s_addr)
227             strcpy(cur_if->route,
228                    netname(cur_if->ifroute, cur_if->netmask));
229         else
230             strcpy(cur_if->route, "none");
231         if ((i = strlen(cur_if->route)) > max_route)
232             max_route = i;
233         if (cur_if->ifip.s_addr)
234             strcpy(cur_if->ip, routename(cur_if->ifip));
235         else
236             strcpy(cur_if->ip, "none");
237         if ((i = strlen(cur_if->ip)) > max_ip)
238             max_ip = i;
239
240         snmp_free_pdu(response);
241
242         memmove(varname, oid_ifname, sizeof(oid_ifname));
243         varname_len = sizeof(oid_ifname) / sizeof(oid);
244         ifentry = varname + 9;
245         instance = varname + 10;
246         request = snmp_pdu_create(SNMP_MSG_GETNEXT);
247
248         *instance = oldindex;
249         *ifentry = IFINDEX;
250         snmp_add_null_var(request, varname, varname_len);
251         *ifentry = IFNAME;
252         snmp_add_null_var(request, varname, varname_len);
253         *ifentry = IFMTU;
254         snmp_add_null_var(request, varname, varname_len);
255         *ifentry = IFOPERSTATUS;
256         snmp_add_null_var(request, varname, varname_len);
257         *ifentry = INUCASTPKTS;
258         snmp_add_null_var(request, varname, varname_len);
259         *ifentry = INNUCASTPKTS;
260         snmp_add_null_var(request, varname, varname_len);
261         *ifentry = INERRORS;
262         snmp_add_null_var(request, varname, varname_len);
263         *ifentry = OUTUCASTPKTS;
264         snmp_add_null_var(request, varname, varname_len);
265         *ifentry = OUTNUCASTPKTS;
266         snmp_add_null_var(request, varname, varname_len);
267         *ifentry = OUTERRORS;
268         snmp_add_null_var(request, varname, varname_len);
269         *ifentry = OUTQLEN;
270         snmp_add_null_var(request, varname, varname_len);
271
272         while ((status =
273                 snmp_synch_response(Session, request,
274                                     &response)) == STAT_SUCCESS) {
275             if (response->errstat != SNMP_ERR_NOSUCHNAME)
276                 break;
277             if ((request =
278                  snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL)
279                 break;
280             snmp_free_pdu(response);
281         }
282         if (status != STAT_SUCCESS
283             || response->errstat != SNMP_ERR_NOERROR) {
284             fprintf(stderr,
285                     "SNMP request failed after %d out of %d interfaces (IF)\n",
286                     ifnum, cfg_nnets);
287             cfg_nnets = ifnum;
288             break;
289         }
290         cur_if = if_table + ifnum - 1;
291         for (var = response->variables; var; var = var->next_variable) {
292             if (snmp_get_do_debugging()) {
293                 print_variable(var->name, var->name_length, var);
294             }
295             if (!var->val.integer)
296                 continue;
297             if (memcmp(var->name, oid_ifname, 8 * sizeof(oid)))
298                 continue;
299             switch (var->name[9]) {
300             case IFINDEX:
301                 ifindex = *var->val.integer;
302                 for (cur_if = if_table;
303                      cur_if->ifindex != ifindex && cur_if->ifindex != 0;
304                      cur_if++);
305                 if (cur_if >= (if_table + cfg_nnets)) {
306                     fprintf(stderr,
307                             "Inconsistent reponse from server. Aborting\n");
308                     exit(0);
309                 }
310                 cur_if->ifindex = ifindex;
311                 break;
312             case OUTQLEN:
313                 sprintf(cur_if->s_outq, "%lu", *var->val.integer);
314                 i = strlen(cur_if->s_outq);
315                 if (i > max_outq)
316                     max_outq = i;
317                 break;
318             case OUTERRORS:
319                 sprintf(cur_if->s_oerrs, "%lu", *var->val.integer);
320                 i = strlen(cur_if->s_oerrs);
321                 if (i > max_oerrs)
322                     max_oerrs = i;
323                 break;
324             case INERRORS:
325                 sprintf(cur_if->s_ierrs, "%lu", *var->val.integer);
326                 i = strlen(cur_if->s_ierrs);
327                 if (i > max_ierrs)
328                     max_ierrs = i;
329                 break;
330             case IFMTU:
331                 cur_if->mtu = *var->val.integer;
332                 break;
333             case INUCASTPKTS:
334                 cur_if->ipkts += *var->val.integer;
335                 sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts);
336                 i = strlen(cur_if->s_ipkts);
337                 if (i > max_ipkts)
338                     max_ipkts = i;
339                 break;
340             case INNUCASTPKTS:
341                 cur_if->ipkts += *var->val.integer;
342                 sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts);
343                 i = strlen(cur_if->s_ipkts);
344                 if (i > max_ipkts)
345                     max_ipkts = i;
346                 break;
347             case OUTUCASTPKTS:
348                 cur_if->opkts += *var->val.integer;
349                 sprintf(cur_if->s_opkts, "%lu", cur_if->opkts);
350                 i = strlen(cur_if->s_opkts);
351                 if (i > max_opkts)
352                     max_opkts = i;
353                 break;
354             case OUTNUCASTPKTS:
355                 cur_if->opkts += *var->val.integer;
356                 sprintf(cur_if->s_opkts, "%lu", cur_if->opkts);
357                 i = strlen(cur_if->s_opkts);
358                 if (i > max_opkts)
359                     max_opkts = i;
360                 break;
361             case IFNAME:
362                 oldindex = var->name[10];
363                 if (var->val_len >= sizeof(cur_if->name))
364                     var->val_len = sizeof(cur_if->name) - 1;
365                 memmove(cur_if->name, var->val.string, var->val_len);
366                 cur_if->name[var->val_len] = 0;
367                 if ((i = strlen(cur_if->name) + 1) > max_name)
368                     max_name = i;
369                 break;
370             case IFOPERSTATUS:
371                 cur_if->operstatus = *var->val.integer;
372                 break;
373             }
374         }
375
376         snmp_free_pdu(response);
377
378         if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) {
379             cur_if->name[0] = 0;
380             continue;
381         }
382         if (cur_if->operstatus != MIB_IFSTATUS_UP) {
383             cp = strchr(cur_if->name, '\0');
384             *cp++ = '*';
385             *cp = '\0';
386         }
387     }
388
389     printf("%*.*s %5.5s %*.*s %*.*s %*s %*s %*s %*s %*s",
390            -max_name, max_name, "Name", "Mtu",
391            -max_route, max_route, "Network",
392            -max_ip, max_ip, "Address",
393            max_ipkts, "Ipkts",
394            max_ierrs, "Ierrs",
395            max_opkts, "Opkts", max_oerrs, "Oerrs", max_outq, "Queue");
396     putchar('\n');
397     for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets;
398          ifnum++, cur_if++) {
399         if (cur_if->name[0] == 0)
400             continue;
401         printf("%*.*s %5d ", -max_name, max_name, cur_if->name,
402                cur_if->mtu);
403         printf("%*.*s ", -max_route, max_route, cur_if->route);
404         printf("%*.*s ", -max_ip, max_ip, cur_if->ip);
405         printf("%*s %*s %*s %*s %*s",
406                max_ipkts, cur_if->s_ipkts, max_ierrs, cur_if->s_ierrs,
407                max_opkts, cur_if->s_opkts, max_oerrs, cur_if->s_oerrs,
408                max_outq, cur_if->s_outq);
409         putchar('\n');
410     }
411     free(if_table);
412 }
413
414 /*
415  * Print a description of the network interfaces.
416  */
417 void
418 intpro(int interval)
419 {
420     oid             varname[MAX_OID_LEN], *instance, *ifentry;
421     size_t          varname_len;
422     int             ifnum, cfg_nnets;
423     oid             curifip[4];
424     netsnmp_variable_list *var;
425     netsnmp_pdu    *request, *response;
426     int             status;
427     int             ifindex, oldindex = 0;
428     struct _if_info {
429         int             ifindex;
430         char            name[128];
431         char            ip[128], route[128];
432         char            ioctets[20], ierrs[20], ooctets[20], oerrs[20],
433             outqueue[20];
434         int             operstatus;
435         u_long          netmask;
436         struct in_addr  ifip, ifroute;
437     }              *if_table, *cur_if;
438     int             max_name = 4, max_route = 7, max_ip = 7, max_ioctets =
439         7, max_ooctets = 7;
440     int             i;
441
442     if (interval) {
443         sidewaysintpr((unsigned) interval);
444         return;
445     }
446     var =
447         getvarbyname(Session, oid_cfg_nnets,
448                      sizeof(oid_cfg_nnets) / sizeof(oid));
449     if (var && var->val.integer) {
450         cfg_nnets = *var->val.integer;
451         snmp_free_var(var);
452     } else {
453         fprintf(stderr,
454                 "No response when requesting number of interfaces.\n");
455         return;
456     }
457     DEBUGMSGTL(("netstat:if", "cfg_nnets = %d\n", cfg_nnets));
458
459     memset(curifip, 0, sizeof(curifip));
460     if_table = (struct _if_info *) calloc(cfg_nnets, sizeof(*if_table));
461     cur_if = if_table;
462
463     for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) {
464         register char  *cp;
465
466         request = snmp_pdu_create(SNMP_MSG_GETNEXT);
467         memmove(varname, oid_ipadentaddr, sizeof(oid_ipadentaddr));
468         varname_len = sizeof(oid_ipadentaddr) / sizeof(oid);
469         instance = varname + 9;
470         memmove(varname + 10, curifip, sizeof(curifip));
471         *instance = IPIFINDEX;
472         snmp_add_null_var(request, varname, varname_len);
473         *instance = IPADDR;
474         snmp_add_null_var(request, varname, varname_len);
475         *instance = IPNETMASK;
476         snmp_add_null_var(request, varname, varname_len);
477
478         status = snmp_synch_response(Session, request, &response);
479         if (status != STAT_SUCCESS
480             || response->errstat != SNMP_ERR_NOERROR) {
481             fprintf(stderr,
482                     "SNMP request failed for interface %d, variable %ld out of %d interfaces (IP)\n",
483                     ifnum, response->errindex, cfg_nnets);
484             cfg_nnets = ifnum;
485             break;
486         }
487         for (var = response->variables; var; var = var->next_variable) {
488             if (snmp_get_do_debugging()) {
489                 print_variable(var->name, var->name_length, var);
490             }
491             switch (var->name[9]) {
492             case IPIFINDEX:
493                 ifindex = *var->val.integer;
494                 for (cur_if = if_table;
495                      cur_if->ifindex != ifindex && cur_if->ifindex != 0;
496                      cur_if++);
497                 cur_if->ifindex = ifindex;
498                 break;
499             case IPADDR:
500                 memmove(curifip, var->name + 10, sizeof(curifip));
501                 memmove(&cur_if->ifip, var->val.string, sizeof(u_long));
502                 break;
503             case IPNETMASK:
504                 memmove(&cur_if->netmask, var->val.string, sizeof(u_long));
505             }
506         }
507         cur_if->ifroute.s_addr = cur_if->ifip.s_addr & cur_if->netmask;
508         if (cur_if->ifroute.s_addr)
509             strcpy(cur_if->route,
510                    netname(cur_if->ifroute, cur_if->netmask));
511         else
512             strcpy(cur_if->route, "none");
513         if ((i = strlen(cur_if->route)) > max_route)
514             max_route = i;
515         if (cur_if->ifip.s_addr)
516             strcpy(cur_if->ip, routename(cur_if->ifip));
517         else
518             strcpy(cur_if->ip, "none");
519         if ((i = strlen(cur_if->ip)) > max_ip)
520             max_ip = i;
521
522         snmp_free_pdu(response);
523
524         memmove(varname, oid_ifname, sizeof(oid_ifname));
525         varname_len = sizeof(oid_ifname) / sizeof(oid);
526         ifentry = varname + 9;
527         instance = varname + 10;
528         request = snmp_pdu_create(SNMP_MSG_GETNEXT);
529
530         *instance = oldindex;
531         *ifentry = IFINDEX;
532         snmp_add_null_var(request, varname, varname_len);
533         *ifentry = IFNAME;
534         snmp_add_null_var(request, varname, varname_len);
535         *ifentry = IFOPERSTATUS;
536         snmp_add_null_var(request, varname, varname_len);
537         *ifentry = INOCTETS;
538         snmp_add_null_var(request, varname, varname_len);
539         *ifentry = OUTOCTETS;
540         snmp_add_null_var(request, varname, varname_len);
541
542         while ((status =
543                 snmp_synch_response(Session, request,
544                                     &response)) == STAT_SUCCESS) {
545             if (response->errstat != SNMP_ERR_NOSUCHNAME)
546                 break;
547             if ((request =
548                  snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL)
549                 break;
550             snmp_free_pdu(response);
551         }
552         if (status != STAT_SUCCESS
553             || response->errstat != SNMP_ERR_NOERROR) {
554             fprintf(stderr,
555                     "SNMP request failed for interface %d, variable %ld out of %d interfaces (IF)\n",
556                     ifnum, response->errindex, cfg_nnets);
557             cfg_nnets = ifnum;
558             break;
559         }
560         for (var = response->variables; var; var = var->next_variable) {
561             if (snmp_get_do_debugging()) {
562                 print_variable(var->name, var->name_length, var);
563             }
564             if (!var->val.integer)
565                 continue;
566             switch (var->name[9]) {
567             case IFINDEX:
568                 ifindex = *var->val.integer;
569                 for (cur_if = if_table;
570                      cur_if->ifindex != ifindex && cur_if->ifindex != 0;
571                      cur_if++);
572                 cur_if->ifindex = ifindex;
573                 break;
574             case INOCTETS:
575                 sprintf(cur_if->ioctets, "%lu", *var->val.integer);
576                 i = strlen(cur_if->ioctets);
577                 if (i > max_ioctets)
578                     max_ioctets = i;
579                 break;
580             case OUTOCTETS:
581                 sprintf(cur_if->ooctets, "%lu", *var->val.integer);
582                 i = strlen(cur_if->ooctets);
583                 if (i > max_ooctets)
584                     max_ooctets = i;
585                 break;
586             case IFNAME:
587                 oldindex = var->name[10];
588                 if (var->val_len >= sizeof(cur_if->name))
589                     var->val_len = sizeof(cur_if->name) - 1;
590                 memmove(cur_if->name, var->val.string, var->val_len);
591                 cur_if->name[var->val_len] = 0;
592                 if ((i = strlen(cur_if->name) + 1) > max_name)
593                     max_name = i;
594                 break;
595             case IFOPERSTATUS:
596                 cur_if->operstatus = *var->val.integer;
597                 break;
598             }
599         }
600
601         snmp_free_pdu(response);
602
603         if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) {
604             cur_if->name[0] = 0;
605             continue;
606         }
607         if (cur_if->operstatus != MIB_IFSTATUS_UP) {
608             cp = strchr(cur_if->name, '\0');
609             *cp++ = '*';
610             *cp = '\0';
611         }
612     }
613
614     printf("%*.*s %*.*s %*.*s %*.*s %*.*s ",
615            -max_name, max_name, "Name",
616            -max_route, max_route, "Network",
617            -max_ip, max_ip, "Address",
618            max_ioctets, max_ioctets, "Ioctets",
619            max_ooctets, max_ooctets, "Ooctets");
620     putchar('\n');
621     for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets;
622          ifnum++, cur_if++) {
623         if (cur_if->name[0] == 0)
624             continue;
625         printf("%*.*s ", -max_name, max_name, cur_if->name);
626         printf("%*.*s ", -max_route, max_route, cur_if->route);
627         printf("%*.*s ", -max_ip, max_ip, cur_if->ip);
628         printf("%*s %*s", max_ioctets, cur_if->ioctets,
629                max_ioctets, cur_if->ooctets);
630         putchar('\n');
631     }
632     free(if_table);
633 }
634
635 #define MAXIF   128
636 struct iftot {
637     char            ift_name[128];      /* interface name */
638     unsigned int    ift_ip;     /* input packets */
639     unsigned int    ift_ie;     /* input errors */
640     unsigned int    ift_op;     /* output packets */
641     unsigned int    ift_oe;     /* output errors */
642     unsigned int    ift_co;     /* collisions */
643 } iftot[MAXIF];
644
645 u_char          signalled;      /* set if alarm goes off "early" */
646
647 /*
648  * timerSet sets or resets the timer to fire in "interval" seconds.
649  * timerPause waits only if the timer has not fired.
650  * timing precision is not considered important.
651  */
652
653 #if (defined(WIN32) || defined(cygwin))
654 static int      sav_int;
655 static time_t   timezup;
656 static void
657 timerSet(int interval_seconds)
658 {
659     sav_int = interval_seconds;
660     timezup = time(0) + interval_seconds;
661 }
662
663 /*
664  * you can do better than this ! 
665  */
666 static void
667 timerPause(void)
668 {
669     time_t          now;
670     while (time(&now) < timezup)
671 #ifdef WIN32
672         Sleep(400);
673 #else
674     {
675         struct timeval  tx;
676         tx.tv_sec = 0;
677         tx.tv_usec = 400 * 1000;        /* 400 milliseconds */
678         select(0, 0, 0, 0, &tx);
679     }
680 #endif
681 }
682
683 #else
684
685 /*
686  * Called if an interval expires before sidewaysintpr has completed a loop.
687  * Sets a flag to not wait for the alarm.
688  */
689 RETSIGTYPE
690 catchalarm(int sig)
691 {
692     signalled = YES;
693 }
694
695 static void
696 timerSet(int interval_seconds)
697 {
698 #ifdef HAVE_SIGSET
699     (void) sigset(SIGALRM, catchalarm);
700 #else
701     (void) signal(SIGALRM, catchalarm);
702 #endif
703     signalled = NO;
704     (void) alarm(interval_seconds);
705 }
706
707 static void
708 timerPause(void)
709 {
710 #ifdef HAVE_SIGHOLD
711     sighold(SIGALRM);
712     if (!signalled) {
713         sigpause(SIGALRM);
714     }
715 #else
716     int             oldmask;
717     oldmask = sigblock(sigmask(SIGALRM));
718     if (!signalled) {
719         sigpause(0);
720     }
721     sigsetmask(oldmask);
722 #endif
723 }
724
725 #endif                          /* !WIN32 && !cygwin */
726
727 /*
728  * Print a running summary of interface statistics.
729  * Repeat display every interval seconds, showing statistics
730  * collected over that interval.  Assumes that interval is non-zero.
731  * First line printed at top of screen is always cumulative.
732  */
733 static void
734 sidewaysintpr(unsigned int interval)
735 {
736     register struct iftot *ip, *total;
737     register int    line;
738     struct iftot   *lastif, *sum, *interesting, ifnow, *now = &ifnow;
739     netsnmp_variable_list *var;
740     oid             varname[MAX_OID_LEN], *instance, *ifentry;
741     size_t          varname_len;
742     int             ifnum, cfg_nnets;
743
744     lastif = iftot;
745     sum = iftot + MAXIF - 1;
746     total = sum - 1;
747     interesting = iftot;
748     var =
749         getvarbyname(Session, oid_cfg_nnets,
750                      sizeof(oid_cfg_nnets) / sizeof(oid));
751     if (var) {
752         cfg_nnets = *var->val.integer;
753         snmp_free_var(var);
754     } else
755         return;
756     memmove(varname, oid_ifname, sizeof(oid_ifname));
757     varname_len = sizeof(oid_ifname) / sizeof(oid);
758     for (ifnum = 1, ip = iftot; ifnum <= cfg_nnets; ifnum++) {
759         char           *cp;
760
761         ip->ift_name[0] = '(';
762         varname[10] = ifnum;
763         var = getvarbyname(Session, varname, varname_len);
764         if (var) {
765             if (var->val_len >= (sizeof(ip->ift_name) - 3))
766                 var->val_len = (sizeof(ip->ift_name) - 4);
767             memmove(ip->ift_name + 1, var->val.string, var->val_len);
768             snmp_free_var(var);
769         }
770         cp = (char *) strchr(ip->ift_name, ' ');
771         if (cp != NULL)
772             *cp = '\0';
773         if (intrface && strcmp(ip->ift_name + 1, intrface) == 0)
774             interesting = ip;
775         ip->ift_name[15] = '\0';
776         cp = (char *) strchr(ip->ift_name, '\0');
777         sprintf(cp, ")");
778         ip++;
779         if (ip >= iftot + MAXIF - 2)
780             break;
781     }
782     lastif = ip;
783
784     timerSet(interval);
785
786   banner:
787     printf("     input   %-6.6s     output       ", interesting->ift_name);
788     if (lastif - iftot > 0)
789         printf("                 input  (Total)     output");
790     for (ip = iftot; ip < iftot + MAXIF; ip++) {
791         ip->ift_ip = 0;
792         ip->ift_ie = 0;
793         ip->ift_op = 0;
794         ip->ift_oe = 0;
795         ip->ift_co = 0;
796     }
797     putchar('\n');
798     printf("%10.10s %8.8s %10.10s %8.8s %8.8s ",
799            "packets", "errs", "packets", "errs", "colls");
800     if (lastif - iftot > 0)
801         printf("%10.10s %8.8s %10.10s %8.8s %8.8s ",
802                "packets", "errs", "packets", "errs", "colls");
803     putchar('\n');
804     fflush(stdout);
805     line = 0;
806   loop:
807     sum->ift_ip = 0;
808     sum->ift_ie = 0;
809     sum->ift_op = 0;
810     sum->ift_oe = 0;
811     sum->ift_co = 0;
812     memmove(varname, oid_ifinucastpkts, sizeof(oid_ifinucastpkts));
813     varname_len = sizeof(oid_ifinucastpkts) / sizeof(oid);
814     ifentry = varname + 9;
815     instance = varname + 10;
816     for (ifnum = 1, ip = iftot; ifnum <= cfg_nnets && ip < lastif;
817          ip++, ifnum++) {
818         memset(now, 0, sizeof(*now));
819         *instance = ifnum;
820         *ifentry = INUCASTPKTS;
821         var = getvarbyname(Session, varname, varname_len);
822         if (var) {
823             now->ift_ip = *var->val.integer;
824             snmp_free_var(var);
825         }
826         *ifentry = INNUCASTPKTS;
827         var = getvarbyname(Session, varname, varname_len);
828         if (var) {
829             now->ift_ip += *var->val.integer;
830             snmp_free_var(var);
831         }
832         *ifentry = INERRORS;
833         var = getvarbyname(Session, varname, varname_len);
834         if (var) {
835             now->ift_ie = *var->val.integer;
836             snmp_free_var(var);
837         }
838         *ifentry = OUTUCASTPKTS;
839         var = getvarbyname(Session, varname, varname_len);
840         if (var) {
841             now->ift_op = *var->val.integer;
842             snmp_free_var(var);
843         }
844         *ifentry = OUTNUCASTPKTS;
845         var = getvarbyname(Session, varname, varname_len);
846         if (var) {
847             now->ift_op += *var->val.integer;
848             snmp_free_var(var);
849         }
850         *ifentry = OUTERRORS;
851         var = getvarbyname(Session, varname, varname_len);
852         if (var) {
853             now->ift_oe = *var->val.integer;
854             snmp_free_var(var);
855         }
856
857         if (ip == interesting)
858             printf("%10d %8d %10d %8d %8d ",
859                    now->ift_ip - ip->ift_ip,
860                    now->ift_ie - ip->ift_ie,
861                    now->ift_op - ip->ift_op,
862                    now->ift_oe - ip->ift_oe, now->ift_co - ip->ift_co);
863         ip->ift_ip = now->ift_ip;
864         ip->ift_ie = now->ift_ie;
865         ip->ift_op = now->ift_op;
866         ip->ift_oe = now->ift_oe;
867         ip->ift_co = now->ift_co;
868         sum->ift_ip += ip->ift_ip;
869         sum->ift_ie += ip->ift_ie;
870         sum->ift_op += ip->ift_op;
871         sum->ift_oe += ip->ift_oe;
872         sum->ift_co += ip->ift_co;
873     }
874     if (lastif - iftot > 0)
875         printf("%10d %8d %10d %8d %8d ",
876                sum->ift_ip - total->ift_ip,
877                sum->ift_ie - total->ift_ie,
878                sum->ift_op - total->ift_op,
879                sum->ift_oe - total->ift_oe, sum->ift_co - total->ift_co);
880     *total = *sum;
881     putchar('\n');
882     fflush(stdout);
883     line++;
884
885     timerPause();
886     timerSet(interval);
887
888     if (line == 21)
889         goto banner;
890     goto loop;
891  /*NOTREACHED*/}