#include "CSnmptrap.h" #include "TSysTime.h" #include "CSysFormat.h" oid CSnmptrap::objid_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 }; oid CSnmptrap::objid_sysuptime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 }; oid CSnmptrap::objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; CSnmptrap::CSnmptrap() { inform = 0; } CSnmptrap::~CSnmptrap() { } std::string CSnmptrap::FindString(std::string a, std::string b) { if (a.size()>b.size()) swap(a, b); //确保前面的一个字符串短; std::string str_m; for (int i = 0; i= sizeof(Opts)) { snmp_log(LOG_ERR, "Too many localOpts in snmp_parse_args()\n"); return -1; } strcat(Opts, localOpts); } /* * get the options */ DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc)); for (arg = 0; arg < argc; arg++) { DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg])); } optind = 1; while ((arg = getopt(argc, argv, Opts)) != EOF) { DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c (optarg %s) (sp %d)\n", optind, arg, optarg, sp)); switch (arg) { case '-': if (strcasecmp(optarg, "help") == 0) { ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } if (strcasecmp(optarg, "version") == 0) { fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT; goto out; } handle_long_opt(optarg); break; case 'V': fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT; goto out; case 'h': ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; case 'H': init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE); fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT; goto out; case 'Y': netsnmp_config_remember(optarg); break; case 'm': setenv("MIBS", optarg, 1); break; case 'M': netsnmp_get_mib_directory(); /* prepare the default directories */ netsnmp_set_mib_directory(optarg); break; case 'O': cp = snmp_out_options(optarg, argc, argv); if (cp != NULL) { fprintf(stderr, "Unknown output option passed to -O: %c.\n", *cp); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'I': cp = snmp_in_options(optarg, argc, argv); if (cp != NULL) { fprintf(stderr, "Unknown input option passed to -I: %c.\n", *cp); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'P': cp = snmp_mib_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown parsing option passed to -P: %c.\n", *cp); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'd': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET, 1); break; case 's': session->localname = strdup(optarg); break; case 'v': session->version = -1; if (!strcmp(optarg, "1")) { session->version = SNMP_VERSION_1; } if (!strcasecmp(optarg, "2c")) { session->version = SNMP_VERSION_2c; } if (!strcasecmp(optarg, "3")) { session->version = SNMP_VERSION_3; } if (session->version == -1) { fprintf(stderr, "Invalid version specified after -v flag: %s\n", optarg); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'p': fprintf(stderr, "Warning: -p option is no longer used - "); fprintf(stderr, "specify the remote host as HOST:PORT\n"); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; case 'T': { char leftside[SNMP_MAXBUF_MEDIUM], rightside[SNMP_MAXBUF_MEDIUM]; char *tmpcp, *tmpopt; /* ensure we have a proper argument */ tmpopt = strdup(optarg); tmpcp = strchr(tmpopt, '='); if (!tmpcp) { fprintf(stderr, "-T expects a NAME=VALUE pair.\n"); free(tmpopt); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } *tmpcp++ = '\0'; /* create the transport config container if this is the first */ if (!session->transport_configuration) { netsnmp_container_init_list(); session->transport_configuration = netsnmp_container_find("transport_configuration:fifo"); if (!session->transport_configuration) { fprintf(stderr, "failed to initialize the transport configuration container\n"); free(tmpopt); ret = NETSNMP_PARSE_ARGS_ERROR; goto out; } session->transport_configuration->compare = (netsnmp_container_compare*) netsnmp_transport_config_compare; } /* set the config */ strlcpy(leftside, tmpopt, sizeof(leftside)); strlcpy(rightside, tmpcp, sizeof(rightside)); CONTAINER_INSERT(session->transport_configuration, netsnmp_transport_create_config(leftside, rightside)); free(tmpopt); } break; case 't': session->timeout = (long)(atof(optarg) * 1000000L); if (session->timeout <= 0) { fprintf(stderr, "Invalid timeout in seconds after -t flag.\n"); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'r': session->retries = atoi(optarg); if (session->retries < 0 || !isdigit((unsigned char)(optarg[0]))) { fprintf(stderr, "Invalid number of retries after -r flag.\n"); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'c': if (zero_sensitive) { SNMP_FREE(Cpsz); /* free any previous value */ if ((Cpsz = strdup(optarg)) != NULL) { //memcpy(optarg,0, sizeof(optarg)); //memset(optarg, '\0', strlen(optarg)); } else { fprintf(stderr, "malloc failure processing -c flag.\n"); ret = NETSNMP_PARSE_ARGS_ERROR; goto out; } } else { Cpsz = strdup(optarg); } break; case '3': if (snmpv3_parse_args(optarg, session, &Apsz, &Xpsz, argc, argv, flags) < 0) { ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; case 'L': if (snmp_log_options(optarg, argc, argv) < 0) { ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; #define SNMPV3_CMD_OPTIONS #ifdef SNMPV3_CMD_OPTIONS case 'Z': case 'e': case 'E': case 'n': case 'l': case 'u': #ifdef NETSNMP_SECMOD_USM case 'a': case 'x': case 'A': case 'X': #endif /* NETSNMP_SECMOD_USM */ if (snmpv3_parse_arg(arg, optarg, session, &Apsz, &Xpsz, argc, argv, flags) < 0) { ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } break; #endif /* SNMPV3_CMD_OPTIONS */ case '?': ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; default: proc(argc, argv, arg); break; } } DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc)); /* * save command line parameters which should have precedence above config file settings * (There ought to be a more scalable approach than this....) */ if (netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION)) { backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION)); } /* * read in MIB database and initialize the snmp library, read the config file */ init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE); /* * restore command line parameters which should have precedence above config file settings */ if (backup_NETSNMP_DS_LIB_OUTPUT_PRECISION) { netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION, backup_NETSNMP_DS_LIB_OUTPUT_PRECISION); free(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION); } /* * session default version */ if (session->version == SNMP_DEFAULT_VERSION) { /* * run time default version */ session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SNMPVERSION); /* * compile time default version */ if (!session->version) { switch (NETSNMP_DEFAULT_SNMP_VERSION) { case 1: session->version = SNMP_VERSION_1; break; case 2: session->version = SNMP_VERSION_2c; break; case 3: session->version = SNMP_VERSION_3; break; default: snmp_log(LOG_ERR, "Can't determine a valid SNMP version for the session\n"); return(NETSNMP_PARSE_ARGS_ERROR); } } else { if (session->version == NETSNMP_DS_SNMP_VERSION_1) /* bogus value. version 1 actually = 0 */ session->version = SNMP_VERSION_1; } } #ifdef NETSNMP_SECMOD_USM /* XXX: this should ideally be moved to snmpusm.c somehow */ /* * make master key from pass phrases */ if (Apsz) { session->securityAuthKeyLen = USM_AUTH_KU_LEN; if (session->securityAuthProto == NULL) { /* * get .conf set default */ const oid *def = get_default_authtype(&session->securityAuthProtoLen); session->securityAuthProto = snmp_duplicate_objid(def, session->securityAuthProtoLen); } if (session->securityAuthProto == NULL) { session->securityAuthProto = snmp_duplicate_objid(SNMP_DEFAULT_AUTH_PROTO, SNMP_DEFAULT_AUTH_PROTOLEN); session->securityAuthProtoLen = SNMP_DEFAULT_AUTH_PROTOLEN; } if (generate_Ku(session->securityAuthProto, session->securityAuthProtoLen, (u_char *)Apsz, strlen(Apsz), session->securityAuthKey, &session->securityAuthKeyLen) != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "Error generating a key (Ku) from the supplied authentication pass phrase. \n"); ret = NETSNMP_PARSE_ARGS_ERROR; goto out; } free(Apsz); Apsz = NULL; } if (Xpsz) { session->securityPrivKeyLen = USM_PRIV_KU_LEN; if (session->securityPrivProto == NULL) { /* * get .conf set default */ const oid *def = get_default_privtype(&session->securityPrivProtoLen); session->securityPrivProto = snmp_duplicate_objid(def, session->securityPrivProtoLen); } if (session->securityPrivProto == NULL) { session->securityPrivProto = snmp_duplicate_objid(SNMP_DEFAULT_PRIV_PROTO, SNMP_DEFAULT_PRIV_PROTOLEN); session->securityPrivProtoLen = SNMP_DEFAULT_PRIV_PROTOLEN; } if (generate_Ku(session->securityAuthProto, session->securityAuthProtoLen, (u_char *)Xpsz, strlen(Xpsz), session->securityPrivKey, &session->securityPrivKeyLen) != SNMPERR_SUCCESS) { snmp_perror(argv[0]); fprintf(stderr, "Error generating a key (Ku) from the supplied privacy pass phrase. \n"); ret = NETSNMP_PARSE_ARGS_ERROR; goto out; } free(Xpsz); Xpsz = NULL; } #endif /* NETSNMP_SECMOD_USM */ /* * get the hostname */ if (optind == argc) { fprintf(stderr, "No hostname specified.\n"); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } session->peername = argv[optind++]; /* hostname */ #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) /* * If v1 or v2c, check community has been set, either by a -c option above, * or via a default token somewhere. * If neither, it will be taken from the incoming request PDU. */ if (session->version == SNMP_VERSION_1 || session->version == SNMP_VERSION_2c) { if (Cpsz == NULL) { Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_COMMUNITY); if (Cpsz == NULL) { if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_IGNORE_NO_COMMUNITY)) { DEBUGMSGTL(("snmp_parse_args", "ignoring that the community string is not present\n")); session->community = NULL; session->community_len = 0; } else { fprintf(stderr, "No community name specified.\n"); ret = NETSNMP_PARSE_ARGS_ERROR_USAGE; goto out; } } else { Cpsz = NULL; } } else { session->community = (unsigned char *)Cpsz; session->community_len = strlen(Cpsz); Cpsz = NULL; } } #endif /* support for community based SNMP */ ret = optind; out: free(Apsz); free(Xpsz); free(Cpsz); return ret; } int CSnmptrap::snmp_parse_args1(int argc, char **argv, netsnmp_session * session, const char *localOpts, void(*proc) (int, char *const *, int)) { return netsnmp_parse_args1(argc, argv, session, localOpts, proc, 0); } int CSnmptrap::trapmain(int argc, char *argv[],const char* custom) { netsnmp_session session, *ss; netsnmp_pdu *pdu, *response; oid name[MAX_OID_LEN]; size_t name_length; int arg; int status; char *trap = NULL; int exitval = 1; #ifndef NETSNMP_DISABLE_SNMPV1 char *specific = NULL, *description = NULL, *agent = NULL; in_addr_t *pdu_in_addr_t; #endif SOCK_STARTUP; //char* argv2[] = { "netsnmp_ALL.exe","-v", "2c", "-c", "public", "192.168.31.8", "", "1.3.6.1.4.1.2345", "HH3C-REDUNDANCY-POWER-MIB::hh3credundancyPowerStatus","i","2" }; //argv = argv2; /** parse args (also initializes session) */ arg = snmp_parse_args1(argc, argv, &session, "C:", optProc); session.callback = snmp_input1; session.callback_magic = NULL; /* * setup the local engineID which may be for either or both of the * contextEngineID and/or the securityEngineID. */ setup_engineID(NULL, NULL); /* if we don't have a contextEngineID set via command line arguments, use our internal engineID as the context. */ if (session.contextEngineIDLen == 0 || session.contextEngineID == NULL) { session.contextEngineID = snmpv3_generate_engineID(&session.contextEngineIDLen); } if (session.version == SNMP_VERSION_3 && !inform) { /* * for traps, we use ourselves as the authoritative engine * which is really stupid since command line apps don't have a * notion of a persistent engine. Hence, our boots and time * values are probably always really wacked with respect to what * a manager would like to see. * * The following should be enough to: * * 1) prevent the library from doing discovery for engineid & time. * 2) use our engineid instead of the remote engineid for * authoritative & privacy related operations. * 3) The remote engine must be configured with users for our engineID. * * -- Wes */ /* * pick our own engineID */ if (session.securityEngineIDLen == 0 || session.securityEngineID == NULL) { session.securityEngineID = snmpv3_generate_engineID(&session.securityEngineIDLen); } /* * set boots and time, which will cause problems if this * machine ever reboots and a remote trap receiver has cached our * boots and time... I'll cause a not-in-time-window report to * be sent back to this machine. */ if (session.engineBoots == 0) session.engineBoots = 1; if (session.engineTime == 0) /* not really correct, */ session.engineTime = get_uptime(); /* but it'll work. Sort of. */ set_enginetime(session.securityEngineID, session.securityEngineIDLen, session.engineBoots, session.engineTime, TRUE); } ss = snmp_add(&session, netsnmp_transport_open_client("snmptrap", session.peername,custom), NULL, NULL); if (ss == NULL) { /* * diagnose netsnmp_transport_open_client and snmp_add errors with * the input netsnmp_session pointer */ snmp_sess_perror("snmptrap", &session); goto out; } #ifndef NETSNMP_DISABLE_SNMPV1 if (session.version == SNMP_VERSION_1) { if (inform) { fprintf(stderr, "Cannot send INFORM as SNMPv1 PDU\n"); goto out; } pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (!pdu) { fprintf(stderr, "Failed to create trap PDU\n"); goto out; } pdu_in_addr_t = (in_addr_t *)pdu->agent_addr; if (arg == argc) { fprintf(stderr, "No enterprise oid\n"); goto out; } if (argv[arg][0] == 0) { pdu->enterprise = (oid *)malloc(sizeof(objid_enterprise)); memcpy(pdu->enterprise, objid_enterprise, sizeof(objid_enterprise)); pdu->enterprise_length = sizeof(objid_enterprise) / sizeof(oid); } else { name_length = MAX_OID_LEN; if (!snmp_parse_oid(argv[arg], name, &name_length)) { snmp_perror(argv[arg]); goto out; } pdu->enterprise = (oid *)malloc(name_length * sizeof(oid)); memcpy(pdu->enterprise, name, name_length * sizeof(oid)); pdu->enterprise_length = name_length; } if (++arg >= argc) { fprintf(stderr, "Missing agent parameter\n"); goto out; } agent = argv[arg]; if (agent != NULL && strlen(agent) != 0) { int ret = netsnmp_gethostbyname_v4(agent, pdu_in_addr_t); if (ret < 0) { fprintf(stderr, "unknown host: %s\n", agent); goto out; } } else { *pdu_in_addr_t = get_myaddr(); } if (++arg == argc) { fprintf(stderr, "Missing generic-trap parameter\n"); // usage(); goto out; } trap = argv[arg]; pdu->trap_type = atoi(trap); if (++arg == argc) { fprintf(stderr, "Missing specific-trap parameter\n"); goto out; } specific = argv[arg]; pdu->specific_type = atoi(specific); if (++arg == argc) { fprintf(stderr, "Missing uptime parameter\n"); goto out; } description = argv[arg]; if (description == NULL || *description == 0) pdu->time = get_uptime(); else pdu->time = atol(description); } else #endif { long sysuptime; char csysuptime[20]; pdu = snmp_pdu_create(inform ? SNMP_MSG_INFORM : SNMP_MSG_TRAP2); if (!pdu) { fprintf(stderr, "Failed to create notification PDU\n"); goto out; } if (arg == argc) { fprintf(stderr, "Missing up-time parameter\n"); goto out; } trap = argv[arg]; if (*trap == 0) { sysuptime = get_uptime(); sprintf(csysuptime, "%ld", sysuptime); trap = csysuptime; } snmp_add_var(pdu, objid_sysuptime, sizeof(objid_sysuptime) / sizeof(oid), 't', trap); if (++arg == argc) { fprintf(stderr, "Missing trap-oid parameter\n"); goto out; } if (snmp_add_var (pdu, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid), 'o', argv[arg]) != 0) { snmp_perror(argv[arg]); goto out; } } arg++; while (arg < argc) { arg += 3; if (arg > argc) { fprintf(stderr, "%s: Missing type/value for variable\n", argv[arg - 3]); goto out; } name_length = MAX_OID_LEN; if (!snmp_parse_oid(argv[arg - 3], name, &name_length)) { snmp_perror(argv[arg - 3]); goto out; } if (snmp_add_var(pdu, name, name_length, argv[arg - 2][0],argv[arg - 1]) != 0) { snmp_perror(argv[arg - 3]); goto out; } } if (inform) status = snmp_synch_response(ss, pdu, &response); else status = snmp_send(ss, pdu) == 0; if (status) { snmp_sess_perror(inform ? "snmpinform" : "snmptrap", ss); if (!inform) snmp_free_pdu(pdu); goto close_session; } else if (inform) snmp_free_pdu(response); exitval = 0; close_session: snmp_close(ss); //snmp_shutdown(NETSNMP_APPLICATION_CONFIG_TYPE); out: SOCK_CLEANUP; return exitval; }