/* * save info from incoming trap * * return 0 on success, anything else is an error */ static int _sql_save_trap_info(sql_buf *sqlb, netsnmp_pdu *pdu, netsnmp_transport *transport) { static oid trapoids[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5, 0 }; oid *trap_oid, tmp_oid[MAX_OID_LEN]; time_t now; struct tm *cur_time; size_t tmp_size; size_t buf_host_len_t, buf_oid_len_t, buf_user_len_t; int oid_overflow, trap_oid_len; netsnmp_variable_list *vars; if ((NULL == sqlb) || (NULL == pdu) || (NULL == transport)) return -1; DEBUGMSGTL(("sql:queue", "queueing incoming trap\n")); /** time */ (void) time(&now); cur_time = localtime(&now); sqlb->time.year = cur_time->tm_year + 1900; sqlb->time.month = cur_time->tm_mon + 1; sqlb->time.day = cur_time->tm_mday; sqlb->time.hour = cur_time->tm_hour; sqlb->time.minute = cur_time->tm_min; sqlb->time.second = cur_time->tm_sec; sqlb->time.second_part = 0; sqlb->time.neg = 0; /** host name */ buf_host_len_t = 0; tmp_size = sizeof(sqlb->host); realloc_format_trap((u_char**)&sqlb->host, &tmp_size, &buf_host_len_t, 1, "%B", pdu, transport); sqlb->host_len = buf_host_len_t; /* snmpTrapOID */ if (pdu->command == SNMP_MSG_TRAP) { /* * convert a v1 trap to a v2 varbind */ if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) { trap_oid_len = pdu->enterprise_length; memcpy(tmp_oid, pdu->enterprise, sizeof(oid) * trap_oid_len); if (tmp_oid[trap_oid_len - 1] != 0) tmp_oid[trap_oid_len++] = 0; tmp_oid[trap_oid_len++] = pdu->specific_type; trap_oid = tmp_oid; } else { trapoids[9] = pdu->trap_type + 1; trap_oid = trapoids; trap_oid_len = OID_LENGTH(trapoids); } } else { vars = pdu->variables; if (vars && vars->next_variable) { trap_oid_len = vars->next_variable->val_len / sizeof(oid); trap_oid = vars->next_variable->val.objid; } else { static oid null_oid[] = { 0, 0 }; trap_oid_len = OID_LENGTH(null_oid); trap_oid = null_oid; } } tmp_size = 0; buf_oid_len_t = oid_overflow = 0; netsnmp_sprint_realloc_objid_tree((u_char**)&sqlb->oid,&tmp_size, &buf_oid_len_t, 1, &oid_overflow, trap_oid, trap_oid_len); sqlb->oid_len = buf_oid_len_t; if (oid_overflow) snmp_log(LOG_WARNING,"OID truncated in sql buffer\n"); /** request id */ sqlb->reqid = pdu->reqid; /** version (convert to 1 based, for sql enum) */ sqlb->version = pdu->version + 1; /** command type (convert to 1 based, for sql enum) */ sqlb->type = pdu->command - 159; /** community string/user name */ tmp_size = 0; buf_user_len_t = 0; realloc_format_trap((u_char**)&sqlb->user, &tmp_size, &buf_user_len_t, 1, "%u", pdu, transport); sqlb->user_len = buf_user_len_t; /** transport */ sqlb->transport = transport->f_fmtaddr(transport, pdu->transport_data, pdu->transport_data_length); /** security model */ sqlb->security_model = pdu->securityModel; if ((SNMP_MP_MODEL_SNMPv3+1) == sqlb->version) { sqlb->msgid = pdu->msgid; sqlb->security_level = pdu->securityLevel; if (pdu->contextName) { sqlb->context = netsnmp_strdup_and_null((u_char*)pdu->contextName, pdu->contextNameLen); sqlb->context_len = pdu->contextNameLen; } if (pdu->contextEngineID) { sqlb->context_engine_len = binary_to_hex(pdu->contextEngineID, pdu->contextEngineIDLen, &sqlb->context_engine); } if (pdu->securityName) { sqlb->security_name = netsnmp_strdup_and_null((u_char*)pdu->securityName, pdu->securityNameLen); sqlb->security_name_len = pdu->securityNameLen; } if (pdu->securityEngineID) { sqlb->security_engine_len = binary_to_hex(pdu->securityEngineID, pdu->securityEngineIDLen, &sqlb->security_engine); } } return 0; }
/* * Trap handler for logging to a file */ int print_handler( netsnmp_pdu *pdu, netsnmp_transport *transport, netsnmp_trapd_handler *handler) { u_char *rbuf = NULL; size_t r_len = 64, o_len = 0; int trunc = 0; DEBUGMSGTL(( "snmptrapd", "print_handler\n")); /* * Don't bother logging authentication failures * XXX - can we handle this via suitable handler entries instead? */ if (pdu->trap_type == SNMP_TRAP_AUTHFAIL && dropauth) return NETSNMPTRAPD_HANDLER_OK; if ((rbuf = (u_char *) calloc(r_len, 1)) == NULL) { snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n"); return NETSNMPTRAPD_HANDLER_FAIL; /* Failed but keep going */ } /* * If there's a format string registered for this trap, then use it. */ if (handler && handler->format) { DEBUGMSGTL(( "snmptrapd", "format = '%s'\n", handler->format)); if (*handler->format) { trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, handler->format, pdu, transport); } else { free(rbuf); return NETSNMPTRAPD_HANDLER_OK; /* A 0-length format string means don't log */ } /* * Otherwise (i.e. a NULL handler format string), * use a standard output format setting * either configurable, or hardwired * * XXX - v1 traps use a different routine for hardwired output * Do we actually need this separate v1 routine? * Or would a suitable format string be sufficient? */ } else { if ( pdu->command == SNMP_MSG_TRAP ) { if (print_format1) { DEBUGMSGTL(( "snmptrapd", "print_format v1 = '%s'\n", print_format1)); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, print_format1, pdu, transport); } else { DEBUGMSGTL(( "snmptrapd", "v1 format\n")); trunc = !realloc_format_plain_trap(&rbuf, &r_len, &o_len, 1, pdu, transport); } } else { if (print_format2) { DEBUGMSGTL(( "snmptrapd", "print_format v2 = '%s'\n", print_format2)); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, print_format2, pdu, transport); } else { DEBUGMSGTL(( "snmptrapd", "v2/3 format\n")); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, PRINT_V23_NOTIFICATION_FORMAT, pdu, transport); } } } snmp_log(LOG_INFO, "%s%s", rbuf, (trunc?" [TRUNCATED]\n":"")); free(rbuf); return NETSNMPTRAPD_HANDLER_OK; }
/* * Trap handler for invoking a suitable script */ int command_handler( netsnmp_pdu *pdu, netsnmp_transport *transport, netsnmp_trapd_handler *handler) { #ifndef USING_UTILITIES_EXECUTE_MODULE NETSNMP_LOGONCE((LOG_WARNING, "support for run_shell_command not available\n")); return NETSNMPTRAPD_HANDLER_FAIL; #else u_char *rbuf = NULL; size_t r_len = 64, o_len = 0; int oldquick; DEBUGMSGTL(( "snmptrapd", "command_handler\n")); DEBUGMSGTL(( "snmptrapd", "token = '%s'\n", handler->token)); if (handler && handler->token && *handler->token) { netsnmp_pdu *v2_pdu = NULL; if (pdu->command == SNMP_MSG_TRAP) v2_pdu = convert_v1pdu_to_v2(pdu); else v2_pdu = pdu; oldquick = snmp_get_quick_print(); snmp_set_quick_print(1); /* * Format the trap and pass this string to the external command */ if ((rbuf = (u_char *) calloc(r_len, 1)) == NULL) { snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n"); return NETSNMPTRAPD_HANDLER_FAIL; /* Failed but keep going */ } /* * If there's a format string registered for this trap, then use it. * Otherwise use the standard execution format setting. */ if (handler && handler->format && *handler->format) { DEBUGMSGTL(( "snmptrapd", "format = '%s'\n", handler->format)); realloc_format_trap(&rbuf, &r_len, &o_len, 1, handler->format, v2_pdu, transport); } else { if ( pdu->command == SNMP_MSG_TRAP && exec_format1 ) { DEBUGMSGTL(( "snmptrapd", "exec v1 = '%s'\n", exec_format1)); realloc_format_trap(&rbuf, &r_len, &o_len, 1, exec_format1, pdu, transport); } else if ( pdu->command != SNMP_MSG_TRAP && exec_format2 ) { DEBUGMSGTL(( "snmptrapd", "exec v2/3 = '%s'\n", exec_format2)); realloc_format_trap(&rbuf, &r_len, &o_len, 1, exec_format2, pdu, transport); } else { DEBUGMSGTL(( "snmptrapd", "execute format\n")); realloc_format_trap(&rbuf, &r_len, &o_len, 1, EXECUTE_FORMAT, v2_pdu, transport); } } /* * and pass this formatted string to the command specified */ run_shell_command(handler->token, (char*)rbuf, NULL, NULL); /* Not interested in output */ snmp_set_quick_print(oldquick); if (pdu->command == SNMP_MSG_TRAP) snmp_free_pdu(v2_pdu); free(rbuf); } return NETSNMPTRAPD_HANDLER_OK; #endif /* !def USING_UTILITIES_EXECUTE_MODULE */ }
/* * Trap handler for logging via syslog */ int syslog_handler( netsnmp_pdu *pdu, netsnmp_transport *transport, netsnmp_trapd_handler *handler) { u_char *rbuf = NULL; size_t r_len = 64, o_len = 0; int trunc = 0; DEBUGMSGTL(( "snmptrapd", "syslog_handler\n")); if (SyslogTrap) return NETSNMPTRAPD_HANDLER_OK; if ((rbuf = (u_char *) calloc(r_len, 1)) == NULL) { snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n"); return NETSNMPTRAPD_HANDLER_FAIL; /* Failed but keep going */ } /* * If there's a format string registered for this trap, then use it. */ if (handler && handler->format) { DEBUGMSGTL(( "snmptrapd", "format = '%s'\n", handler->format)); if (*handler->format) { trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, handler->format, pdu, transport); } else { free(rbuf); return NETSNMPTRAPD_HANDLER_OK; /* A 0-length format string means don't log */ } /* * Otherwise (i.e. a NULL handler format string), * use a standard output format setting * either configurable, or hardwired * * XXX - v1 traps use a different hardwired formats for * standard and enterprise specific traps * Do we actually need this? */ } else { if ( pdu->command == SNMP_MSG_TRAP ) { if (syslog_format1) { DEBUGMSGTL(( "snmptrapd", "syslog_format v1 = '%s'\n", syslog_format1)); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, syslog_format1, pdu, transport); } else if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) { DEBUGMSGTL(( "snmptrapd", "v1 enterprise format\n")); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, SYSLOG_V1_ENTERPRISE_FORMAT, pdu, transport); } else { DEBUGMSGTL(( "snmptrapd", "v1 standard trap format\n")); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, SYSLOG_V1_STANDARD_FORMAT, pdu, transport); } } else { /* SNMPv2/3 notifications */ if (syslog_format2) { DEBUGMSGTL(( "snmptrapd", "syslog_format v1 = '%s'\n", syslog_format2)); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, syslog_format2, pdu, transport); } else { DEBUGMSGTL(( "snmptrapd", "v2/3 format\n")); trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1, SYSLOG_V23_NOTIFICATION_FORMAT, pdu, transport); } } } snmp_log(LOG_WARNING, "%s%s", rbuf, (trunc?" [TRUNCATED]\n":"")); free(rbuf); return NETSNMPTRAPD_HANDLER_OK; }