#include #include "json.h" #include "CSnmpClass.h" #include "CSnmptrap.h" #include "log.h" #include "TSysTime.h" //char* CSnmpClass::m_pDdefault_port = "udp:192.168.1.82:162"; //char* CSnmpClass::m_pDdefault_port = "udp:192.168.12.10:162"; char* CSnmpClass::m_pDdefault_port = "udp:162"; char* CSnmpClass::m_pDefault_port = m_pDdefault_port; int CSnmpClass::m_nDofork = 1; void* CSnmpClass::m_pInstance = nullptr; CSnmpClass::CSnmpClass() { m_nAlarmStatus = 0; m_nPowerFlag = 0; m_nErpsFlag = 0; m_nPhyFlag = 0; m_nBoardFlag = 0; m_pOolInvoker = nullptr; m_pTrap1_fmt_str_remember = nullptr; m_nTrapd_status = SNMPTRAPD_STOPPED; m_pApp_name_long = "Net-SNMP Trap Handler"; m_pApp_name = "snmptrapd"; memset(m_bindip,0,100); AppLogConfigure(nullptr, "netsnmp", "netsnmp"); m_pOolInvoker = new TSysThreadPool; m_pOolInvoker->Start(2); } CSnmpClass::~CSnmpClass() { Stop(); std::vector ::iterator iter = m_pWhite_list.begin(); for (; iter != m_pWhite_list.end();) { if (*iter) { delete (*iter); (*iter) = NULL; } iter = m_pWhite_list.erase(iter); } if (m_pOolInvoker) { delete m_pOolInvoker; m_pOolInvoker = nullptr; } TermHandler(1); BLOG_DEBUG("app closed"); } RETSIGTYPE CSnmpClass::TermHandler(int sig) { netsnmp_running = 0; /* * In case of windows, select() in receive() function will not return * on signal. Thats why following function is called, which closes the * socket descriptors and causes the select() to return */ snmp_close(main_session); } int CSnmpClass::PreParse(netsnmp_session * session, netsnmp_transport *transport, void *transport_data, int transport_data_length) { return 1; } netsnmp_session* CSnmpClass::SnmptrapdAddSession(netsnmp_transport *t) { netsnmp_session sess, *session = &sess, *rc = NULL; snmp_sess_init(session); session->peername = SNMP_DEFAULT_PEERNAME; /* Original code had NULL here */ session->version = SNMP_DEFAULT_VERSION; session->community_len = SNMP_DEFAULT_COMMUNITY_LEN; session->retries = SNMP_DEFAULT_RETRIES; session->timeout = SNMP_DEFAULT_TIMEOUT; session->callback = snmp_input; session->callback_magic = (void *)t; session->authenticator = NULL; sess.isAuthoritative = SNMP_SESS_UNKNOWNAUTH; rc = snmp_add(session, t, PreParse, NULL); if (rc == NULL) { snmp_sess_perror("snmptrapd", session); } return rc; } void CSnmpClass::SnmptrapdCloseSessions(netsnmp_session * sess_list) { netsnmp_session *s = NULL, *next = NULL; for (s = sess_list; s != NULL; s = next) { next = s->next; snmp_close(s); } } void CSnmpClass::ParseTrapdAddress(const char *token, char *cptr) { char buf[BUFSIZ]; char *p; cptr = copy_nword(cptr, buf, sizeof(buf)); if (m_pDefault_port == m_pDdefault_port) { m_pDefault_port = strdup(buf); } else { p = (char*)malloc(strlen(buf) + 1 + strlen(m_pDefault_port) + 1); if (p) { strcpy(p, buf); strcat(p, ","); strcat(p, m_pDefault_port); } free(m_pDefault_port); m_pDefault_port = p; } } void CSnmpClass::FreeTrapdAddress(void) { if (m_pDefault_port != m_pDdefault_port) { free(m_pDefault_port); m_pDefault_port = m_pDdefault_port; } } void CSnmpClass::ParseConfigDoNotLogTraps(const char *token, char *cptr) { if (atoi(cptr) > 0) SyslogTrap++; } void CSnmpClass::ParseConfigDoNotFork(const char *token, char *cptr) { if (netsnmp_ds_parse_boolean(cptr) == 1) m_nDofork = 0; } void CSnmpClass::ParseConfigIgnoreAuthFailure(const char *token, char *cptr) { if (netsnmp_ds_parse_boolean(cptr) == 1) dropauth = 1; } void CSnmpClass::ParseConfigOutputOption(const char *token, char *cptr) { char *cp; cp = snmp_out_toggle_options(cptr); if (cp != NULL) { fprintf(stderr, "Unknown output option passed to -O: %c\n", *cp); } } void CSnmpClass::ParseConfigAddForwarderInfo(const char *token, char *cptr) { if (netsnmp_ds_parse_boolean(cptr) == 1) { netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ADD_FORWARDER_INFO, 1); } } void CSnmpClass::Action() { char custom[100] = ""; memcpy(custom, m_send_bind_ip.c_str(), m_send_bind_ip.size()); CSnmptrap* m_pTrap = new CSnmptrap; while (!IsAborted()) { Sleep(m_nMtime*1000); if (m_systemType == "h3c") continue; //m_Alarm.lock(); int status = m_nAlarmStatus; std::vector::iterator iter; for (iter = m_dst_ip.begin(); iter != m_dst_ip.end(); iter++) { m_pTrap->SendTrap2(status, *iter, m_sCommunity, "KTT Alarm", "1.3.6.1.4.1.2345", custom, m_needTime); BLOG_DEBUG(fmt::format("Action SendTrap:: ip:{},comunnity:{},KTT Alarm:{}", *iter, m_sCommunity, status)); } //m_pTrap->SendTrap2(status, m_dst_ip, m_sCommunity, "KTT Alarm", "1.3.6.1.4.1.2345",custom, m_needTime); } delete m_pTrap; } std::string CSnmpClass::FindString(std::string a, std::string b) { if (a.size()>b.size()) swap(a, b); //确保前面的一个字符串短; std::string str_m; for (int i = 0; iSendTrapH3c(status, "10.1.101.21", comunnity, "TKO Alarm"); m_pTrap->SendTrapH3c(status, "10.1.201.21", comunnity, "TKO Alarm"); m_pTrap->SendTrapH3c(status, "10.1.101.22", comunnity, "TKO Alarm"); m_pTrap->SendTrapH3c(status, "10.1.201.22", comunnity, "TKO Alarm"); BLOG_DEBUG(fmt::format("SendTrap:: comunnity:{},TKO Alarm:{}", comunnity, status)); break; case 'C': m_pTrap->SendTrapH3c(status, "10.4.101.21", comunnity, "CBL Alarm"); m_pTrap->SendTrapH3c(status, "10.4.201.21", comunnity, "CBL Alarm"); m_pTrap->SendTrapH3c(status, "10.4.101.22", comunnity, "CBL Alarm"); m_pTrap->SendTrapH3c(status, "10.4.201.22", comunnity, "CBL Alarm"); BLOG_DEBUG(fmt::format("SendTrap:: comunnity:{},CBL Alarm:{}", comunnity, status)); break; default: break; } // delete m_pTrap; } void CSnmpClass::SendString(int status, std::string comunnity, std::string buf, std::string moduleIdentity, std::string power) { m_Alarm.lock(); m_nAlarmStatus = status; m_Alarm.unlock(); CSnmptrap* m_pTrap = new CSnmptrap; char custom[100] = ""; memcpy(custom, m_send_bind_ip.c_str(), m_send_bind_ip.size()); std::vector::iterator iter; for (iter = m_dst_ip.begin(); iter != m_dst_ip.end(); iter++) { m_pTrap->SendTrap(status, *iter, comunnity, "KTT Alarm", moduleIdentity, power, custom, m_needTime); BLOG_DEBUG(fmt::format("SendTrap:: ip:{},comunnity:{},KTT Alarm:{}", *iter, comunnity, status)); } //m_pTrap->SendTrap(status, m_dst_ip, comunnity, "KTT Alarm", moduleIdentity, power,custom, m_needTime); /*m_pTrap->SendTrap(status, "192.168.31.8:161", comunnity, "KTT Alarm", moduleIdentity, power);*/ delete m_pTrap; } int CSnmpClass::ParsePtype(std::string buf,std::string upAnddown) { //POWER_FAILED //POWER_RECOVERED //PHY_UPDOWN int m_nResult = 1; if ("POWER_FAILED" == buf) { m_nPowerFlag = 1; m_nResult = 0; //SendString(1,buf); } if ("POWER_RECOVERED" == buf) { m_nPowerFlag = 0; m_nResult = 0; } if ("PHY_UPDOWN" == buf) { std::string::size_type m_nindex = upAnddown.find("changed to down"); if (m_nindex != upAnddown.npos) { //buff = buff.substr(0, m_nindex); m_nPhyFlag = 1; } else { m_nPhyFlag = 0; } m_nResult = 0; } return m_nResult; } int CSnmpClass::ParseEtype(std::string buf, std::string upAnddown) { //ERPS_STATE_CHANGED int m_nResult = 1; if ("ERPS_STATE_CHANGED" == buf) { std::string::size_type m_nindex = upAnddown.find("changed state to Protection"); if (m_nindex != upAnddown.npos) { BLOG_DEBUG("find changed state to Protection"); m_nErpsFlag = 1; m_nResult = 0; } else { std::string::size_type m_nindex_2 = upAnddown.find("changed state to Idle"); if (m_nindex_2 != upAnddown.npos) { //buff = buff.substr(0, m_nindex); BLOG_DEBUG("find changed state to Idle"); m_nErpsFlag = 0; m_nResult = 0; } } } return m_nResult; } int CSnmpClass::ParseBtype(std::string buf) { int m_nResult = 1; //BOARD_STATE_FAULT //BOARD_STATE_NORMAL if ("BOARD_STATE_FAULT" == buf) { m_nBoardFlag = 1; m_nResult = 0; } if ("BOARD_STATE_NORMAL" == buf) { m_nBoardFlag = 0; m_nResult = 0; } return m_nResult; } void CSnmpClass::MoxaParseBuffer(std::string buf, std::string comunnity) { //printf("RECV:%s\n", buf.c_str()); //std::string test = "{2022-03-23 13:52:51 192.168.12.253 [192.168.12.253] (via UDP: [192.168.1.82]:49990->[192.168.1.82]:162) TRAP, SNMP v1, community public \ // SNMPv2 - SMI::enterprises.8691.7.7 Enterprise Specific Trap(2) Uptime: 0 : 03 : 57.68 \ // SNMPv2 - SMI::enterprises.8691.7.7.2.2 = INTEGER : 3}"; if (CheckPower(buf, comunnity) || CheckResetPower(buf, comunnity) || CheckNetwork(buf, comunnity)) return; } void CSnmpClass::H3cParseBuffer(std::string buf, std::string comunnity) { //POWER_FAILED //POWER_RECOVERED //ERPS_STATE_CHANGED //PHY_UPDOWN //BOARD_STATE_FAULT //BOARD_STATE_NORMAL std::string m_sdata = "POWER_FAILED;POWER_RECOVERED;ERPS_STATE_CHANGED;PHY_UPDOWN;BOARD_STATE_FAULT;BOARD_STATE_NORMAL"; #if 1 std::string m_sResult = FindString(buf, m_sdata); #else std::string test1 = "2021-06-10 10:19:20 [UDP: [10.2.100.1]:10703->[10.1.100.99]:162]:DISMAN - EVENT - MIB::sysUpTimeInstance = Timeticks: (1295968167) 149 days, 23 : 54 : 41.67SNMPv2 - MIB::snmpTrapOID.0 = OID : SNMPv2 - SMI::mib - 2.192.0.1SNMPv2 - SMI::mib - 2.192.1.2.1.2.1143 = INTEGER : 23SNMPv2 - SMI::mib - 2.192.1.2.1.3.1143 = INTEGER : 5SNMPv2 - SMI::mib - 2.192.1.2.1.4.1143 = Gauge32 : 1SNMPv2 - SMI::mib - 2.192.1.2.1.5.1143 = Hex - STRING : 07 E5 06 0A 0A 11 2E 00 00 00 2B 08 00SNMPv2 - SMI::mib - 2.192.1.2.1.6.1143 = STRING: \"WVB-COM-CSW\"SNMPv2 - SMI::mib - 2.192.1.2.1.7.1143 = STRING : \"DEV\"SNMPv2 - SMI::mib - 2.192.1.2.1.8.1143 = STRING : \"-\"SNMPv2 - SMI::mib - 2.192.1.2.1.9.1143 = STRING : \"BOARD_REBOOT\"SNMPv2 - SMI::mib - 2.192.1.2.1.10.1143 = Gauge32 : 3SNMPv2 - SMI::mib - 2.192.1.2.1.11.1143 = STRING : \"Physical state on the interface Ten-GigabitEthernet1/2/0/29 changed to up.\"SNMPv2 - SMI::mib - 2.192.1.3.1.4.1143.1.12.83.121.115.76.111.99.64.50.53.53.48.54.7.67.104.97.115.115.105.115 = STRING : \"1\"SNMPv2 - SMI::mib - 2.192.1.3.1.4.1143.2.12.83.121.115.76.111.99.64.50.53.53.48.54.4.83.108.111.116 = STRING : \"0\"SNMPv2 - SMI::mib - 2.192.1.3.1.4.1143.3.12.83.121.115.76.111.99.64.50.53.53.48.54.3.77.68.67 = STRING : \"1\""; std::string m_sResult = FindString(m_sdata, test1); buf = test1; #endif int m_nFlag = 0; char m_cFirst = (m_sResult.c_str())[0]; switch (m_cFirst) { case 'P': m_nFlag = ParsePtype(m_sResult, buf); break; case 'E': m_nFlag = ParseEtype(m_sResult, buf); break; case 'B': m_nFlag = ParseBtype(m_sResult); break; default: m_nFlag = 1; break; } if (0 == m_nFlag) { printf("RECV:{%s}\n", m_sResult.c_str()); BLOG_DEBUG(fmt::format("RECV:{}", m_sResult)); BLOG_DEBUG(fmt::format("[comunnity::{}]m_nPowerFlag:{},m_nErpsFlag:{},m_nPhyFlag:{},m_nBoardFlag:{}", comunnity, m_nPowerFlag, m_nErpsFlag, m_nPhyFlag, m_nBoardFlag)); if (m_nPowerFlag || m_nErpsFlag || m_nPhyFlag || m_nBoardFlag) { SendStringH3c(1, comunnity, buf); } else { SendStringH3c(0, comunnity, buf); } } } void CSnmpClass::ParseBuffer(std::string buf, std::string comunnity) { OutputDebugStringA(fmt::format("RECV:{}", buf).c_str()); if (m_systemType == "moxa") MoxaParseBuffer(buf, comunnity); if (m_systemType == "h3c") H3cParseBuffer(buf, comunnity); } int CSnmpClass::RecvHandler(netsnmp_pdu* pdu, netsnmp_transport* transport, netsnmp_trapd_handler * handler) { #if 1 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" : "")); std::string m_sBuff = (char*)rbuf; BLOG_DEBUG(m_sBuff); // char* m_pCom = (char*)malloc(pdu->community_len + 1); memset(m_pCom,0, pdu->community_len + 1); memcpy(m_pCom, pdu->community, pdu->community_len); std::string Community = std::string(m_pCom); free(m_pCom); evpp::EventLoop* curr_loop = ((CSnmpClass*)m_pInstance)->m_pOolInvoker->GetNextLoop(); if (!curr_loop) { //BLOG_DEBUG(fmt::format("[FAIL] find an executive for AcknowledgeEntityStatusEX")); } else { curr_loop->RunInLoop(std::bind(&CSnmpClass::ReadProcess, (CSnmpClass*)m_pInstance, m_sBuff, Community)); } free(rbuf); #endif return NETSNMPTRAPD_HANDLER_OK; } int CSnmpClass::PrintHandler(netsnmp_pdu* pdu,netsnmp_transport* transport,netsnmp_trapd_handler * handler) { printf("print_handler\n"); //std::string m_sBuff = (char*)rbuf; #if 0 u_char *rbuf = NULL; size_t r_len = 64, o_len = 0; int trunc = 0; printf("print_handler\n"); 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" : "")); std::string bufftest = (char*)rbuf; //SnmptrapdMainLoop(); evpp::EventLoop* curr_loop = ((CSnmpClass*)m_pInstance)->m_pOolInvoker->GetNextLoop(); if (!curr_loop) { //BLOG_DEBUG(fmt::format("[FAIL] find an executive for AcknowledgeEntityStatusEX")); } else { curr_loop->RunInLoop(std::bind(&CSnmpClass::ReadProcess, (CSnmpClass*)m_pInstance, bufftest)); } free(rbuf); #endif return NETSNMPTRAPD_HANDLER_OK; } void CSnmpClass::ReadProcess(std::string buf, std::string comunnity) { //STRING: //INTEGER: m_sCommunity = comunnity; ParseBuffer(buf, comunnity); } void CSnmpClass::SnmptrapdMainLoop(void) { int count, numfds, block; fd_set readfds, writefds, exceptfds; struct timeval timeout; NETSNMP_SELECT_TIMEVAL timeout2; while (netsnmp_running) { numfds = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); block = 0; timerclear(&timeout); timeout.tv_sec = 5; snmp_select_info(&numfds, &readfds, &timeout, &block); #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_external_event_info(&numfds, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ timeout2.tv_sec = timeout.tv_sec; timeout2.tv_usec = timeout.tv_usec; count = select(numfds, &readfds, &writefds, &exceptfds, !block ? &timeout2 : NULL); if (count > 0) { #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_dispatch_external_events(&count, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ /* If there are any more events after external events, then * try SNMP events. */ if (count > 0) { snmp_read(&readfds); } } else { switch (count) { case 0: snmp_timeout(); break; case -1: if (errno == EINTR) continue; snmp_log_perror("select"); netsnmp_running = 0; break; default: fprintf(stderr, "select returned %d\n", count); netsnmp_running = 0; } } run_alarms(); } } /*******************************************************************-o-****** * main - Non Windows * SnmpTrapdMain - Windows to support windows service * * Parameters: * argc * *argv[] * * Returns: * 0 Always succeeds. (?) * * * Setup and start the trap receiver daemon. * * Also successfully EXITs with zero for some options. */ void CSnmpClass::InitNetsnmpTrapdAuth(void) { /* register our function as a authorization handler */ netsnmp_trapd_handler *traph; //RecvHandler //traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_AUTH_HANDLER,netsnmp_trapd_auth); traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_AUTH_HANDLER, RecvHandler); traph->authtypes = TRAP_AUTH_NONE; #ifdef USING_MIBII_VACM_CONF_MODULE /* register our configuration tokens for VACM configs */ init_vacm_config_tokens(); #endif /* register a config token for turning off the authorization entirely */ netsnmp_ds_register_config(ASN_BOOLEAN, "snmptrapd", "disableAuthorization", NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_NO_AUTHORIZATION); } int CSnmpClass::SnmpTrapdMain(int argc, char * argv[]) { static const char options[] = "aAc:CdD::efF:g:hHI:L:m:M:no:O:Ptu:vx:X-:""p:"; netsnmp_session *sess_list = NULL, *ss = NULL; netsnmp_transport *transport = NULL; int arg, i = 0; int uid = 0, gid = 0; int exit_code = 1; char *cp, *listen_ports = NULL; #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) int agentx_subagent = 1; #endif netsnmp_trapd_handler *traph; signal(SIGTERM,TermHandler); signal(SIGINT,TermHandler); /* * register our configuration handlers now so -H properly displays them */ snmptrapd_register_configs(); #ifdef NETSNMP_SECMOD_USM init_usm_conf("snmptrapd"); #endif /* NETSNMP_SECMOD_USM */ register_config_handler("snmptrapd", "snmpTrapdAddr", ParseTrapdAddress, FreeTrapdAddress, "string"); register_config_handler("snmptrapd", "doNotLogTraps", ParseConfigDoNotLogTraps, NULL, "(1|yes|true|0|no|false)"); register_config_handler("snmptrapd", "doNotFork", ParseConfigDoNotFork, NULL, "(1|yes|true|0|no|false)"); register_config_handler("snmptrapd", "ignoreAuthFailure", ParseConfigIgnoreAuthFailure, NULL, "(1|yes|true|0|no|false)"); register_config_handler("snmptrapd", "outputOption", ParseConfigOutputOption, NULL, "string"); register_config_handler("snmptrapd", "addForwarderInfo", ParseConfigAddForwarderInfo, NULL, "(1|yes|true|0|no|false)"); snmp_log_syslogname(m_pApp_name_long); /* * Now process options normally. */ #if 1 while ((arg = getopt(argc, argv, options)) != EOF) { switch (arg) { case 'c': if (optarg != NULL) { netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OPTIONALCONFIG, optarg); } else { return 1; } break; case 'C': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1); break; case 'd': netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DUMP_PACKET, 1); break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'f': m_nDofork = 0; break; case 'F': if (optarg != NULL) { if ((strncmp(optarg, "print", 5) == 0) || (strncmp(optarg, "syslog", 6) == 0) || (strncmp(optarg, "execute", 7) == 0)) { /* New style: "type=format" */ m_pTrap1_fmt_str_remember = strdup(optarg); cp = strchr(m_pTrap1_fmt_str_remember, '='); if (cp) *cp = ' '; } else { /* Old style: implicitly "print=format" */ m_pTrap1_fmt_str_remember = (char*)malloc(strlen(optarg) + 7); sprintf(m_pTrap1_fmt_str_remember, "print %s", optarg); } } else { return 1; } break; case 'L': if (snmp_log_options(optarg, argc, argv) < 0) { return 1; } break; } } #endif SOCK_STARTUP; /* * I'm being lazy here, and not checking the * return value from these registration calls. * Don't try this at home, children! */ if (0 == snmp_get_do_logging()) { traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, syslog_handler); traph->authtypes = TRAP_AUTH_LOG; snmp_enable_syslog(); } else { traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, PrintHandler); traph->authtypes = TRAP_AUTH_LOG; } #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) /* * we're an agentx subagent? */ if (agentx_subagent) { /* * make us a agentx client. */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); } #endif /* * don't fail if we can't do agentx (ie, socket not there, or not root) */ netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS); /* * ignore any warning messages. */ netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS); /* * initialize the agent library */ init_agent("snmptrapd"); #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) #ifdef NETSNMP_FEATURE_CHECKING netsnmp_feature_require(register_snmpEngine_scalars_context) #endif /* NETSNMP_FEATURE_CHECKING */ /* * initialize local modules */ if (agentx_subagent) { subagent_init(); #ifdef USING_SNMPV3_SNMPENGINE_MODULE /* * register scalars from SNMP-FRAMEWORK-MIB::snmpEngineID group; * allows engineID probes via the master agent under the * snmptrapd context */ register_snmpEngine_scalars_context("snmptrapd"); #endif } #endif /* USING_AGENTX_SUBAGENT_MODULE && !NETSNMP_SNMPTRAPD_DISABLE_AGENTX */ /* register our authorization handler */ InitNetsnmpTrapdAuth(); #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX) if (agentx_subagent) { #ifdef USING_SNMPV3_USMUSER_MODULE #ifdef NETSNMP_FEATURE_CHECKING netsnmp_feature_require(init_register_usmUser_context) #endif /* NETSNMP_FEATURE_CHECKING */ /* register ourselves as having a USM user database */ init_register_usmUser_context("snmptrapd"); #endif #ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE /* register net-snmp vacm extensions */ init_register_nsVacm_context("snmptrapd"); #endif #ifdef USING_TLSTM_MIB_SNMPTLSTMCERTTOTSNTABLE_MODULE init_snmpTlstmCertToTSNTable_context("snmptrapd"); #endif } #endif /* * Initialize the world. */ init_snmp("snmptrapd"); if (m_pTrap1_fmt_str_remember) { parse_format(NULL, m_pTrap1_fmt_str_remember); } if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) { /* * just starting up to process specific configuration and then * shutting down immediately. */ netsnmp_running = 0; } /* * if no logging options on command line or in conf files, use syslog */ if (0 == snmp_get_do_logging()) { snmp_enable_syslog_ident(m_pApp_name_long, LOG_DAEMON); } if (listen_ports) cp = listen_ports; else cp = m_pDefault_port; printf("%s\n", m_pDefault_port); while (cp != NULL) { char *sep = strchr(cp, ','); if (sep != NULL) { *sep = 0; } transport = netsnmp_transport_open_server("snmptrap", cp); if (transport == NULL) { snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n", cp, errno, strerror(errno)); SnmptrapdCloseSessions(sess_list); goto sock_cleanup; } else { ss = SnmptrapdAddSession(transport); if (ss == NULL) { /* * Shouldn't happen? We have already opened the transport * successfully so what could have gone wrong? */ SnmptrapdCloseSessions(sess_list); snmp_log(LOG_ERR, "couldn't open snmp - %s", strerror(errno)); goto sock_cleanup; } else { ss->next = sess_list; sess_list = ss; } } /* * Process next listen address, if there is one. */ if (sep != NULL) { *sep = ','; cp = sep + 1; } else { cp = NULL; } } SNMP_FREE(listen_ports); /* done with them */ #ifdef NETSNMP_USE_MYSQL if (netsnmp_mysql_init()) { fprintf(stderr, "MySQL initialization failed\n"); goto sock_cleanup; } #endif snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version()); #ifdef WIN32SERVICE m_nTrapd_status = SNMPTRAPD_RUNNING; #endif SnmptrapdMainLoop(); if (snmp_get_do_logging()) { struct tm *tm; time_t timer; time(&timer); tm = localtime(&timer); snmp_log(LOG_INFO, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.\n", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, netsnmp_get_version()); } snmp_log(LOG_INFO, "Stopping snmptrapd\n"); #ifdef NETSNMP_EMBEDDED_PERL shutdown_perl(); #endif SnmptrapdCloseSessions(sess_list); snmp_shutdown("snmptrapd"); #ifdef WIN32SERVICE m_nTrapd_status = SNMPTRAPD_STOPPED; #endif snmp_disable_log(); exit_code = 0; sock_cleanup: SOCK_CLEANUP; out: return exit_code; } void CSnmpClass::GetIdentity(std::string data) { //enterprises.8691.7.XXX.2对应着moxa的mib中的swTraps std::string buf = data; while(1) { std::string::size_type index = buf.find(","); if (index != std::string::npos) { /*std::string ff = buf.substr(0,index);*/ std::string tmp = buf.substr(0, index); tmp = "enterprises.8691.7." + tmp; m_identity.emplace_back(tmp); buf = buf.substr(index + 1); } else { if (buf != "") { buf = "enterprises.8691.7." + buf; m_identity.emplace_back(buf); } break; } } return; } bool CSnmpClass::LoadDeviceInfo() { char* text = NULL; FILE *pf = fopen("deveice.config", "rb+"); if (!pf) { printf("open deveice.config failed\n"); return false; } fseek(pf, 0, SEEK_END); long lSize = ftell(pf); text = (char*)malloc(lSize); rewind(pf); fread(text, sizeof(char), lSize, pf); std::string filedata = std::string(text, lSize); free(text); fclose(pf); nlohmann::json j = nlohmann::json::parse(filedata); std::string system = j["system"]; m_systemType = system; m_needTime = j["times"]; m_nMtime = j["interval"]; std::string receive_bind_ip = j["receive_bind_ip"]; std::string send_bind_ip = j["send_bind_ip"]; for (int i = 0; i < j["dst_ip"].size(); i++) { std::string dst_ip = j["dst_ip"][i]; m_dst_ip.emplace_back(dst_ip); } m_receive_bind_ip = receive_bind_ip; if (send_bind_ip != "") m_send_bind_ip = send_bind_ip; else m_send_bind_ip = "0.0.0.0"; memcpy(m_bindip, m_receive_bind_ip.c_str(), m_receive_bind_ip.size()); m_pDdefault_port = m_bindip; m_pDefault_port = m_pDdefault_port; std::string data = j["module-identity"]; GetIdentity(data); int sizeef = j["white_list"].size(); for (int i = 0; i < sizeef; i++) { DEVICEINFO* point = new DEVICEINFO; std::string srcIp = j["white_list"][i]["ip"]; std::string port = j["white_list"][i]["port_index"]; point->srcip = srcIp; point->port_index = port; m_pWhite_list.emplace_back(point); } return true; } bool CSnmpClass::FindIntegerOrSend(std::string src, std::string comunnity, std::string moduleIdentity, std::string power) { bool re = false; std::string::size_type index = src.find("INTEGER:"); if (index != std::string::npos) { int integer = std::stoi(src.substr(index + 8, src.size())); //printf("INTEGER=%d\n", integer); if (integer == 2) { OutputDebugStringA("Power Alarm"); SendString(1, comunnity, src, moduleIdentity, power); re = true; } if (integer == 3) { OutputDebugStringA("Power Alarm Clear"); SendString(0, comunnity, src, moduleIdentity, power); re = true; } } else { OutputDebugStringA("not find Power"); } return re; } bool CSnmpClass::CheckResetPower(std::string buf, std::string comunnity) { bool result = false; //std::string test = "SNMPv2-SMI::enterprises.8691.7.98 Cold Start Trap"; //buf = test; std::string::size_type index = buf.find("Cold Start Trap"); if (index != std::string::npos) { CSnmptrap* m_pTrap = new CSnmptrap; std::vector ::iterator iter = m_identity.begin(); for (; iter != m_identity.end(); iter++) { std::string::size_type index2 = buf.find(*iter); if (index2 != std::string::npos) { char custom[100] = ""; memcpy(custom, m_send_bind_ip.c_str(), m_send_bind_ip.size()); printf("%s,Reset sucess Alarm clear\n",(*iter).c_str()); std::vector::iterator iter2; for (iter2 = m_dst_ip.begin(); iter2 != m_dst_ip.end(); iter2++) { m_pTrap->SendTrap2(0, *iter2, comunnity, "KTT Alarm", *iter2, custom, m_needTime); BLOG_DEBUG(fmt::format("SendTrap:: ip:{},comunnity:{},KTT Alarm:{}", *iter2, comunnity, 0)); } /*m_pTrap->SendTrap2(0, m_dst_ip, comunnity, "KTT Alarm", *iter,custom, m_needTime);*/ m_Alarm.lock(); m_nAlarmStatus = 0; m_Alarm.unlock(); result = true; break; } } delete m_pTrap; } return result; } bool CSnmpClass::CheckPower(std::string buf, std::string comunnity) { bool result = false; //std::string test = "2022-03-23 13:52:51 192.168.12.253 [192.168.12.253] (via UDP: [192.168.1.82]:49990->[192.168.1.82]:162) TRAP, SNMP v1, community public \ // SNMPv2 - SMI::enterprises.8691.7.7 Enterprise Specific Trap(2) Uptime: 0 : 03 : 57.68 \ // SNMPv2 - SMI::enterprises.8691.7.7.2.2=INTEGER: 3"; //buf = test; std::vector ::iterator iter = m_identity.begin(); for (; iter != m_identity.end(); iter++) { //enterprises.8691.7.XXX.2对应着moxa的mib中的swTraps std::string power1 = (*iter) + ".2.2"; std::string power2 = (*iter) + ".2.3"; std::string::size_type index = buf.find(power1); if (index != std::string::npos) { OutputDebugStringA("power1"); result = FindIntegerOrSend(buf, comunnity, (*iter), power1); break; } index = buf.find(power2); if (index != std::string::npos) { OutputDebugStringA("power2"); result = FindIntegerOrSend(buf, comunnity, (*iter), power2); break; } } return result; } bool CSnmpClass::CheckPort_index(std::string src, std::string port_index) { bool result = false; std::string::size_type index2 = src.find("INTEGER:"); if (index2 != std::string::npos) { int integer = std::stoi(src.substr(index2 + 8, src.size())); char tmp[100] = ""; sprintf(tmp, "%d", integer); std::string::size_type index = port_index.find(std::string(tmp)); if (index != std::string::npos) { result = true; } } return result; } bool CSnmpClass::FindNetAlarm(std::string buf, std::string comunnity, std::string moduleIdentity) { bool result = false; int status = 2; std::string::size_type link = buf.find("Link Down Trap"); if (link != std::string::npos) { status = 1; } link = buf.find("Link Up Trap"); if (link != std::string::npos) { status = 0; } if (status == 2) return result; std::vector ::iterator iter = m_pWhite_list.begin(); for (; iter != m_pWhite_list.end(); iter++) { if ((*iter)->srcip == "") continue; std::string::size_type index = buf.find((*iter)->srcip); //没在白名单的ip地址数据直接发送snmp if (index == std::string::npos) { char custom[100] = ""; memcpy(custom, m_send_bind_ip.c_str(), m_send_bind_ip.size()); CSnmptrap* m_pTrap = new CSnmptrap; //printf("Link Alarm %d\n",status); OutputDebugStringA(fmt::format("Link Alarm {}", status).c_str()); std::vector::iterator iter2; for (iter2 = m_dst_ip.begin(); iter2 != m_dst_ip.end(); iter2++) { m_pTrap->SendTrap2(status, *iter2, comunnity, "KTT Alarm", moduleIdentity, custom, m_needTime); BLOG_DEBUG(fmt::format("SendTrap:: ip:{},comunnity:{},KTT Alarm:{}", *iter2, comunnity, status)); } /*m_pTrap->SendTrap2(status, m_dst_ip, comunnity, "KTT Alarm", moduleIdentity, custom, m_needTime);*/ result = true; m_Alarm.lock(); m_nAlarmStatus = status; m_Alarm.unlock(); delete m_pTrap; } else { //white_list处理忽略port CSnmptrap* m_pTrap = new CSnmptrap; if (!CheckPort_index(buf, (*iter)->port_index)) { char custom[100] = ""; memcpy(custom, m_send_bind_ip.c_str(), m_send_bind_ip.size()); m_Alarm.lock(); m_nAlarmStatus = status; m_Alarm.unlock(); printf("white_list Link Alarm %d\n",status); std::vector::iterator iter2; for (iter2 = m_dst_ip.begin(); iter2 != m_dst_ip.end(); iter2++) { m_pTrap->SendTrap2(status, *iter2, comunnity, "KTT Alarm", moduleIdentity, custom, m_needTime); BLOG_DEBUG(fmt::format("SendTrap:: ip:{},comunnity:{},KTT Alarm:{}", *iter2, comunnity, status)); } /*m_pTrap->SendTrap2(status, m_dst_ip, comunnity, "KTT Alarm", moduleIdentity,custom, m_needTime);*/ result = true; } else { printf("white_list port\n"); } delete m_pTrap; break; } } return result; } bool CSnmpClass::CheckNetwork(std::string buf, std::string comunnity) { bool result = false; //std::string test = "2022-03-23 14:04:21 192.168.12.253 [192.168.12.253] (via UDP: [192.168.1.82]:64451->[192.168.1.82]:162) TRAP, SNMP v1, community public \ // SNMPv2 - SMI::enterprises.8691.7.7 Link Down Trap(0) Uptime: 0 : 15 : 28.53 \ // IF - MIB::ifIndex.2 = INTEGER:3"; //buf = test; std::vector ::iterator iter = m_identity.begin(); for (; iter != m_identity.end(); iter++) { std::string::size_type identity = buf.find(*iter); if (identity != std::string::npos) { result = FindNetAlarm(buf,comunnity, *iter); break; } } return result; } int CSnmpClass::Init(std::string addr) { if (!LoadDeviceInfo()) return -1; Start(); BLOG_DEBUG("application start"); m_sDeviceIp = addr; m_pInstance = (void*)this; char* argv2[] = { "netsnmp_ALL.exe","-Lo" }; return SnmpTrapdMain(2, argv2); } /* * To stop Snmp Trap Receiver daemon * This portion is still not working */ void CSnmpClass::StopSnmpTrapd(void) { /* * Shut Down Service */ TermHandler(1); /* * Wait till trap receiver is completely stopped */ while (m_nTrapd_status != SNMPTRAPD_STOPPED) { Sleep(100); } }