static void send_v1_trap (struct snmp_session *ss, int trap, int specific) { struct snmp_pdu *pdu; struct timeval now, diff; gettimeofday(&now, NULL); now.tv_sec--; now.tv_usec += 1000000L; diff.tv_sec = now.tv_sec - starttime.tv_sec; diff.tv_usec = now.tv_usec - starttime.tv_usec; if (diff.tv_usec > 1000000L){ diff.tv_usec -= 1000000L; diff.tv_sec++; } pdu = snmp_pdu_create (SNMP_MSG_TRAP); if (trap == 6) { pdu->enterprise = objid_enterprisetrap; pdu->enterprise_length = length_enterprisetrap-2; } else { pdu->enterprise = version_id; pdu->enterprise_length = version_id_len; } pdu->agent_addr.sin_addr.s_addr = get_myaddr(); pdu->trap_type = trap; pdu->specific_type = specific; pdu->time = diff.tv_sec * 100 + diff.tv_usec / 10000; if (snmp_send (ss, pdu) == 0) { snmp_perror ("snmpd: send_v1_trap"); } #ifdef USING_MIBII_SNMP_MIB_MODULE snmp_outtraps++; #endif }
// Creates a SNMP TRAP PDU void snmpDeliverTrap_netsnmp::_createPdu( Uint16 snmpVersion, const String& trapOid, snmp_session*& sessionPtr, snmp_pdu*& snmpPdu) { PEG_METHOD_ENTER(TRC_IND_HANDLER, "snmpDeliverTrap_netsnmp::_createPdu"); oid _SYSTEM_UP_TIME_OID [] = {1,3,6,1,2,1,1,3,0}; oid _SNMPTRAP_OID [] = {1,3,6,1,6,3,1,1,4,1,0}; in_addr_t* pduInAddr; switch (snmpVersion) { case _SNMPv1_TRAP: { sessionPtr->version = SNMP_VERSION_1; // Create the PDU snmpPdu = snmp_pdu_create(SNMP_MSG_TRAP); // Failed to create pdu if (!snmpPdu) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( _MSG_PDU_CREATE_FAILED_KEY, _MSG_PDU_CREATE_FAILED)); } // Make sure that the v1 trap PDU includes the local IP address pduInAddr = (in_addr_t*) snmpPdu->agent_addr; *pduInAddr = get_myaddr(); // get system up time snmpPdu->time = get_uptime(); // Pack trap information into the PDU try { _packTrapInfoIntoPdu(trapOid, snmpPdu); } catch (CIMException& e) { Logger::put_l( Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING, MessageLoaderParms( _MSG_PACK_TRAP_INFO_INTO_PDU_FAILED_KEY, _MSG_PACK_TRAP_INFO_INTO_PDU_FAILED, e.getMessage())); } break; } case _SNMPv2C_TRAP: { sessionPtr->version = SNMP_VERSION_2c; // Create the PDU snmpPdu = snmp_pdu_create(SNMP_MSG_TRAP2); // Failed to create pdu if (!snmpPdu) { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, MessageLoaderParms( _MSG_PDU_CREATE_FAILED_KEY, _MSG_PDU_CREATE_FAILED)); } // Add sysUpTime to the PDU char sysUpTime[32]; sprintf(sysUpTime, "%ld", get_uptime()); Sint32 retCode; retCode = snmp_add_var( snmpPdu, _SYSTEM_UP_TIME_OID, OID_LENGTH(_SYSTEM_UP_TIME_OID), 't', sysUpTime); // Failed to add sysUpTime to the pdu if (retCode != 0) { String errMsg = snmp_api_errstring(retCode); Logger::put_l( Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING, MessageLoaderParms( _MSG_ADD_SYSUPTIME_TO_PDU_FAILED_KEY, _MSG_ADD_SYSUPTIME_TO_PDU_FAILED, errMsg)); } // Add snmp trap to the PDU retCode = snmp_add_var( snmpPdu, _SNMPTRAP_OID, OID_LENGTH(_SNMPTRAP_OID), 'o', trapOid.getCString()); // Failed to add snmp trap to the pdu if (retCode != 0) { String errMsg = snmp_api_errstring(retCode); Logger::put_l( Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING, MessageLoaderParms( _MSG_ADD_SNMP_TRAP_TO_PDU_FAILED_KEY, _MSG_ADD_SNMP_TRAP_TO_PDU_FAILED, errMsg)); } break; } default: { PEG_METHOD_EXIT(); throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED, MessageLoaderParms( _MSG_VERSION_NOT_SUPPORTED_KEY, _MSG_VERSION_NOT_SUPPORTED)); } } PEG_METHOD_EXIT(); }
int main (int argc, char *argv[]) { netsnmp_session session, *ss; netsnmp_pdu *pdu, *response; oid name[MAX_OID_LEN]; size_t name_length; int arg; int status; char *trap = NULL; char *prognam; int exitval = 0; #ifndef NETSNMP_DISABLE_SNMPV1 char *specific = NULL, *description = NULL, *agent = NULL; in_addr_t *pdu_in_addr_t; #endif prognam = strrchr (argv[0], '/'); if (prognam) prognam++; else prognam = argv[0]; putenv (strdup ("POSIXLY_CORRECT=1")); if (strcmp (prognam, "snmpinform") == 0) inform = 1; switch (arg = snmp_parse_args (argc, argv, &session, "C:", optProc)) { 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; session.callback = snmp_input; 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. */ } ss = snmp_add (&session, netsnmp_transport_open_client ("snmptrap", session.peername), 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); SOCK_CLEANUP; exit (1); } #ifndef NETSNMP_DISABLE_SNMPV1 if (session.version == SNMP_VERSION_1) { if (inform) { fprintf (stderr, "Cannot send INFORM as SNMPv1 PDU\n"); SOCK_CLEANUP; exit (1); } pdu = snmp_pdu_create (SNMP_MSG_TRAP); if (!pdu) { fprintf (stderr, "Failed to create trap PDU\n"); SOCK_CLEANUP; exit (1); } pdu_in_addr_t = (in_addr_t *) pdu->agent_addr; if (arg == argc) { fprintf (stderr, "No enterprise oid\n"); usage (); SOCK_CLEANUP; exit (1); } 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]); usage (); SOCK_CLEANUP; exit (1); } 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"); usage (); SOCK_CLEANUP; exit (1); } 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); exit (1); } } else { *pdu_in_addr_t = get_myaddr (); } if (++arg == argc) { fprintf (stderr, "Missing generic-trap parameter\n"); usage (); SOCK_CLEANUP; exit (1); } trap = argv[arg]; pdu->trap_type = atoi (trap); if (++arg == argc) { fprintf (stderr, "Missing specific-trap parameter\n"); usage (); SOCK_CLEANUP; exit (1); } specific = argv[arg]; pdu->specific_type = atoi (specific); if (++arg == argc) { fprintf (stderr, "Missing uptime parameter\n"); usage (); SOCK_CLEANUP; exit (1); } 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"); SOCK_CLEANUP; exit (1); } if (arg == argc) { fprintf (stderr, "Missing up-time parameter\n"); usage (); SOCK_CLEANUP; exit (1); } 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"); usage (); SOCK_CLEANUP; exit (1); } if (snmp_add_var (pdu, objid_snmptrap, sizeof (objid_snmptrap) / sizeof (oid), 'o', argv[arg]) != 0) { snmp_perror (argv[arg]); SOCK_CLEANUP; exit (1); } } arg++; while (arg < argc) { arg += 3; if (arg > argc) { fprintf (stderr, "%s: Missing type/value for variable\n", argv[arg - 3]); SOCK_CLEANUP; exit (1); } name_length = MAX_OID_LEN; if (!snmp_parse_oid (argv[arg - 3], name, &name_length)) { snmp_perror (argv[arg - 3]); SOCK_CLEANUP; exit (1); } if (snmp_add_var (pdu, name, name_length, argv[arg - 2][0], argv[arg - 1]) != 0) { snmp_perror (argv[arg - 3]); SOCK_CLEANUP; exit (1); } } 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); exitval = 1; } else if (inform) snmp_free_pdu (response); snmp_close (ss); snmp_shutdown ("snmpapp"); SOCK_CLEANUP; return exitval; }
/** * This function allows you to make a distinction between generic * traps from different classes of equipment. For example, you may want * to handle a SNMP_TRAP_LINKDOWN trap for a particular device in a * different manner to a generic system SNMP_TRAP_LINKDOWN trap. * * * @param trap is the generic trap type. The trap types are: * - SNMP_TRAP_COLDSTART: * cold start * - SNMP_TRAP_WARMSTART: * warm start * - SNMP_TRAP_LINKDOWN: * link down * - SNMP_TRAP_LINKUP: * link up * - SNMP_TRAP_AUTHFAIL: * authentication failure * - SNMP_TRAP_EGPNEIGHBORLOSS: * egp neighbor loss * - SNMP_TRAP_ENTERPRISESPECIFIC: * enterprise specific * * @param specific is the specific trap value. * * @param enterprise is an enterprise oid in which you want to send specifc * traps from. * * @param enterprise_length is the length of the enterprise oid, use macro, * OID_LENGTH, to compute length. * * @param vars is used to supply list of variable bindings to form an SNMPv2 * trap. * * @param context currently unused * * @param flags currently unused * * @return void * * @see send_easy_trap * @see send_v2trap */ int netsnmp_send_traps(int trap, int specific, oid * enterprise, int enterprise_length, netsnmp_variable_list * vars, char * context, int flags) { netsnmp_pdu *template_v1pdu; netsnmp_pdu *template_v2pdu; netsnmp_variable_list *vblist = NULL; netsnmp_variable_list *trap_vb; netsnmp_variable_list *var; in_addr_t *pdu_in_addr_t; u_long uptime; struct trap_sink *sink; DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific)); DEBUGMSGOID(("trap", enterprise, enterprise_length)); DEBUGMSG(( "trap", "\n")); if (vars) { vblist = snmp_clone_varbind( vars ); if (!vblist) { snmp_log(LOG_WARNING, "send_trap: failed to clone varbind list\n"); return -1; } } if ( trap == -1 ) { /* * Construct the SNMPv2-style notification PDU */ if (!vblist) { snmp_log(LOG_WARNING, "send_trap: called with NULL v2 information\n"); return -1; } template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2); if (!template_v2pdu) { snmp_log(LOG_WARNING, "send_trap: failed to construct v2 template PDU\n"); snmp_free_varbind(vblist); return -1; } /* * Check the varbind list we've been given. * If it starts with a 'sysUptime.0' varbind, then use that. * Otherwise, prepend a suitable 'sysUptime.0' varbind. */ if (!snmp_oid_compare( vblist->name, vblist->name_length, sysuptime_oid, sysuptime_oid_len )) { template_v2pdu->variables = vblist; trap_vb = vblist->next_variable; } else { uptime = netsnmp_get_agent_uptime(); var = NULL; snmp_varlist_add_variable( &var, sysuptime_oid, sysuptime_oid_len, ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime)); if (!var) { snmp_log(LOG_WARNING, "send_trap: failed to insert sysUptime varbind\n"); snmp_free_pdu(template_v2pdu); snmp_free_varbind(vblist); return -1; } template_v2pdu->variables = var; var->next_variable = vblist; trap_vb = vblist; } /* * 'trap_vb' should point to the snmpTrapOID.0 varbind, * identifying the requested trap. If not then bomb out. * If it's a 'standard' trap, then we need to append an * snmpEnterprise varbind (if there isn't already one). */ if (!trap_vb || snmp_oid_compare(trap_vb->name, trap_vb->name_length, snmptrap_oid, snmptrap_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 trapOID varbind provided\n"); snmp_free_pdu(template_v2pdu); return -1; } if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix), trap_prefix, OID_LENGTH(trap_prefix))) { var = find_varbind_in_list( template_v2pdu->variables, snmptrapenterprise_oid, snmptrapenterprise_oid_len); if (!var && !snmp_varlist_add_variable( &(template_v2pdu->variables), snmptrapenterprise_oid, snmptrapenterprise_oid_len, ASN_OBJECT_ID, (char*)enterprise, enterprise_length*sizeof(oid))) { snmp_log(LOG_WARNING, "send_trap: failed to add snmpEnterprise to v2 trap\n"); snmp_free_pdu(template_v2pdu); return -1; } } /* * If everything's OK, convert the v2 template into an SNMPv1 trap PDU. */ template_v1pdu = convert_v2pdu_to_v1( template_v2pdu ); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to convert v2->v1 template PDU\n"); } } else { /* * Construct the SNMPv1 trap PDU.... */ template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to construct v1 template PDU\n"); snmp_free_varbind(vblist); return -1; } template_v1pdu->trap_type = trap; template_v1pdu->specific_type = specific; template_v1pdu->time = netsnmp_get_agent_uptime(); if (snmp_clone_mem((void **) &template_v1pdu->enterprise, enterprise, enterprise_length * sizeof(oid))) { snmp_log(LOG_WARNING, "send_trap: failed to set v1 enterprise OID\n"); snmp_free_varbind(vblist); snmp_free_pdu(template_v1pdu); return -1; } template_v1pdu->enterprise_length = enterprise_length; template_v1pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; template_v1pdu->variables = vblist; /* * ... and convert it into an SNMPv2-style notification PDU. */ template_v2pdu = convert_v1pdu_to_v2( template_v1pdu ); if (!template_v2pdu) { snmp_log(LOG_WARNING, "send_trap: failed to convert v1->v2 template PDU\n"); } } /* * Check whether we're ignoring authFail traps */ if (template_v1pdu) { if (template_v1pdu->trap_type == SNMP_TRAP_AUTHFAIL && snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu(template_v1pdu); snmp_free_pdu(template_v2pdu); return 0; } /* * Ensure that the v1 trap PDU includes the local IP address */ pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); } /* * Now loop through the list of trap sinks * and call the trap callback routines, * providing an appropriately formatted PDU in each case */ for (sink = sinks; sink; sink = sink->next) { #ifndef NETSNMP_DISABLE_SNMPV1 if (sink->version == SNMP_VERSION_1) { if (template_v1pdu) { send_trap_to_sess(sink->sesp, template_v1pdu); } } else { #endif if (template_v2pdu) { template_v2pdu->command = sink->pdutype; send_trap_to_sess(sink->sesp, template_v2pdu); } #ifndef NETSNMP_DISABLE_SNMPV1 } #endif } if (template_v1pdu) snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP1, template_v1pdu); if (template_v2pdu) snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP2, template_v2pdu); snmp_free_pdu(template_v1pdu); snmp_free_pdu(template_v2pdu); return 0; }
int sendtrap(struct opts opts, char *community, int status, char *message) { int return_stat = 0; #ifdef HAVE_SNMPTRAP struct snmp_session session, *ss; struct snmp_pdu *pdu; char statusmsg[12]; oid enterprise[] = {1,3,6,1,4,1,300}; oid statusoid[] = {1,3,6,1,4,1,300,1}; oid messageoid[] = {1,3,6,1,4,1,300,2}; int counter; char *messagebuf; in_addr_t *pdu_in_addr_t; for (counter=0; counter < opts.nr_traphosts; counter++) { snmp_sess_init( &session ); /* strlen() doesn't count the terminating \0, so we do +1 in malloc. */ session.peername = (char *)malloc(strlen(opts.traphosts[counter])+1); strcpy (session.peername, opts.traphosts[counter]); session.community = (char *)malloc(strlen(community)+1); strcpy (session.community, community); session.community_len = strlen(session.community); session.version = SNMP_VERSION_1; session.retries = 5; session.timeout = 500; session.remote_port = 162; session.authenticator = NULL; ss = snmp_open(&session); if (!ss) { snmp_sess_perror( "Error: sendtrap/snmp_open", &session ); return_stat++; } pdu = snmp_pdu_create(SNMP_MSG_TRAP); pdu_in_addr_t = (struct in_addr_t *)&pdu->agent_addr; pdu->enterprise = malloc(sizeof(enterprise)); memcpy (pdu->enterprise, enterprise, sizeof(enterprise)); pdu->enterprise_length = sizeof(enterprise) / sizeof (oid); pdu->trap_type = 6; pdu->specific_type = 1; pdu->time = 0; pdu->contextEngineID = 0x0; *pdu_in_addr_t = get_myaddr(); sprintf(statusmsg, "%d", status); snmp_add_var (pdu, statusoid, sizeof(statusoid) / sizeof (oid), 'i', statusmsg); messagebuf = (char *)malloc(strlen(message)+1); strcpy(messagebuf,message); snmp_add_var (pdu, messageoid, sizeof(messageoid) / sizeof (oid), 's', message); if (!snmp_send(ss, pdu)) { snmp_sess_perror("Error: sendtrap/snmp_send", &ss ); return_stat++; } snmp_close(ss); } #endif return return_stat; }
void send_enterprise_trap_vars (int trap, int specific, oid *enterprise, int enterprise_length, struct variable_list *vars) { struct variable_list uptime_var, snmptrap_var, enterprise_var; struct variable_list *v2_vars, *last_var=NULL; struct snmp_pdu *template_pdu, *pdu; struct timeval now; long uptime; struct sockaddr_in *pduIp; struct trap_sink *sink; oid temp_oid[MAX_OID_LEN]; /* * Initialise SNMPv2 required variables */ gettimeofday(&now, NULL); uptime = calculate_time_diff(&now, &starttime); memset (&uptime_var, 0, sizeof (struct variable_list)); snmp_set_var_objid( &uptime_var, sysuptime_oid, OID_LENGTH(sysuptime_oid)); snmp_set_var_value( &uptime_var, (u_char *)&uptime, sizeof(uptime) ); uptime_var.type = ASN_TIMETICKS; uptime_var.next_variable = &snmptrap_var; memset (&snmptrap_var, 0, sizeof (struct variable_list)); snmp_set_var_objid( &snmptrap_var, snmptrap_oid, OID_LENGTH(snmptrap_oid)); /* value set later .... */ snmptrap_var.type = ASN_OBJECT_ID; if ( vars ) snmptrap_var.next_variable = vars; else snmptrap_var.next_variable = &enterprise_var; /* find end of provided varbind list, ready to append the enterprise info if necessary */ last_var = vars; while ( last_var && last_var->next_variable ) last_var = last_var->next_variable; memset (&enterprise_var, 0, sizeof (struct variable_list)); snmp_set_var_objid( &enterprise_var, snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid)); snmp_set_var_value( &enterprise_var, (u_char *)enterprise, enterprise_length*sizeof(oid)); enterprise_var.type = ASN_OBJECT_ID; enterprise_var.next_variable = NULL; v2_vars = &uptime_var; /* * Create a template PDU, ready for sending */ template_pdu = snmp_pdu_create( SNMP_MSG_TRAP ); if ( template_pdu == NULL ) { /* Free memory if value stored dynamically */ snmp_set_var_value( &enterprise_var, NULL, 0); return; } template_pdu->trap_type = trap; template_pdu->specific_type = specific; if ( snmp_clone_mem((void **)&template_pdu->enterprise, enterprise, enterprise_length*sizeof(oid))) { snmp_free_pdu( template_pdu ); snmp_set_var_value( &enterprise_var, NULL, 0); return; } template_pdu->enterprise_length = enterprise_length; template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; pduIp = (struct sockaddr_in *)&template_pdu->agent_addr; pduIp->sin_family = AF_INET; pduIp->sin_len = sizeof(*pduIp); pduIp->sin_addr.s_addr = get_myaddr(); template_pdu->time = uptime; /* * Now use the parameters to determine * which v2 variables are needed, * and what values they should take. */ switch ( trap ) { case -1: /* * SNMPv2 only * Check to see whether the variables provided * are sufficient for SNMPv2 notifications */ if (vars && snmp_oid_compare(vars->name, vars->name_length, sysuptime_oid, OID_LENGTH(sysuptime_oid)) == 0 ) v2_vars = vars; else if (vars && snmp_oid_compare(vars->name, vars->name_length, snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0 ) uptime_var.next_variable = vars; else { /* Hmmm... we don't seem to have a value - oops! */ snmptrap_var.next_variable = vars; } last_var = NULL; /* Don't need enterprise info */ break; /* "Standard" SNMPv1 traps */ case SNMP_TRAP_COLDSTART: snmp_set_var_value( &snmptrap_var, (u_char *)cold_start_oid, sizeof(cold_start_oid)); break; case SNMP_TRAP_WARMSTART: snmp_set_var_value( &snmptrap_var, (u_char *)warm_start_oid, sizeof(warm_start_oid)); break; case SNMP_TRAP_LINKDOWN: snmp_set_var_value( &snmptrap_var, (u_char *)link_down_oid, sizeof(link_down_oid)); break; case SNMP_TRAP_LINKUP: snmp_set_var_value( &snmptrap_var, (u_char *)link_up_oid, sizeof(link_up_oid)); break; case SNMP_TRAP_AUTHFAIL: if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu( template_pdu ); snmp_set_var_value( &enterprise_var, NULL, 0); return; } snmp_set_var_value( &snmptrap_var, (u_char *)auth_fail_oid, sizeof(auth_fail_oid)); break; case SNMP_TRAP_EGPNEIGHBORLOSS: snmp_set_var_value( &snmptrap_var, (u_char *)egp_xxx_oid, sizeof(egp_xxx_oid)); break; case SNMP_TRAP_ENTERPRISESPECIFIC: memcpy( &temp_oid, (char *)enterprise, (enterprise_length)*sizeof(oid)); temp_oid[ enterprise_length ] = 0; temp_oid[ enterprise_length+1 ] = specific; snmp_set_var_value( &snmptrap_var, (u_char *)&temp_oid, (enterprise_length+2)*sizeof(oid)); snmptrap_var.next_variable = vars; last_var = NULL; /* Don't need version info */ break; } /* * Now loop through the list of trap sinks, * sending an appropriately formatted PDU to each */ for ( sink = sinks ; sink ; sink=sink->next ) { if ( sink->version == SNMP_VERSION_1 && trap == -1 ) continue; /* Skip v1 sinks for v2 only traps */ template_pdu->version = sink->version; template_pdu->command = sink->pdutype; if ( sink->version != SNMP_VERSION_1 ) { template_pdu->variables = v2_vars; if ( last_var ) last_var->next_variable = &enterprise_var; } else template_pdu->variables = vars; pdu = snmp_clone_pdu( template_pdu ); pdu->sessid = sink->sesp->sessid; /* AgentX only ? */ if ( snmp_send( sink->sesp, pdu) == 0 ) { snmp_sess_perror ("snmpd: send_trap", sink->sesp); snmp_free_pdu( pdu ); } else { snmp_increment_statistic(STAT_SNMPOUTTRAPS); snmp_increment_statistic(STAT_SNMPOUTPKTS); } if ( sink->version != SNMP_VERSION_1 && last_var ) last_var->next_variable = NULL; } /* Free memory if values stored dynamically */ snmp_set_var_value( &enterprise_var, NULL, 0); snmp_set_var_value( &snmptrap_var, NULL, 0); /* Ensure we don't free anything we shouldn't */ if ( last_var ) last_var->next_variable = NULL; template_pdu->variables = NULL; snmp_free_pdu( template_pdu ); }
void send_enterprise_trap_vars(int trap, int specific, oid * enterprise, int enterprise_length, netsnmp_variable_list * vars) { netsnmp_variable_list uptime_var, snmptrap_var, enterprise_var; netsnmp_variable_list *v2_vars, *last_var = NULL; netsnmp_pdu *template_pdu; u_long uptime; in_addr_t *pdu_in_addr_t; struct trap_sink *sink; #ifdef BRCM_SNMP_MIB_SUPPORT oid temp_oid[MAX_OID_LEN]; #endif /* * Initialise SNMPv2 required variables */ uptime = netsnmp_get_agent_uptime(); memset(&uptime_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&uptime_var, sysuptime_oid, OID_LENGTH(sysuptime_oid)); snmp_set_var_value(&uptime_var, (u_char *) & uptime, sizeof(uptime)); uptime_var.type = ASN_TIMETICKS; uptime_var.next_variable = &snmptrap_var; memset(&snmptrap_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&snmptrap_var, snmptrap_oid, OID_LENGTH(snmptrap_oid)); /* * value set later .... */ snmptrap_var.type = ASN_OBJECT_ID; if (vars) snmptrap_var.next_variable = vars; else snmptrap_var.next_variable = &enterprise_var; /* * find end of provided varbind list, * ready to append the enterprise info if necessary */ last_var = vars; while (last_var && last_var->next_variable) last_var = last_var->next_variable; memset(&enterprise_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&enterprise_var, snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid)); snmp_set_var_value(&enterprise_var, (u_char *) enterprise, enterprise_length * sizeof(oid)); enterprise_var.type = ASN_OBJECT_ID; enterprise_var.next_variable = NULL; v2_vars = &uptime_var; /* * Create a template PDU, ready for sending */ template_pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (template_pdu == NULL) { /* * Free memory if value stored dynamically */ snmp_set_var_value(&enterprise_var, NULL, 0); return; } template_pdu->trap_type = trap; template_pdu->specific_type = specific; if (snmp_clone_mem((void **) &template_pdu->enterprise, enterprise, enterprise_length * sizeof(oid))) { snmp_free_pdu(template_pdu); snmp_set_var_value(&enterprise_var, NULL, 0); return; } template_pdu->enterprise_length = enterprise_length; template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; pdu_in_addr_t = (in_addr_t *) template_pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); template_pdu->time = uptime; /* * Now use the parameters to determine * which v2 variables are needed, * and what values they should take. */ switch (trap) { case -1: /* * SNMPv2 only * Check to see whether the variables provided * are sufficient for SNMPv2 notifications */ if (vars && netsnmp_oid_equals(vars->name, vars->name_length, sysuptime_oid, OID_LENGTH(sysuptime_oid)) == 0) v2_vars = vars; else if (vars && netsnmp_oid_equals(vars->name, vars->name_length, snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0) uptime_var.next_variable = vars; else { /* * Hmmm... we don't seem to have a value - oops! */ snmptrap_var.next_variable = vars; } last_var = NULL; /* Don't need enterprise info */ convert_v2_to_v1(vars, template_pdu); break; /* * "Standard" SNMPv1 traps */ case SNMP_TRAP_COLDSTART: snmp_set_var_value(&snmptrap_var, (u_char *) cold_start_oid, sizeof(cold_start_oid)); break; case SNMP_TRAP_WARMSTART: snmp_set_var_value(&snmptrap_var, (u_char *) warm_start_oid, sizeof(warm_start_oid)); break; case SNMP_TRAP_LINKDOWN: snmp_set_var_value(&snmptrap_var, (u_char *) link_down_oid, sizeof(link_down_oid)); break; case SNMP_TRAP_LINKUP: snmp_set_var_value(&snmptrap_var, (u_char *) link_up_oid, sizeof(link_up_oid)); break; case SNMP_TRAP_AUTHFAIL: if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu(template_pdu); snmp_set_var_value(&enterprise_var, NULL, 0); return; } snmp_set_var_value(&snmptrap_var, (u_char *) auth_fail_oid, sizeof(auth_fail_oid)); break; case SNMP_TRAP_EGPNEIGHBORLOSS: snmp_set_var_value(&snmptrap_var, (u_char *) egp_xxx_oid, sizeof(egp_xxx_oid)); break; #ifdef BRCM_SNMP_MIB_SUPPORT case SNMP_TRAP_ENTERPRISESPECIFIC: memcpy(temp_oid, (char *) enterprise, (enterprise_length) * sizeof(oid)); temp_oid[enterprise_length] = 0; temp_oid[enterprise_length + 1] = specific; snmp_set_var_value(&snmptrap_var, (u_char *) temp_oid, (enterprise_length + 2) * sizeof(oid)); snmptrap_var.next_variable = vars; last_var = NULL; /* Don't need version info */ break; #endif /* BRCM_SNMP_MIB_SUPPORT */ } /* * Now loop through the list of trap sinks, * sending an appropriately formatted PDU to each */ for (sink = sinks; sink; sink = sink->next) { if (sink->version == SNMP_VERSION_1 && trap == -1) continue; /* Skip v1 sinks for v2 only traps */ template_pdu->command = sink->pdutype; if (sink->version != SNMP_VERSION_1) { template_pdu->variables = v2_vars; if (last_var) last_var->next_variable = &enterprise_var; } else template_pdu->variables = vars; send_trap_to_sess(sink->sesp, template_pdu); if (sink->version != SNMP_VERSION_1 && last_var) last_var->next_variable = NULL; } /* * send stuff to registered callbacks */ /* * v2 traps/informs */ template_pdu->variables = v2_vars; if (last_var) last_var->next_variable = &enterprise_var; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP2, template_pdu); if (last_var) last_var->next_variable = NULL; /* * v1 traps */ template_pdu->command = SNMP_MSG_TRAP; template_pdu->variables = vars; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP1, template_pdu); /* * Free memory if values stored dynamically */ snmp_set_var_value(&enterprise_var, NULL, 0); snmp_set_var_value(&snmptrap_var, NULL, 0); /* * Ensure we don't free anything we shouldn't */ if (last_var) last_var->next_variable = NULL; template_pdu->variables = NULL; snmp_free_pdu(template_pdu); }
int trap_send_v1(TrapReceiver *tRcv, TrapData *tData) { netsnmp_pdu *pdu=NULL; oid name[MAX_OID_LEN]; size_t name_length; in_addr_t *pdu_in_addr_t=NULL; int ret = 0; TrapNode *tNode=NULL; TrapParam *tParam=NULL; pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (NULL == pdu) { trap_syslog(LOG_WARNING, "Failed to create snmp pdu: snmp_msg_trap\n"); SOCK_CLEANUP; return 1; } name_length = MAX_OID_LEN; if (!snmp_parse_oid(tData->oid, name, &name_length)) { trap_syslog(LOG_WARNING, "Failed to parse oid: %s\n", tData->oid); SOCK_CLEANUP; snmp_free_pdu(pdu); return 1; } pdu->enterprise = (oid *)malloc(name_length * sizeof(oid)); memcpy(pdu->enterprise, name, name_length * sizeof(oid)); pdu->enterprise_length = name_length; pdu_in_addr_t = (in_addr_t *)pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); pdu->trap_type = 6; pdu->specific_type = 17; pdu->time = get_uptime(); for (tNode = tData->paramList.first; tNode; tNode = tNode->next) { tParam = tNode->data; name_length = MAX_OID_LEN; if (!snmp_parse_oid(tParam->oid, name, &name_length)) { trap_syslog(LOG_WARNING, "Failed to parse oid: %s\n", tParam->oid); SOCK_CLEANUP; snmp_free_pdu(pdu); return 1; } if (snmp_add_var(pdu, name, name_length, tParam->type, tParam->value) != 0) { trap_syslog(LOG_WARNING, "Failed to add var: %c, %s\n", tParam->type, tParam->value); SOCK_CLEANUP; snmp_free_pdu(pdu); return 1; } } if (snmp_send(tRcv->ss, pdu) == 0) { trap_syslog(LOG_WARNING, "Failed to send trap pdu\n"); snmp_free_pdu(pdu); ret = 1; } return ret; }