| /* |
| * snmpstatus.c - send snmp GET requests to a network entity. |
| * |
| */ |
| /*********************************************************************** |
| Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University |
| |
| All Rights Reserved |
| |
| Permission to use, copy, modify, and distribute this software and its |
| documentation for any purpose and without fee is hereby granted, |
| provided that the above copyright notice appear in all copies and that |
| both that copyright notice and this permission notice appear in |
| supporting documentation, and that the name of CMU not be |
| used in advertising or publicity pertaining to distribution of the |
| software without specific, written prior permission. |
| |
| CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
| ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL |
| CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR |
| ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
| WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
| ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
| SOFTWARE. |
| ******************************************************************/ |
| #include <net-snmp/net-snmp-config.h> |
| |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| #include <sys/types.h> |
| #if HAVE_NETINET_IN_H |
| #include <netinet/in.h> |
| #endif |
| #include <stdio.h> |
| #include <ctype.h> |
| #if TIME_WITH_SYS_TIME |
| # ifdef WIN32 |
| # include <sys/timeb.h> |
| # else |
| # include <sys/time.h> |
| # endif |
| # include <time.h> |
| #else |
| # if HAVE_SYS_TIME_H |
| # include <sys/time.h> |
| # else |
| # include <time.h> |
| # endif |
| #endif |
| #if HAVE_SYS_SELECT_H |
| #include <sys/select.h> |
| #endif |
| #if HAVE_WINSOCK_H |
| #include <winsock.h> |
| #endif |
| #if HAVE_NETDB_H |
| #include <netdb.h> |
| #endif |
| #if HAVE_ARPA_INET_H |
| #include <arpa/inet.h> |
| #endif |
| |
| #include <net-snmp/utilities.h> |
| |
| #include <net-snmp/net-snmp-includes.h> |
| |
| oid objid_sysDescr[] = { 1, 3, 6, 1, 2, 1, 1, 1, 0 }; |
| size_t length_sysDescr = sizeof(objid_sysDescr) / sizeof(oid); |
| oid objid_sysUpTime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 }; |
| size_t length_sysUpTime = sizeof(objid_sysUpTime) / sizeof(oid); |
| oid objid_ifOperStatus[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 8 }; |
| size_t length_ifOperStatus = |
| sizeof(objid_ifOperStatus) / sizeof(oid); |
| oid objid_ifInUCastPkts[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 11 }; |
| size_t length_ifInUCastPkts = |
| sizeof(objid_ifInUCastPkts) / sizeof(oid); |
| oid objid_ifInNUCastPkts[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 12 }; |
| size_t length_ifInNUCastPkts = |
| sizeof(objid_ifInNUCastPkts) / sizeof(oid); |
| oid objid_ifOutUCastPkts[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 17 }; |
| size_t length_ifOutUCastPkts = |
| sizeof(objid_ifOutUCastPkts) / sizeof(oid); |
| oid objid_ifOutNUCastPkts[] = |
| { 1, 3, 6, 1, 2, 1, 2, 2, 1, 18 }; |
| size_t length_ifOutNUCastPkts = |
| sizeof(objid_ifOutNUCastPkts) / sizeof(oid); |
| oid objid_ipInReceives[] = { 1, 3, 6, 1, 2, 1, 4, 3, 0 }; |
| size_t length_ipInReceives = |
| sizeof(objid_ipInReceives) / sizeof(oid); |
| oid objid_ipOutRequests[] = { 1, 3, 6, 1, 2, 1, 4, 10, 0 }; |
| size_t length_ipOutRequests = |
| sizeof(objid_ipOutRequests) / sizeof(oid); |
| |
| #define NETSNMP_DS_APP_DONT_FIX_PDUS 0 |
| |
| static void |
| optProc(int argc, char *const *argv, int opt) |
| { |
| switch (opt) { |
| case 'C': |
| while (*optarg) { |
| switch (*optarg++) { |
| case 'f': |
| netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, |
| NETSNMP_DS_APP_DONT_FIX_PDUS); |
| break; |
| default: |
| fprintf(stderr, "Unknown flag passed to -C: %c\n", |
| optarg[-1]); |
| exit(1); |
| } |
| } |
| break; |
| } |
| } |
| |
| void |
| usage(void) |
| { |
| fprintf(stderr, "USAGE: snmpstatus "); |
| snmp_parse_args_usage(stderr); |
| fprintf(stderr, "\n\n"); |
| snmp_parse_args_descriptions(stderr); |
| fprintf(stderr, |
| " -C APPOPTS\t\tSet various application specific behaviours:\n"); |
| fprintf(stderr, |
| "\t\t\t f: do not fix errors and retry the request\n"); |
| } |
| |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| netsnmp_session session, *ss; |
| netsnmp_pdu *pdu, *response; |
| netsnmp_variable_list *vars; |
| netsnmp_transport *transport = NULL; |
| char *sysdescr = NULL; |
| u_long uptime = 0; |
| int status; |
| int ipin = 0, ipout = 0, ipackets = 0, opackets = 0; |
| int good_var; |
| int down_interfaces = 0; |
| char buf[40]; |
| int interfaces; |
| int count; |
| int exitval = 0; |
| |
| /* |
| * get the common command line arguments |
| */ |
| switch (snmp_parse_args(argc, argv, &session, "C:", &optProc)) { |
| case -2: |
| exit(0); |
| case -1: |
| usage(); |
| exit(1); |
| default: |
| break; |
| } |
| |
| SOCK_STARTUP; |
| |
| /* |
| * open an SNMP session |
| */ |
| ss = snmp_open(&session); |
| if (ss == NULL) { |
| /* |
| * diagnose snmp_open errors with the input netsnmp_session pointer |
| */ |
| snmp_sess_perror("snmpstatus", &session); |
| SOCK_CLEANUP; |
| exit(1); |
| } |
| |
| /* |
| * create PDU for GET request and add object names to request |
| */ |
| pdu = snmp_pdu_create(SNMP_MSG_GET); |
| snmp_add_null_var(pdu, objid_sysDescr, length_sysDescr); |
| snmp_add_null_var(pdu, objid_sysUpTime, length_sysUpTime); |
| snmp_add_null_var(pdu, objid_ipInReceives, length_ipInReceives); |
| snmp_add_null_var(pdu, objid_ipOutRequests, length_ipOutRequests); |
| |
| /* |
| * do the request |
| */ |
| retry: |
| status = snmp_synch_response(ss, pdu, &response); |
| if (status == STAT_SUCCESS) { |
| if (response->errstat == SNMP_ERR_NOERROR) { |
| for (vars = response->variables; vars; |
| vars = vars->next_variable) { |
| if (vars->name_length == length_sysDescr |
| && !memcmp(objid_sysDescr, vars->name, |
| sizeof(objid_sysDescr))) { |
| sysdescr = (char *) malloc(vars->val_len + 1); |
| memcpy(sysdescr, vars->val.string, vars->val_len); |
| sysdescr[vars->val_len] = '\0'; |
| } |
| if (vars->name_length == length_sysUpTime && |
| !memcmp(objid_sysUpTime, vars->name, |
| sizeof(objid_sysUpTime)) && |
| vars->val.integer) { |
| uptime = *vars->val.integer; |
| } |
| if (vars->name_length == length_ipInReceives && |
| !memcmp(objid_ipInReceives, vars->name, |
| sizeof(objid_ipInReceives)) && |
| vars->val.integer) { |
| ipin = *vars->val.integer; |
| } |
| if (vars->name_length == length_ipOutRequests && |
| !memcmp(objid_ipOutRequests, vars->name, |
| sizeof(objid_ipOutRequests)) && |
| vars->val.integer) { |
| ipout = *vars->val.integer; |
| } |
| } |
| } else { |
| fprintf(stderr, "Error in packet.\nReason: %s\n", |
| snmp_errstring(response->errstat)); |
| if (response->errindex != 0) { |
| fprintf(stderr, "Failed object: "); |
| for (count = 1, vars = response->variables; |
| vars && count != response->errindex; |
| vars = vars->next_variable, count++); |
| if (vars) |
| fprint_objid(stderr, vars->name, vars->name_length); |
| fprintf(stderr, "\n"); |
| } |
| |
| /* |
| * retry if the errored variable was successfully removed |
| */ |
| if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
| NETSNMP_DS_APP_DONT_FIX_PDUS)) { |
| pdu = snmp_fix_pdu(response, SNMP_MSG_GET); |
| snmp_free_pdu(response); |
| response = NULL; |
| if (pdu != NULL) |
| goto retry; |
| } |
| } |
| } else if (status == STAT_TIMEOUT) { |
| fprintf(stderr, "Timeout: No Response from %s\n", |
| session.peername); |
| SOCK_CLEANUP; |
| exit(1); |
| } else { /* status == STAT_ERROR */ |
| snmp_sess_perror("snmpstatus", ss); |
| SOCK_CLEANUP; |
| exit(2); |
| } |
| |
| transport = snmp_sess_transport(snmp_sess_pointer(ss)); |
| if (transport != NULL && transport->f_fmtaddr != NULL) { |
| char *addr_string = transport->f_fmtaddr(transport, |
| response->transport_data, |
| response-> |
| transport_data_length); |
| if (addr_string != NULL) { |
| printf("[%s]=>[%s] Up: %s\n", addr_string, sysdescr, |
| uptime_string(uptime, buf)); |
| free(addr_string); |
| } |
| } else { |
| printf("[<UNKNOWN>]=>[%s] Up: %s\n", sysdescr, |
| uptime_string(uptime, buf)); |
| } |
| |
| if (response) |
| snmp_free_pdu(response); |
| |
| /* |
| * create PDU for GET request and add object names to request |
| */ |
| pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); |
| snmp_add_null_var(pdu, objid_ifOperStatus, length_ifOperStatus); |
| snmp_add_null_var(pdu, objid_ifInUCastPkts, length_ifInUCastPkts); |
| snmp_add_null_var(pdu, objid_ifInNUCastPkts, length_ifInNUCastPkts); |
| snmp_add_null_var(pdu, objid_ifOutUCastPkts, length_ifOutUCastPkts); |
| snmp_add_null_var(pdu, objid_ifOutNUCastPkts, length_ifOutNUCastPkts); |
| |
| /* |
| * ?? note: this code is not quite complete |
| */ |
| good_var = 5; |
| interfaces = 0; |
| while (good_var == 5) { |
| good_var = 0; |
| status = snmp_synch_response(ss, pdu, &response); |
| if (status == STAT_SUCCESS) { |
| if (response->errstat == SNMP_ERR_NOERROR) { |
| pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); |
| for (vars = response->variables; vars; |
| vars = vars->next_variable) { |
| if ((vars->type & 0xF0) == 0x80) { |
| print_variable(vars->name, vars->name_length, vars); |
| continue; |
| } |
| if (vars->name_length >= length_ifOperStatus |
| && !memcmp(objid_ifOperStatus, vars->name, |
| sizeof(objid_ifOperStatus))) { |
| if (*vars->val.integer != MIB_IFSTATUS_UP) |
| down_interfaces++; |
| snmp_add_null_var(pdu, vars->name, |
| vars->name_length); |
| good_var++; |
| } else if (vars->name_length >= length_ifInUCastPkts && |
| !memcmp(objid_ifInUCastPkts, vars->name, |
| sizeof(objid_ifInUCastPkts))) { |
| ipackets += *vars->val.integer; |
| snmp_add_null_var(pdu, vars->name, |
| vars->name_length); |
| good_var++; |
| } else if (vars->name_length >= length_ifInNUCastPkts |
| && !memcmp(objid_ifInNUCastPkts, vars->name, |
| sizeof(objid_ifInNUCastPkts))) { |
| ipackets += *vars->val.integer; |
| snmp_add_null_var(pdu, vars->name, |
| vars->name_length); |
| good_var++; |
| } else if (vars->name_length >= length_ifOutUCastPkts |
| && !memcmp(objid_ifOutUCastPkts, vars->name, |
| sizeof(objid_ifOutUCastPkts))) { |
| opackets += *vars->val.integer; |
| snmp_add_null_var(pdu, vars->name, |
| vars->name_length); |
| good_var++; |
| } else if (vars->name_length >= length_ifOutNUCastPkts |
| && !memcmp(objid_ifOutNUCastPkts, |
| vars->name, |
| sizeof(objid_ifOutNUCastPkts))) { |
| opackets += *vars->val.integer; |
| snmp_add_null_var(pdu, vars->name, |
| vars->name_length); |
| good_var++; |
| } |
| } |
| if (good_var == 5) |
| interfaces++; |
| } else { |
| fprintf(stderr, "Error in packet.\nReason: %s\n", |
| snmp_errstring(response->errstat)); |
| if (response->errindex != 0) { |
| fprintf(stderr, "Failed object: "); |
| for (count = 1, vars = response->variables; |
| vars && count != response->errindex; |
| vars = vars->next_variable, count++); |
| if (vars) |
| fprint_objid(stderr, vars->name, |
| vars->name_length); |
| fprintf(stderr, "\n"); |
| } |
| exitval = 2; |
| } |
| } else if (status == STAT_TIMEOUT) { |
| fprintf(stderr, "Timeout: No Response from %s\n", |
| session.peername); |
| exitval = 1; |
| } else { /* status == STAT_ERROR */ |
| snmp_sess_perror("snmpstatus", ss); |
| exitval = 1; |
| } |
| |
| if (response) |
| snmp_free_pdu(response); |
| } |
| printf("Interfaces: %d, Recv/Trans packets: %d/%d | IP: %d/%d\n", |
| interfaces, ipackets, opackets, ipin, ipout); |
| if (down_interfaces > 0) { |
| printf("%d interface%s down!\n", |
| down_interfaces, down_interfaces > 1 ? "s are" : " is"); |
| } |
| |
| snmp_close(ss); |
| SOCK_CLEANUP; |
| return exitval; |
| } |