diff options
Diffstat (limited to 'apps/snmptest.c')
-rw-r--r-- | apps/snmptest.c | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/apps/snmptest.c b/apps/snmptest.c new file mode 100644 index 0000000..24de47b --- /dev/null +++ b/apps/snmptest.c @@ -0,0 +1,535 @@ +/* + * snmptest.c - send snmp requests to a network entity. + * + * Usage: snmptest -v 1 [-q] hostname community [objectID] + * + */ +/*********************************************************************** + 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 +# include <sys/time.h> +# 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_NETDB_H +#include <netdb.h> +#endif +#if HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#include <net-snmp/net-snmp-includes.h> + +int command = SNMP_MSG_GET; + +int input_variable(netsnmp_variable_list *); + +void +usage(void) +{ + fprintf(stderr, "USAGE: snmptest "); + snmp_parse_args_usage(stderr); + fprintf(stderr, "\n\n"); + snmp_parse_args_descriptions(stderr); +} + +int +main(int argc, char *argv[]) +{ + netsnmp_session session, *ss; + netsnmp_pdu *pdu = NULL, *response, *copy = NULL; + netsnmp_variable_list *vars, *vp; + netsnmp_transport *transport = NULL; + int ret; + int status, count; + char input[128]; + int varcount, nonRepeaters = -1, maxRepetitions; + + /* + * get the common command line arguments + */ + switch (snmp_parse_args(argc, argv, &session, NULL, NULL)) { + case NETSNMP_PARSE_ARGS_ERROR: + exit(1); + case NETSNMP_PARSE_ARGS_SUCCESS_EXIT: + exit(0); + case NETSNMP_PARSE_ARGS_ERROR_USAGE: + 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("snmptest", &session); + SOCK_CLEANUP; + exit(1); + } + + varcount = 0; + for(;;) { + vars = NULL; + for (ret = 1; ret != 0;) { + vp = (netsnmp_variable_list *) + malloc(sizeof(netsnmp_variable_list)); + memset(vp, 0, sizeof(netsnmp_variable_list)); + + while ((ret = input_variable(vp)) == -1); + if (ret == 1) { + varcount++; + /* + * add it to the list + */ + if (vars == NULL) { + /* + * if first variable + */ + pdu = snmp_pdu_create(command); + pdu->variables = vp; + } else { + vars->next_variable = vp; + } + vars = vp; + } else { + /* + * free the last (unused) variable + */ + if (vp->name) + free((char *) vp->name); + if (vp->val.string) + free((char *) vp->val.string); + free((char *) vp); + + if (command == SNMP_MSG_GETBULK) { + if (nonRepeaters == -1) { + nonRepeaters = varcount; + ret = -1; /* so we collect more variables */ + printf("Now input the repeating variables\n"); + } else { + printf("What repeat count? "); + fflush(stdout); + if (!fgets(input, sizeof(input), stdin)) { + printf("Quitting, Goodbye\n"); + SOCK_CLEANUP; + exit(0); + } + maxRepetitions = atoi(input); + pdu->non_repeaters = nonRepeaters; + pdu->max_repetitions = maxRepetitions; + } + } + } + if (varcount == 0 && ret == 0) { + if (!copy) { + printf("No PDU to send.\n"); + ret = -1; + } else { + pdu = snmp_clone_pdu(copy); + printf("Resending last PDU.\n"); + } + } + } + copy = snmp_clone_pdu(pdu); + if (command == SNMP_MSG_TRAP2) { + /* + * No response needed + */ + if (!snmp_send(ss, pdu)) { + snmp_free_pdu(pdu); + snmp_sess_perror("snmptest", ss); + } + } else { + status = snmp_synch_response(ss, pdu, &response); + if (status == STAT_SUCCESS) { + if (command == SNMP_MSG_INFORM && + response->errstat == SNMP_ERR_NOERROR) { + printf("Inform Acknowledged\n"); + } else { + switch (response->command) { + case SNMP_MSG_GET: + printf("Received Get Request "); + break; + case SNMP_MSG_GETNEXT: + printf("Received Getnext Request "); + break; + case SNMP_MSG_RESPONSE: + printf("Received Get Response "); + break; +#ifndef NETSNMP_NO_WRITE_SUPPORT + case SNMP_MSG_SET: + printf("Received Set Request "); + break; +#endif /* NETSNMP_NO_WRITE_SUPPORT */ + case SNMP_MSG_TRAP: + printf("Received Trap Request "); + break; + case SNMP_MSG_GETBULK: + printf("Received Bulk Request "); + break; + case SNMP_MSG_INFORM: + printf("Received Inform Request "); + break; + case SNMP_MSG_TRAP2: + printf("Received SNMPv2 Trap Request "); + break; + } + 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("from %s\n", addr_string); + free(addr_string); + } + } else { + printf("from <UNKNOWN>\n"); + } + printf + ("requestid 0x%lX errstat 0x%lX errindex 0x%lX\n", + response->reqid, response->errstat, + response->errindex); + if (response->errstat == SNMP_ERR_NOERROR) { + for (vars = response->variables; vars; + vars = vars->next_variable) + print_variable(vars->name, vars->name_length, + vars); + } else { + printf("Error in packet.\nReason: %s\n", + snmp_errstring(response->errstat)); + if (response->errindex != 0) { + for (count = 1, vars = response->variables; + vars && count != response->errindex; + vars = vars->next_variable, count++); + if (vars) { + printf("Failed object: "); + print_objid(vars->name, vars->name_length); + } + printf("\n"); + } + } + } + } else if (status == STAT_TIMEOUT) { + printf("Timeout: No Response from %s\n", session.peername); + } else { /* status == STAT_ERROR */ + snmp_sess_perror("snmptest", ss); + } + + if (response) + snmp_free_pdu(response); + } + varcount = 0; + nonRepeaters = -1; + } + /* NOTREACHED */ +} + +int +input_variable(netsnmp_variable_list * vp) +{ + char buf[256]; + size_t val_len; + u_char ch; + + printf("Variable: "); + fflush(stdout); + if (!fgets(buf, sizeof(buf), stdin)) { + printf("Quitting, Goobye\n"); + SOCK_CLEANUP; + exit(0); + } + val_len = strlen(buf); + + if (val_len == 0 || *buf == '\n') { + vp->name_length = 0; + return 0; + } + if (buf[val_len - 1] == '\n') + buf[--val_len] = 0; + if (*buf == '$') { + switch (toupper((unsigned char)(buf[1]))) { + case 'G': + command = SNMP_MSG_GET; + printf("Request type is Get Request\n"); + break; + case 'N': + command = SNMP_MSG_GETNEXT; + printf("Request type is Getnext Request\n"); + break; +#ifndef NETSNMP_NO_WRITE_SUPPORT + case 'S': + command = SNMP_MSG_SET; + printf("Request type is Set Request\n"); + break; +#endif /* NETSNMP_NO_WRITE_SUPPORT */ + case 'B': + command = SNMP_MSG_GETBULK; + printf("Request type is Bulk Request\n"); + printf + ("Enter a blank line to terminate the list of non-repeaters\n"); + printf("and to begin the repeating variables\n"); + break; + case 'I': + command = SNMP_MSG_INFORM; + printf("Request type is Inform Request\n"); + printf("(Are you sending to the right port?)\n"); + break; + case 'T': + command = SNMP_MSG_TRAP2; + printf("Request type is SNMPv2 Trap Request\n"); + printf("(Are you sending to the right port?)\n"); + break; + case 'D': + if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_DUMP_PACKET)) { + netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_DUMP_PACKET, 0); + printf("Turned packet dump off\n"); + } else { + netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_DUMP_PACKET, 1); + printf("Turned packet dump on\n"); + } + break; + case 'Q': + switch ((toupper((unsigned char)(buf[2])))) { + case '\n': + case 0: + printf("Quitting, Goodbye\n"); + SOCK_CLEANUP; + exit(0); + break; + case 'P': + if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_QUICK_PRINT)) { + netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_QUICK_PRINT, 0); + printf("Turned quick printing off\n"); + } else { + netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, + NETSNMP_DS_LIB_QUICK_PRINT, 1); + printf("Turned quick printing on\n"); + } + break; + } + break; + default: + printf("Bad command\n"); + } + return -1; + } + { + oid name[MAX_OID_LEN]; + vp->name_length = MAX_OID_LEN; + if (!snmp_parse_oid(buf, name, &vp->name_length)) { + snmp_perror(buf); + return -1; + } + vp->name = snmp_duplicate_objid(name, vp->name_length); + } + + if (command == SNMP_MSG_INFORM + || command == SNMP_MSG_TRAP2 +#ifndef NETSNMP_NO_WRITE_SUPPORT + || command == SNMP_MSG_SET +#endif /* NETSNMP_NO_WRITE_SUPPORT */ + ) { + printf("Type [i|u|s|x|d|n|o|t|a]: "); + fflush(stdout); + if (!fgets(buf, sizeof(buf), stdin)) { + printf("Quitting, Goodbye\n"); + SOCK_CLEANUP; + exit(0); + } + ch = *buf; + switch (ch) { + case 'i': + vp->type = ASN_INTEGER; + break; + case 'u': + vp->type = ASN_UNSIGNED; + break; + case 's': + vp->type = ASN_OCTET_STR; + break; + case 'x': + vp->type = ASN_OCTET_STR; + break; + case 'd': + vp->type = ASN_OCTET_STR; + break; + case 'n': + vp->type = ASN_NULL; + break; + case 'o': + vp->type = ASN_OBJECT_ID; + break; + case 't': + vp->type = ASN_TIMETICKS; + break; + case 'a': + vp->type = ASN_IPADDRESS; + break; + default: + printf + ("bad type \"%c\", use \"i\", \"u\", \"s\", \"x\", \"d\", \"n\", \"o\", \"t\", or \"a\".\n", + *buf); + return -1; + } + getValue: + printf("Value: "); + fflush(stdout); + if (!fgets(buf, sizeof(buf), stdin)) { + printf("Quitting, Goodbye\n"); + SOCK_CLEANUP; + exit(0); + } + switch (vp->type) { + case ASN_INTEGER: + vp->val.integer = (long *) malloc(sizeof(long)); + *(vp->val.integer) = atoi(buf); + vp->val_len = sizeof(long); + break; + case ASN_UNSIGNED: + vp->val.integer = (long *) malloc(sizeof(long)); + *(vp->val.integer) = strtoul(buf, NULL, 0); + vp->val_len = sizeof(long); + break; + case ASN_OCTET_STR: + if (ch == 'd') { + size_t buf_len = 256; + val_len = 0; + if ((vp->val.string = (u_char *) malloc(buf_len)) == NULL) { + printf("malloc failure\n"); + goto getValue; + } + if (!snmp_decimal_to_binary(&(vp->val.string), &buf_len, + &val_len, 1, buf)) { + printf("Bad value or no sub-identifier > 255\n"); + free(vp->val.string); + goto getValue; + } + vp->val_len = val_len; + } else if (ch == 's') { + /* + * -1 to omit trailing newline + */ + vp->val.string = (u_char *) malloc(strlen(buf) - 1); + if (vp->val.string == NULL) { + printf("malloc failure\n"); + goto getValue; + } + memcpy(vp->val.string, buf, strlen(buf) - 1); + vp->val.string[sizeof(vp->val.string)-1] = 0; + vp->val_len = strlen(buf) - 1; + } else if (ch == 'x') { + size_t buf_len = 256; + val_len = 0; + if ((vp->val.string = (u_char *) malloc(buf_len)) == NULL) { + printf("malloc failure\n"); + goto getValue; + } + if (!snmp_hex_to_binary(&(vp->val.string), &buf_len, + &val_len, 1, buf)) { + printf("Bad value (need pairs of hex digits)\n"); + free(vp->val.string); + goto getValue; + } + vp->val_len = val_len; + } + break; + case ASN_NULL: + vp->val_len = 0; + vp->val.string = NULL; + break; + case ASN_OBJECT_ID: + if ('\n' == buf[strlen(buf) - 1]) + buf[strlen(buf) - 1] = '\0'; + else { + oid value[MAX_OID_LEN]; + vp->val_len = MAX_OID_LEN; + if (0 == read_objid(buf, value, &vp->val_len)) { + printf("Unrecognised OID value\n"); + goto getValue; + } + vp->val.objid = snmp_duplicate_objid(value, vp->val_len); + vp->val_len *= sizeof(oid); + } + break; + case ASN_TIMETICKS: + vp->val.integer = (long *) malloc(sizeof(long)); + *(vp->val.integer) = atoi(buf); + vp->val_len = sizeof(long); + break; + case ASN_IPADDRESS: + vp->val.integer = (long *) malloc(sizeof(long)); + *(vp->val.integer) = inet_addr(buf); + vp->val_len = sizeof(long); + break; + default: + printf("Internal error\n"); + break; + } + } else { /* some form of get message */ + vp->type = ASN_NULL; + vp->val_len = 0; + } + return 1; +} |