1 /*****************************************************************
2 Copyright 1989, 1991, 1992 by Carnegie Mellon University
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.
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
21 ******************************************************************/
23 * Copyright (c) 1983,1988 Regents of the University of California.
24 * All rights reserved.
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.
34 #include <net-snmp/net-snmp-config.h>
48 #include <sys/types.h>
49 #if TIME_WITH_SYS_TIME
51 # include <sys/timeb.h>
53 # include <sys/time.h>
58 # include <sys/time.h>
64 #include <sys/select.h>
67 #include <netinet/in.h>
77 #include <sys/socket.h>
84 #include <net-snmp/net-snmp-includes.h>
90 static void sidewaysintpr(unsigned int);
91 static void timerSet(int interval_seconds);
92 static void timerPause(void);
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 };
103 #define IFOPERSTATUS 8
105 #define INUCASTPKTS 11
106 #define INNUCASTPKTS 12
109 #define OUTUCASTPKTS 17
110 #define OUTNUCASTPKTS 18
120 * Print a description of the network interfaces.
125 oid varname[MAX_OID_LEN], *instance, *ifentry;
127 int ifnum, cfg_nnets;
129 netsnmp_variable_list *var;
130 netsnmp_pdu *request, *response;
132 int ifindex, oldindex = 0;
135 char ip[128], route[128];
138 char s_ipkts[20], s_ierrs[20], s_opkts[20], s_oerrs[20],
140 unsigned long ipkts, opkts;
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;
150 sidewaysintpr((unsigned) interval);
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;
161 "No response when requesting number of interfaces.\n");
164 DEBUGMSGTL(("netstat:if", "cfg_nnets = %d\n", cfg_nnets));
166 memset(curifip, 0, sizeof(curifip));
167 if_table = (struct _if_info *) calloc(cfg_nnets, sizeof(*if_table));
170 for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) {
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);
181 snmp_add_null_var(request, varname, varname_len);
182 *instance = IPNETMASK;
183 snmp_add_null_var(request, varname, varname_len);
185 status = snmp_synch_response(Session, request, &response);
186 if (status != STAT_SUCCESS
187 || response->errstat != SNMP_ERR_NOERROR) {
189 "SNMP request failed after %d out of %d interfaces (IP)\n",
191 if (snmp_get_do_debugging()) {
193 "status = %d, errstat = %ld, errindex = %ld\n",
194 status, response->errstat, response->errindex);
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);
203 switch (var->name[9]) {
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)) {
212 "Inconsistent reponse from server. Aborting.\n");
215 cur_if->ifindex = ifindex;
218 memmove(curifip, var->name + 10, sizeof(curifip));
219 memmove(&cur_if->ifip, var->val.string, sizeof(u_long));
222 memmove(&cur_if->netmask, var->val.string, sizeof(u_long));
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));
230 strcpy(cur_if->route, "none");
231 if ((i = strlen(cur_if->route)) > max_route)
233 if (cur_if->ifip.s_addr)
234 strcpy(cur_if->ip, routename(cur_if->ifip));
236 strcpy(cur_if->ip, "none");
237 if ((i = strlen(cur_if->ip)) > max_ip)
240 snmp_free_pdu(response);
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);
248 *instance = oldindex;
250 snmp_add_null_var(request, varname, varname_len);
252 snmp_add_null_var(request, varname, varname_len);
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);
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);
270 snmp_add_null_var(request, varname, varname_len);
273 snmp_synch_response(Session, request,
274 &response)) == STAT_SUCCESS) {
275 if (response->errstat != SNMP_ERR_NOSUCHNAME)
278 snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL)
280 snmp_free_pdu(response);
282 if (status != STAT_SUCCESS
283 || response->errstat != SNMP_ERR_NOERROR) {
285 "SNMP request failed after %d out of %d interfaces (IF)\n",
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);
295 if (!var->val.integer)
297 if (memcmp(var->name, oid_ifname, 8 * sizeof(oid)))
299 switch (var->name[9]) {
301 ifindex = *var->val.integer;
302 for (cur_if = if_table;
303 cur_if->ifindex != ifindex && cur_if->ifindex != 0;
305 if (cur_if >= (if_table + cfg_nnets)) {
307 "Inconsistent reponse from server. Aborting\n");
310 cur_if->ifindex = ifindex;
313 sprintf(cur_if->s_outq, "%lu", *var->val.integer);
314 i = strlen(cur_if->s_outq);
319 sprintf(cur_if->s_oerrs, "%lu", *var->val.integer);
320 i = strlen(cur_if->s_oerrs);
325 sprintf(cur_if->s_ierrs, "%lu", *var->val.integer);
326 i = strlen(cur_if->s_ierrs);
331 cur_if->mtu = *var->val.integer;
334 cur_if->ipkts += *var->val.integer;
335 sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts);
336 i = strlen(cur_if->s_ipkts);
341 cur_if->ipkts += *var->val.integer;
342 sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts);
343 i = strlen(cur_if->s_ipkts);
348 cur_if->opkts += *var->val.integer;
349 sprintf(cur_if->s_opkts, "%lu", cur_if->opkts);
350 i = strlen(cur_if->s_opkts);
355 cur_if->opkts += *var->val.integer;
356 sprintf(cur_if->s_opkts, "%lu", cur_if->opkts);
357 i = strlen(cur_if->s_opkts);
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)
371 cur_if->operstatus = *var->val.integer;
376 snmp_free_pdu(response);
378 if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) {
382 if (cur_if->operstatus != MIB_IFSTATUS_UP) {
383 cp = strchr(cur_if->name, '\0');
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",
395 max_opkts, "Opkts", max_oerrs, "Oerrs", max_outq, "Queue");
397 for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets;
399 if (cur_if->name[0] == 0)
401 printf("%*.*s %5d ", -max_name, max_name, cur_if->name,
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);
415 * Print a description of the network interfaces.
420 oid varname[MAX_OID_LEN], *instance, *ifentry;
422 int ifnum, cfg_nnets;
424 netsnmp_variable_list *var;
425 netsnmp_pdu *request, *response;
427 int ifindex, oldindex = 0;
431 char ip[128], route[128];
432 char ioctets[20], ierrs[20], ooctets[20], oerrs[20],
436 struct in_addr ifip, ifroute;
437 } *if_table, *cur_if;
438 int max_name = 4, max_route = 7, max_ip = 7, max_ioctets =
443 sidewaysintpr((unsigned) interval);
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;
454 "No response when requesting number of interfaces.\n");
457 DEBUGMSGTL(("netstat:if", "cfg_nnets = %d\n", cfg_nnets));
459 memset(curifip, 0, sizeof(curifip));
460 if_table = (struct _if_info *) calloc(cfg_nnets, sizeof(*if_table));
463 for (ifnum = 1; ifnum <= cfg_nnets; ifnum++) {
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);
474 snmp_add_null_var(request, varname, varname_len);
475 *instance = IPNETMASK;
476 snmp_add_null_var(request, varname, varname_len);
478 status = snmp_synch_response(Session, request, &response);
479 if (status != STAT_SUCCESS
480 || response->errstat != SNMP_ERR_NOERROR) {
482 "SNMP request failed for interface %d, variable %ld out of %d interfaces (IP)\n",
483 ifnum, response->errindex, cfg_nnets);
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);
491 switch (var->name[9]) {
493 ifindex = *var->val.integer;
494 for (cur_if = if_table;
495 cur_if->ifindex != ifindex && cur_if->ifindex != 0;
497 cur_if->ifindex = ifindex;
500 memmove(curifip, var->name + 10, sizeof(curifip));
501 memmove(&cur_if->ifip, var->val.string, sizeof(u_long));
504 memmove(&cur_if->netmask, var->val.string, sizeof(u_long));
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));
512 strcpy(cur_if->route, "none");
513 if ((i = strlen(cur_if->route)) > max_route)
515 if (cur_if->ifip.s_addr)
516 strcpy(cur_if->ip, routename(cur_if->ifip));
518 strcpy(cur_if->ip, "none");
519 if ((i = strlen(cur_if->ip)) > max_ip)
522 snmp_free_pdu(response);
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);
530 *instance = oldindex;
532 snmp_add_null_var(request, varname, varname_len);
534 snmp_add_null_var(request, varname, varname_len);
535 *ifentry = IFOPERSTATUS;
536 snmp_add_null_var(request, varname, varname_len);
538 snmp_add_null_var(request, varname, varname_len);
539 *ifentry = OUTOCTETS;
540 snmp_add_null_var(request, varname, varname_len);
543 snmp_synch_response(Session, request,
544 &response)) == STAT_SUCCESS) {
545 if (response->errstat != SNMP_ERR_NOSUCHNAME)
548 snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) == NULL)
550 snmp_free_pdu(response);
552 if (status != STAT_SUCCESS
553 || response->errstat != SNMP_ERR_NOERROR) {
555 "SNMP request failed for interface %d, variable %ld out of %d interfaces (IF)\n",
556 ifnum, response->errindex, cfg_nnets);
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);
564 if (!var->val.integer)
566 switch (var->name[9]) {
568 ifindex = *var->val.integer;
569 for (cur_if = if_table;
570 cur_if->ifindex != ifindex && cur_if->ifindex != 0;
572 cur_if->ifindex = ifindex;
575 sprintf(cur_if->ioctets, "%lu", *var->val.integer);
576 i = strlen(cur_if->ioctets);
581 sprintf(cur_if->ooctets, "%lu", *var->val.integer);
582 i = strlen(cur_if->ooctets);
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)
596 cur_if->operstatus = *var->val.integer;
601 snmp_free_pdu(response);
603 if (intrface != NULL && strcmp(cur_if->name, intrface) != 0) {
607 if (cur_if->operstatus != MIB_IFSTATUS_UP) {
608 cp = strchr(cur_if->name, '\0');
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");
621 for (ifnum = 0, cur_if = if_table; ifnum < cfg_nnets;
623 if (cur_if->name[0] == 0)
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);
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 */
645 u_char signalled; /* set if alarm goes off "early" */
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.
653 #if (defined(WIN32) || defined(cygwin))
655 static time_t timezup;
657 timerSet(int interval_seconds)
659 sav_int = interval_seconds;
660 timezup = time(0) + interval_seconds;
664 * you can do better than this !
670 while (time(&now) < timezup)
677 tx.tv_usec = 400 * 1000; /* 400 milliseconds */
678 select(0, 0, 0, 0, &tx);
686 * Called if an interval expires before sidewaysintpr has completed a loop.
687 * Sets a flag to not wait for the alarm.
696 timerSet(int interval_seconds)
699 (void) sigset(SIGALRM, catchalarm);
701 (void) signal(SIGALRM, catchalarm);
704 (void) alarm(interval_seconds);
717 oldmask = sigblock(sigmask(SIGALRM));
725 #endif /* !WIN32 && !cygwin */
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.
734 sidewaysintpr(unsigned int interval)
736 register struct iftot *ip, *total;
738 struct iftot *lastif, *sum, *interesting, ifnow, *now = &ifnow;
739 netsnmp_variable_list *var;
740 oid varname[MAX_OID_LEN], *instance, *ifentry;
742 int ifnum, cfg_nnets;
745 sum = iftot + MAXIF - 1;
749 getvarbyname(Session, oid_cfg_nnets,
750 sizeof(oid_cfg_nnets) / sizeof(oid));
752 cfg_nnets = *var->val.integer;
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++) {
761 ip->ift_name[0] = '(';
763 var = getvarbyname(Session, varname, varname_len);
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);
770 cp = (char *) strchr(ip->ift_name, ' ');
773 if (intrface && strcmp(ip->ift_name + 1, intrface) == 0)
775 ip->ift_name[15] = '\0';
776 cp = (char *) strchr(ip->ift_name, '\0');
779 if (ip >= iftot + MAXIF - 2)
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++) {
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");
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;
818 memset(now, 0, sizeof(*now));
820 *ifentry = INUCASTPKTS;
821 var = getvarbyname(Session, varname, varname_len);
823 now->ift_ip = *var->val.integer;
826 *ifentry = INNUCASTPKTS;
827 var = getvarbyname(Session, varname, varname_len);
829 now->ift_ip += *var->val.integer;
833 var = getvarbyname(Session, varname, varname_len);
835 now->ift_ie = *var->val.integer;
838 *ifentry = OUTUCASTPKTS;
839 var = getvarbyname(Session, varname, varname_len);
841 now->ift_op = *var->val.integer;
844 *ifentry = OUTNUCASTPKTS;
845 var = getvarbyname(Session, varname, varname_len);
847 now->ift_op += *var->val.integer;
850 *ifentry = OUTERRORS;
851 var = getvarbyname(Session, varname, varname_len);
853 now->ift_oe = *var->val.integer;
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;
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);