agent_trap.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:49k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /* agent_trap.c: define trap generation routines for mib modules, etc,
  2.    to use */
  3. #include <config.h>
  4. #include <assert.h>
  5. #if HAVE_UNISTD_H
  6. #include <unistd.h>
  7. #endif
  8. #if HAVE_STDLIB_H
  9. #include <stdlib.h>
  10. #endif
  11. #if HAVE_STRING_H
  12. #include <string.h>
  13. #else
  14. #include <strings.h>
  15. #endif
  16. #if TIME_WITH_SYS_TIME
  17. # ifdef WIN32
  18. #  include <sys/timeb.h>
  19. # else
  20. #  include <time.h>
  21. # endif
  22. # include <time.h>
  23. #else
  24. # if HAVE_SYS_TIME_H
  25. #  include <sys/time.h>
  26. # else
  27. #  include <time.h>
  28. # endif
  29. #endif
  30. #ifdef OS_VXWORKS
  31. #include <sys/times.h>
  32. #endif
  33. #if HAVE_SYS_SOCKET_H
  34. #include <sys/socket.h>
  35. #elif HAVE_WINSOCK_H
  36. #include <ip/socket.h>
  37. #endif
  38. #if HAVE_NETINET_IN_H
  39. #include <netinet/in.h>
  40. #endif
  41. #include <ip/in.h>
  42. #include <ip/ip_var.h>
  43. #include <ip/ip_externs.h>
  44. #include <ip/inet.h>
  45. #include <libsys/timer.h>
  46. #ifdef OS_VXWORKS
  47. #include "asn1.h"
  48. #endif
  49. #include <snmplib/tools.h>
  50. #include <snmplib/snmpv3.h>
  51. #include "snmp_api.h"
  52. #include "snmp_impl.h"
  53. #include "snmp_client.h"
  54. #include "snmp.h"
  55. #include "system.h"
  56. #include "read_config.h"
  57. #include "snmp_debug.h"
  58. #include "system.h"
  59. #include "config_struct.h"
  60. #define SET_SNMP_TRAP_QUEUELEN 0
  61. #define SET_SNMP_TRAP_TIMEOUT 1
  62. #define SET_SNMP_TRAP_SOURCE 2
  63. #define SNMP_AUTH_TRAP 0x0001
  64. #define SNMP_CONFIG_TRAP 0x0002
  65. #define SNMP_SNMPTYPE_TRAP 0x0004
  66. extern oid default_enterprise[10];
  67. extern struct timeval starttime;
  68. struct trap_pdu_list {
  69. struct snmp_pdu  *pdu;
  70. struct trap_pdu_list *next;
  71. };
  72. struct trap_sink {
  73.     struct snmp_session *sesp;
  74.     struct trap_sink *next;
  75. struct trap_pdu_list *pduHead;
  76. int pduCount;
  77.     int pdutype;
  78.     int version;
  79. unsigned short trapflags;
  80. };
  81. struct trap_sink *sinks   = NULL;
  82. extern char *strdup(char*);
  83. extern void get_trapsrc_ip(unsigned long *ipaddr);
  84. #define OID_LENGTH(x)  (sizeof(x)/sizeof(x[0]))
  85. #ifndef SNMP_TRAP_PORT
  86. #define SNMP_TRAP_PORT 162
  87. #endif
  88. oid objid_enterprisetrap[] = { EXTENSIBLEMIB, 251 };
  89. /*oid version_id[]    = { EXTENSIBLEMIB, AGENTID, OSTYPE };*/
  90. oid version_id[]    = { EXTENSIBLEMIB, PRODUCEID};
  91. int enterprisetrap_len = OID_LENGTH( objid_enterprisetrap );
  92. int version_id_len     = OID_LENGTH( version_id );
  93. #define SNMPV2_TRAPS_PREFIX SNMP_OID_SNMPMODULES,1,1,5
  94. oid             trap_prefix[]    = { SNMPV2_TRAPS_PREFIX };
  95. oid  cold_start_oid[] = { SNMPV2_TRAPS_PREFIX, 1 }; /* SNMPv2-MIB */
  96. oid  warm_start_oid[] = { SNMPV2_TRAPS_PREFIX, 2 }; /* SNMPv2-MIB */
  97. oid  link_down_oid[] = { SNMPV2_TRAPS_PREFIX, 3 }; /* IF-MIB */
  98. oid  link_up_oid[] = { SNMPV2_TRAPS_PREFIX, 4 }; /* IF-MIB */
  99. oid  auth_fail_oid[] = { SNMPV2_TRAPS_PREFIX, 5 }; /* SNMPv2-MIB */
  100. oid  egp_xxx_oid[] = { SNMPV2_TRAPS_PREFIX, 99 }; /* ??? */
  101. #define SNMPV2_TRAP_OBJS_PREFIX SNMP_OID_SNMPMODULES,1,1,4
  102. oid  snmptrap_oid[]        = { SNMPV2_TRAP_OBJS_PREFIX, 1, 0 };
  103. oid  snmptrapenterprise_oid[] = { SNMPV2_TRAP_OBJS_PREFIX, 3, 0 };
  104. oid  sysuptime_oid[]        = { SNMP_OID_MIB2,1,3,0 };
  105. int  snmptrap_oid_len        = OID_LENGTH(snmptrap_oid);
  106. int  snmptrapenterprise_oid_len = OID_LENGTH(snmptrapenterprise_oid);
  107. int  sysuptime_oid_len        = OID_LENGTH(sysuptime_oid);
  108. static void free_trap_session (struct trap_sink *sp);
  109. #define SNMP_AUTHENTICATED_TRAPS_ENABLED 1
  110. #define SNMP_AUTHENTICATED_TRAPS_DISABLED 2
  111. extern void snmp_delete_targetAddr (char *host_name, char *community);
  112. extern void snmp_add_targetAddr (char *host_name, char *community, int timeout, int retry);
  113. extern void snmp_add_targetParam (char *host_name, char *community, int model, 
  114.    int secModel, char *secName, int secLevel);
  115. extern void snmp_delete_targetParam (char *host_name, char *community);
  116. int  snmp_enableauthentraps = SNMP_AUTHENTICATED_TRAPS_ENABLED;
  117. char *snmp_trapcommunity = NULL;
  118. int verbose;
  119. /* Prototypes */
  120.  /*
  121. static int create_v1_trap_session (const char *, u_short, const char *);
  122. static int create_v2_trap_session (const char *, u_short, const char *);
  123. static int create_v2_inform_session (const char *, u_short, const char *);
  124. static void free_trap_session (struct trap_sink *sp);
  125. static void send_v1_trap (struct snmp_session *, int, int);
  126. static void send_v2_trap (struct snmp_session *, int, int, int);
  127.  */
  128. void show_snmp_host (void)
  129. {
  130. struct trap_sink *trapsink;
  131. if (sinks == NULL)
  132. {
  133. vty_printf ("Nonen");
  134. vty_printf_end(1);
  135. return;
  136. }
  137. for(trapsink=sinks;trapsink!=NULL;trapsink=trapsink->next){
  138. vty_printf("Notification host: %s udp-port: 162 type: ", trapsink->sesp->peername);
  139. switch (trapsink->pdutype) {
  140. case SNMP_MSG_TRAP:
  141.     vty_printf("trapn");
  142.     break;
  143.     case SNMP_MSG_TRAP2:
  144.         vty_printf("trap version 2n");
  145.         break;
  146.         case SNMP_MSG_INFORM:
  147.             vty_printf("informn");
  148.             break;
  149.         default:
  150.             assert(0);
  151. }
  152. switch (trapsink->version) {
  153. case SNMP_VERSION_1:
  154.     vty_printf("community: %s    security model: v1nn", trapsink->sesp->community);
  155.     break;
  156. case SNMP_VERSION_2c:
  157.     vty_printf("community: %s    security model: v2cnn", trapsink->sesp->community);
  158.     break;
  159. case SNMP_VERSION_3:
  160.     vty_printf("user:      %s    security model: USMnn", trapsink->sesp->securityName);
  161.     break;
  162.     default:
  163.         assert(0);
  164. }
  165. }
  166. vty_printf_end(1);
  167. }
  168. int deleteTrapSessionNoRem (char *peer, char *community, int version, int pdutype, char *vrfname)
  169. {
  170. struct trap_sink *trapsink,*lasttrapsink;
  171. lasttrapsink=NULL;
  172. SNMP_DEBUG_ROUTINES("delete_v1_trap_session()");
  173. if (version == SNMP_VERSION_3) {
  174.      for(trapsink=sinks;trapsink!=NULL;trapsink=trapsink->next){
  175.      if(!strcmp(trapsink->sesp->peername,peer) && 
  176.      !strcmp (trapsink->sesp->securityName, community) &&
  177.                  trapsink->pdutype == pdutype &&
  178.                  trapsink->version == SNMP_VERSION_3 &&
  179.                  !strcmp(trapsink->sesp->vrfname, vrfname)){
  180.      break;
  181.      }
  182.      lasttrapsink=trapsink;
  183.      }
  184. }else{
  185.      for(trapsink=sinks;trapsink!=NULL;trapsink=trapsink->next){
  186.      if(!strcmp(trapsink->sesp->peername,peer) && 
  187.      !strcmp (trapsink->sesp->community, community) &&
  188.                  trapsink->pdutype == pdutype &&
  189.                  trapsink->version == version &&
  190.                  !strcmp(trapsink->sesp->vrfname, vrfname)){
  191.      break;
  192.      }
  193.      lasttrapsink=trapsink;
  194.      }
  195. }
  196. if(trapsink!=NULL){
  197. if(lasttrapsink){
  198. lasttrapsink->next=trapsink->next;
  199. }else{
  200. sinks=trapsink->next;
  201. }
  202. free_trap_session (trapsink);
  203. return 1;
  204. }
  205. return 0;
  206. }
  207. int deleteTrapSession(char *peer, char *community, int version, int pdutype, char *vrfname)
  208. {
  209. if (deleteTrapSessionNoRem (peer, community, version, pdutype, vrfname))
  210. {
  211. snmp_delete_targetAddr (peer, community);
  212. snmp_delete_targetParam (peer, community);
  213. #ifdef INCLUDE_SNMPV3
  214. if (version == SNMP_VERSION_3) {
  215.             snmpv3_dec_remote_engineID_reference(peer, SNMP_TRAP_PORT);
  216. }
  217. #endif /* INCLUDE_SNMPV3*/
  218. return 1;
  219. }
  220. return 0;
  221. }
  222. /*******************
  223.  *
  224.  * Trap session handling
  225.  *
  226.  *******************/
  227. int add_trap_session( struct snmp_session *ss, int pdutype, int version )
  228. {
  229.     struct trap_sink *new_sink =
  230.       (struct trap_sink *) malloc (sizeof (*new_sink));
  231.     if ( new_sink == NULL )
  232. return 0;
  233. new_sink->pduHead = NULL;
  234. new_sink->pduCount = 0;
  235.     new_sink->sesp    = ss;
  236.     new_sink->pdutype = pdutype;
  237.     new_sink->version = version;
  238.     new_sink->next    = sinks;
  239.     new_sink->trapflags = 0xFFFF;
  240.     sinks = new_sink;
  241.     return 1;
  242. }
  243. int createTrapSessionNoAdd (char *sink,char * com,int timeout,int queuelen,unsigned short trapflags, int version, int pdutype, char *vrfname)
  244. {
  245. struct snmp_session  session, *sesp;
  246. int return_val = 0;
  247. struct trap_sink *new_sink;
  248.     memset (&session, 0, sizeof (struct snmp_session));
  249.     session.peername = strdup(sink);
  250. if (session.peername == NULL)
  251. return 0;
  252.     session.version = version;
  253.     session.community = strdup (com);
  254. if (session.community == NULL)
  255. {
  256. free (session.peername);
  257. return 0;
  258. }
  259.     session.community_len = strlen (com);
  260.     session.remote_port = SNMP_TRAP_PORT;
  261. session.securityAuthProtoLen = 0;
  262. session.contextName = NULL;
  263. session.securityEngineID = NULL;
  264. session.securityName = NULL;
  265. session.securityAuthProto = NULL;
  266. session.securityPrivProto = NULL;
  267. strcpy(session.vrfname,vrfname);
  268. sesp = snmp_open (&session);
  269.     if (sesp) {
  270.     sesp->timeout=timeout*1000000L; 
  271. sesp->retries=queuelen;
  272. new_sink = (struct trap_sink *) malloc (sizeof (struct trap_sink));
  273. if ( new_sink == NULL )
  274. {
  275. snmp_close(sesp);
  276. return_val = 0;
  277. }
  278. else
  279. {
  280. return_val = 1;
  281. new_sink->pduHead = NULL;
  282. new_sink->pduCount = 0;
  283. new_sink->sesp    = sesp;
  284. new_sink->pdutype = pdutype;
  285. new_sink->version = version;
  286. new_sink->trapflags = trapflags;
  287. new_sink->next    = sinks;
  288. sinks = new_sink;
  289. }
  290.     }
  291. if (session.peername)
  292. free (session.peername);
  293. if (session.community)
  294. free (session.community);
  295.     /* diagnose snmp_open errors with the input struct snmp_session pointer */
  296. if (!return_val)
  297. {
  298. snmp_sess_perror("snmpd: create_trap_session", &session);
  299. }
  300. return return_val;
  301. }
  302. int createV1TrapSession (char *sink,char * com,unsigned short trapflags, char *vrfname)
  303. {
  304. int return_val;
  305. if ((return_val = createTrapSessionNoAdd (sink, com, snmp_para.timeout, snmp_para.queuelen, trapflags, SNMP_VERSION_1, SNMP_MSG_TRAP,vrfname)))
  306. {
  307. snmp_add_targetAddr (sink, com, 1500, 3);
  308. snmp_add_targetParam (sink, com, SNMP_MP_MODEL_SNMPv1, SNMP_SEC_MODEL_SNMPv1, com, 
  309. SNMP_SEC_LEVEL_NOAUTH);
  310. }
  311. return return_val;
  312. }
  313. int createV2TrapSession (char *sink,char * com,unsigned short trapflags, int pdutype,char *vrfname)
  314. {
  315. int return_val;
  316. if ((return_val = createTrapSessionNoAdd (sink, com, snmp_para.timeout, snmp_para.queuelen, trapflags, SNMP_VERSION_2c, pdutype,vrfname)))
  317. {
  318. snmp_add_targetAddr (sink, com, 1500, 3);
  319. snmp_add_targetParam (sink, com, SNMP_MP_MODEL_SNMPv2c, SNMP_SEC_MODEL_SNMPv2c, com, 
  320. SNMP_SEC_LEVEL_NOAUTH);
  321. }
  322. return return_val;
  323. }
  324. #ifdef INCLUDE_SNMPV3
  325. /*Sunxi added, 26 Feb, 2004*/
  326. int createV3TrapSession(char *sink,char * user, int authtype, int pdutype, unsigned short trapflags,char*vrfname)
  327. {
  328.     struct snmp_session  session, *sesp;
  329.     char *engineid;
  330.     memset (&session, 0, sizeof (struct snmp_session));
  331.     session.peername = sink;
  332.     session.version = SNMP_VERSION_3;
  333.     session.community = NULL;
  334.     session.community_len = 0;
  335.     /* by yangyuhua 2006-4-7*/
  336.     strcpy(session.vrfname, vrfname);
  337.     session.remote_port = SNMP_TRAP_PORT;
  338.     engineid = snmpv3_get_remote_engineID(sink, SNMP_TRAP_PORT);
  339.     if (engineid != NULL) {
  340.         snmp_memdup(&session.contextEngineID, engineid, SNMP_MAX_ENG_SIZE);
  341.         snmp_memdup(&session.securityEngineID, engineid, SNMP_MAX_ENG_SIZE);
  342.         session.contextEngineIDLen = SNMP_MAX_ENG_SIZE;
  343.         session.securityEngineIDLen = SNMP_MAX_ENG_SIZE;
  344.     } else {
  345.         vty_output("%%Error: No snmpEngineID configured for remote host %s port %dn", sink, SNMP_TRAP_PORT);
  346.         return -1;
  347.     }
  348.     session.securityName = strdup(user);
  349.     session.securityNameLen = strlen(user);
  350.     session.securityModel = SNMP_SEC_MODEL_USM;
  351.     session.securityLevel = authtype;
  352.     session.timeout = snmp_para.timeout * 1000000L;
  353.     session.retries = SNMP_DEFAULT_RETRIES;
  354.     sesp = snmp_open (&session);
  355.     if (sesp) {
  356. snmp_add_targetAddr (sink, user, 1500, 3);
  357. snmp_add_targetParam (sink, user, SNMP_MP_MODEL_SNMPv3, SNMP_SEC_MODEL_USM, user, authtype);
  358. snmpv3_inc_remote_engineID_reference(sink, SNMP_TRAP_PORT);
  359.      return( add_trap_session( sesp, pdutype, SNMP_VERSION_3 ));
  360.     }
  361.     /* diagnose snmp_open errors with the input struct snmp_session pointer */
  362.     snmp_sess_perror("snmpd: createV3TrapSession", &session);
  363.     return 0;
  364. }
  365. int destroyV3TrapSession(char *sink, char *user, int pdutype)
  366. {
  367. struct trap_sink *trapsink,*lasttrapsink;
  368. lasttrapsink=NULL;
  369. SNMP_DEBUG_ROUTINES("destroyV3TrapSession()");
  370. for(trapsink=sinks;trapsink!=NULL;trapsink=trapsink->next){
  371. if(!strcmp(trapsink->sesp->peername,sink) && 
  372. !strcmp (trapsink->sesp->securityName, user) && 
  373. trapsink->pdutype == pdutype &&
  374. trapsink->version == SNMP_VERSION_3){
  375. /*found it !!!*/
  376. break;
  377. }
  378. lasttrapsink=trapsink;
  379. }
  380. if(trapsink!=NULL){
  381. if(lasttrapsink){
  382. lasttrapsink->next=trapsink->next;
  383. }else{
  384. sinks=trapsink->next;
  385. }
  386. /*They will be freed in snmp_close --sxf 2k-12-27
  387. if (trapsink->sesp->peername != NULL)
  388. sys_mem_free (trapsink->sesp->peername);
  389. if (trapsink->sesp->community != NULL)
  390. sys_mem_free (trapsink->sesp->community);
  391. */
  392. free_trap_session (trapsink);
  393. snmp_delete_targetAddr (sink, user);
  394. snmp_delete_targetParam (sink, user);
  395. snmpv3_dec_remote_engineID_reference(sink, SNMP_TRAP_PORT);
  396. return 1;
  397. }
  398. return 0;
  399. }
  400. int refreshV3TrapSession(char *sink, char *engineID, size_t engineIDLen)
  401. {
  402. struct trap_sink *trapsink,*lasttrapsink;
  403. lasttrapsink=NULL;
  404. SNMP_DEBUG_ROUTINES("refreshV3TrapSession()");
  405. for(trapsink=sinks;trapsink!=NULL;trapsink=trapsink->next){
  406. if(!strcmp(trapsink->sesp->peername,sink) && 
  407. trapsink->version == SNMP_VERSION_3){
  408. /*found it !!!*/
  409.             SNMP_FREE(trapsink->sesp->contextEngineID);
  410.             SNMP_FREE(trapsink->sesp->securityEngineID);
  411.             snmp_memdup((u_char**)(&trapsink->sesp->contextEngineID), engineID, SNMP_MAX_ENG_SIZE);
  412.             snmp_memdup((u_char**)(&trapsink->sesp->securityEngineID), engineID, SNMP_MAX_ENG_SIZE);/*by yangyuhua 2005-12-6*/
  413.             trapsink->sesp->contextEngineIDLen = SNMP_MAX_ENG_SIZE;
  414.             trapsink->sesp->securityEngineIDLen = SNMP_MAX_ENG_SIZE;
  415. }
  416. lasttrapsink=trapsink;
  417. }
  418. return 0;
  419. }
  420. /*end add*/
  421. #endif /*INCLUDE_SNMPV3*/
  422. int create_trap_session (char *sink, u_short sinkport,
  423. char *com,
  424. int version, int pdutype)
  425. {
  426.     struct snmp_session  session, *sesp;
  427.     memset (&session, 0, sizeof (struct snmp_session));
  428.     session.peername = sink;
  429.     session.version = version;
  430.     if (com) {
  431.         session.community = (u_char *)com;
  432.         session.community_len = strlen (com);
  433.     }
  434.     session.remote_port = sinkport;
  435.     sesp = snmp_open (&session);
  436.     if (sesp) {
  437. return( add_trap_session( sesp, pdutype, version ));
  438.     }
  439.     /* diagnose snmp_open errors with the input struct snmp_session pointer */
  440.     snmp_sess_perror("snmpd: create_trap_session", &session);
  441.     return 0;
  442. }
  443. static int create_v1_trap_session (char *sink, u_short sinkport,
  444.    char *com)
  445. {
  446.     return create_trap_session( sink, sinkport, com,
  447. SNMP_VERSION_1, SNMP_MSG_TRAP );
  448. }
  449. static int create_v2_trap_session (char *sink,  u_short sinkport,
  450.    char *com)
  451. {
  452.     return create_trap_session( sink, sinkport, com,
  453. SNMP_VERSION_2c, SNMP_MSG_TRAP2 );
  454. }
  455. static int create_v2_inform_session (char *sink,  u_short sinkport,
  456.      char *com)
  457. {
  458.     return create_trap_session( sink, sinkport, com,
  459. SNMP_VERSION_2c, SNMP_MSG_INFORM );
  460. }
  461. static void free_trap_session (struct trap_sink *sp)
  462. {
  463.     snmp_close(sp->sesp);
  464.     free (sp);
  465. }
  466. void snmpd_free_trapsinks (void)
  467. {
  468.     struct trap_sink *sp = sinks;
  469.     while (sp) {
  470. sinks = sinks->next;
  471. free_trap_session(sp);
  472. sp = sinks;
  473.     }
  474. }
  475. /*******************
  476.  *
  477.  * Trap handling
  478.  *
  479.  *******************/
  480. #if 0
  481. void send_enterprise_trap_vars (int trap, 
  482.      int specific,
  483.      oid *enterprise, int enterprise_length,
  484.      struct variable_list *vars)
  485. {
  486.     struct variable_list uptime_var, snmptrap_var, enterprise_var;
  487.     struct variable_list *v2_vars, *last_var;
  488.     struct snmp_pdu *template_pdu, *pdu=NULL;
  489.     struct timeval  now;
  490.     long uptime;
  491.     struct soaddr_in *pduIp;
  492.     struct trap_sink *sink;
  493.     oid temp_oid[MAX_OID_LEN];
  494.     u_long addr;
  495. /*
  496.  * Initialise SNMPv2 required variables
  497.  */
  498.     gettimeofday(&now, NULL);
  499.     uptime = calculate_time_diff(&now, &starttime);
  500.     memset (&uptime_var, 0, sizeof (struct variable_list));
  501.     snmp_set_var_objid( &uptime_var, sysuptime_oid, OID_LENGTH(sysuptime_oid));
  502.     snmp_set_var_value( &uptime_var, (u_char *)&uptime, sizeof(uptime) );
  503.     uptime_var.type           = ASN_TIMETICKS;
  504.     uptime_var.next_variable  = &snmptrap_var;
  505.     memset (&snmptrap_var, 0, sizeof (struct variable_list));
  506.     snmp_set_var_objid( &snmptrap_var, snmptrap_oid, OID_LENGTH(snmptrap_oid));
  507. /* value set later .... */
  508.     snmptrap_var.type           = ASN_OBJECT_ID;
  509.     if ( vars )
  510. snmptrap_var.next_variable  = vars;
  511.     else
  512. snmptrap_var.next_variable  = &enterprise_var;
  513. /* find end of provided varbind list,
  514.    ready to append the enterprise info if necessary */
  515.     last_var = vars;
  516.     while ( last_var && last_var->next_variable )
  517. last_var = last_var->next_variable;
  518.     memset (&enterprise_var, 0, sizeof (struct variable_list));
  519.     snmp_set_var_objid( &enterprise_var,
  520.  snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid));
  521.     snmp_set_var_value( &enterprise_var, (u_char *)enterprise, enterprise_length*sizeof(oid));
  522.     enterprise_var.type           = ASN_OBJECT_ID;
  523.     enterprise_var.next_variable  = NULL;
  524.     v2_vars = &uptime_var;
  525. /*
  526.  *  Create a template PDU, ready for sending
  527.  */
  528.     template_pdu = snmp_pdu_create( SNMP_MSG_TRAP );
  529.     if ( template_pdu == NULL )
  530.      {
  531.       if ( vars ) snmp_free_var(&enterprise_var);
  532. snmp_free_varbind(v2_vars);
  533. return;
  534.      }
  535.     template_pdu->trap_type     = trap;
  536.     template_pdu->specific_type = specific;
  537.     if ( snmp_clone_mem((void **)&template_pdu->enterprise,
  538. enterprise, enterprise_length*sizeof(oid))) {
  539. snmp_free_pdu( template_pdu );
  540. if ( vars ) snmp_free_varbind(&enterprise_var);
  541. snmp_free_varbind(v2_vars);
  542. return;
  543.     }
  544.     template_pdu->enterprise_length = enterprise_length;
  545.     template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;
  546.     pduIp = (struct soaddr_in *)&template_pdu->agent_addr;
  547.     pduIp->sin_family  = AF_INET;
  548. get_trapsrc_ip(&addr);
  549. if(addr)
  550. pduIp->sin_addr.s_addr = addr;
  551. else
  552. pduIp->sin_addr.s_addr = get_myaddr();
  553.     template_pdu->time    = uptime;
  554. /*
  555.  *  Now use the parameters to determine
  556.  *    which v2 variables are needed,
  557.  *    and what values they should take.
  558.  */
  559.     switch ( trap ) {
  560. case -1: /*
  561.  * SNMPv2 only
  562.  *  Check to see whether the variables provided
  563.  *    are sufficient for SNMPv2 notifications
  564.  */
  565. if (vars && snmp_oid_compare(vars->name, vars->name_length,
  566. sysuptime_oid, OID_LENGTH(sysuptime_oid)) == 0 )
  567. v2_vars = vars;
  568. else
  569. if (vars && snmp_oid_compare(vars->name, vars->name_length,
  570. snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0 )
  571. uptime_var.next_variable = vars;
  572. else {
  573. /* Hmmm... we don't seem to have a value - oops! */
  574. snmptrap_var.next_variable = vars;
  575. }
  576. last_var = NULL; /* Don't need enterprise info */
  577. break;
  578. /* "Standard" SNMPv1 traps */
  579. case SNMP_TRAP_COLDSTART:
  580. snmp_set_var_value( &snmptrap_var,
  581.     (u_char *)cold_start_oid,
  582.     sizeof(cold_start_oid));
  583. break;
  584. case SNMP_TRAP_WARMSTART:
  585. snmp_set_var_value( &snmptrap_var,
  586.     (u_char *)warm_start_oid,
  587.     sizeof(warm_start_oid));
  588. break;
  589. case SNMP_TRAP_LINKDOWN:
  590. snmp_set_var_value( &snmptrap_var,
  591.     (u_char *)link_down_oid,
  592.     sizeof(link_down_oid));
  593. break;
  594. case SNMP_TRAP_LINKUP:
  595. snmp_set_var_value( &snmptrap_var,
  596.     (u_char *)link_up_oid,
  597.     sizeof(link_up_oid));
  598. break;
  599. case SNMP_TRAP_AUTHFAIL:
  600. if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED)
  601. {
  602. snmp_free_pdu( template_pdu );
  603. snmp_free_varbind(v2_vars);
  604.     return;
  605. }
  606. snmp_set_var_value( &snmptrap_var,
  607.     (u_char *)auth_fail_oid,
  608.     sizeof(auth_fail_oid));
  609. break;
  610. case SNMP_TRAP_EGPNEIGHBORLOSS:
  611. snmp_set_var_value( &snmptrap_var,
  612.     (u_char *)egp_xxx_oid,
  613.     sizeof(egp_xxx_oid));
  614. break;
  615. case SNMP_TRAP_ENTERPRISESPECIFIC:
  616. memcpy( &temp_oid,
  617.     (char *)enterprise,
  618.     (enterprise_length)*sizeof(oid));
  619. temp_oid[ enterprise_length   ] = 0;
  620. temp_oid[ enterprise_length+1 ] = specific;
  621. snmp_set_var_value( &snmptrap_var,
  622.     (u_char *)&temp_oid,
  623.     (enterprise_length+2)*sizeof(oid));
  624. snmptrap_var.next_variable  = vars;
  625. last_var = NULL; /* Don't need version info */
  626. break;
  627.     }
  628.     
  629. /*
  630.  *  Now loop through the list of trap sinks,
  631.  *   sending an appropriately formatted PDU to each
  632.  */
  633. for ( sink = sinks ; sink ; sink=sink->next ) 
  634. {
  635. BOOL bContinue;
  636. if ( sink->version == SNMP_VERSION_1 && trap == -1 )
  637. continue; /* Skip v1 sinks for v2 only traps */
  638. bContinue = TRUE;
  639. switch ( trap )
  640. {
  641. case SNMP_TRAP_COLDSTART:
  642. case SNMP_TRAP_WARMSTART:
  643. case SNMP_TRAP_LINKDOWN:
  644. case SNMP_TRAP_LINKUP:
  645. if(sink->trapflags&SNMP_SNMPTYPE_TRAP)
  646. bContinue = FALSE;
  647. break;
  648. case SNMP_TRAP_AUTHFAIL:
  649. if(sink->trapflags&SNMP_AUTH_TRAP)
  650. bContinue = FALSE;
  651. break;
  652. default:
  653. bContinue = FALSE;
  654. break;
  655. }
  656. if (bContinue)
  657. continue;
  658. template_pdu->version = sink->version;
  659. template_pdu->command = sink->pdutype;
  660. if ( sink->version != SNMP_VERSION_1 )
  661. {
  662. template_pdu->variables = v2_vars;
  663. if ( last_var )
  664. last_var->next_variable = &enterprise_var;
  665. }
  666. else
  667. template_pdu->variables = vars;
  668. pdu = snmp_clone_pdu( template_pdu );
  669. if (pdu == NULL)
  670. continue;
  671. if (!addr)
  672. {
  673. IP_ADDR dest_addr, src_addr;
  674. if (sink->sesp->peername != NULL)
  675. {
  676. dest_addr = inet_addr (sink->sesp->peername);
  677. if (ipof_iffordest(dest_addr, &src_addr) == 0) /*success*/
  678. {
  679. pduIp = (struct soaddr_in *)&pdu->agent_addr;
  680. pduIp->sin_family  = AF_INET;
  681. pduIp->sin_addr.s_addr = src_addr;
  682. }
  683. }
  684. }
  685. pdu->sessid = sink->sesp->sessid; /* AgentX only ? */
  686. if ( snmp_send( sink->sesp, pdu) == 0 ) 
  687. {
  688. if (sink->sesp->s_snmp_errno == SNMPERR_BAD_SENDTO)
  689. {
  690. if (sink->pduCount+1 < snmp_para.queuelen)
  691. {
  692. struct trap_pdu_list *pPduList, *pTemp;
  693. pPduList = (struct trap_pdu_list *) malloc (sizeof (struct trap_pdu_list));
  694. if (pPduList == NULL)
  695. {
  696. snmp_sess_perror ("snmpd: send_trap", sink->sesp);
  697. snmp_free_pdu( pdu );
  698. }
  699. pPduList->pdu = pdu;
  700. if (sink->pduHead == NULL)
  701. {
  702. pPduList->next = NULL;
  703. sink->pduHead = pPduList;
  704. }
  705. else
  706. {
  707. for (pTemp = sink->pduHead; pTemp->next != NULL; pTemp = pTemp->next)
  708. ;
  709. pTemp->next = pPduList;
  710. pPduList->next = NULL;
  711. }
  712. sink->pduCount++;
  713. }
  714. }
  715. else
  716. {
  717. snmp_sess_perror ("snmpd: send_trap", sink->sesp);
  718. snmp_free_pdu( pdu );
  719. }
  720. }
  721. else 
  722. {
  723. snmp_increment_statistic(STAT_SNMPOUTTRAPS);
  724. snmp_increment_statistic(STAT_SNMPOUTPKTS);
  725. }
  726. if ( sink->version != SNMP_VERSION_1 && last_var )
  727. last_var->next_variable = NULL;
  728. }
  729. /* Ensure we don't free anything we shouldn't */
  730.     if ( last_var )
  731. last_var->next_variable = NULL;
  732.   /*  template_pdu->variables = NULL;*/
  733.     snmp_free_pdu( template_pdu );
  734.     snmp_free_pdu( pdu );
  735. }
  736. #else
  737. struct variable_list *
  738. find_varbind_in_list( struct variable_list *vblist,
  739.                       oid *name, size_t len)
  740. {
  741.     struct variable_list  *v;
  742.     for (v=vblist; v; v=v->next_variable)
  743.         if (!snmp_oid_compare(v->name, v->name_length,
  744.                               name,    len))
  745.             return v;
  746.     return NULL;
  747. }
  748. static struct variable_list *
  749. _copy_varlist(struct variable_list *var,      /* source varList */
  750.               int errindex,     /* index of variable to drop (if any) */
  751.               int copy_count)
  752. {                               /* !=0 number variables to copy */
  753.     struct variable_list *newhead, *newvar, *oldvar;
  754.     int             ii = 0;
  755.     newhead = NULL;
  756.     oldvar = NULL;
  757.     while (var && (copy_count-- > 0)) {
  758.         /*
  759.          * Drop the specified variable (if applicable) 
  760.          */
  761.         if (++ii == errindex) {
  762.             var = var->next_variable;
  763.             continue;
  764.         }
  765.         /*
  766.          * clone the next variable. Cleanup if alloc fails 
  767.          */
  768.         newvar = (struct variable_list *)
  769.             malloc(sizeof(struct variable_list));
  770.         if (snmp_clone_var(var, newvar)) {
  771.             if (newvar)
  772.                 free((char *) newvar);
  773.             snmp_free_varbind(newhead);
  774.             return 0;
  775.         }
  776.         /*
  777.          * add cloned variable to new list  
  778.          */
  779.         if (0 == newhead)
  780.             newhead = newvar;
  781.         if (oldvar)
  782.             oldvar->next_variable = newvar;
  783.         oldvar = newvar;
  784.         var = var->next_variable;
  785.     }
  786.     return newhead;
  787. }
  788. struct variable_list *
  789. snmp_clone_varbind(struct variable_list * varlist)
  790. {
  791.     return _copy_varlist(varlist, 0, 10000);    /* skip none, copy all */
  792. }
  793. struct snmp_pdu*
  794. convert_v2pdu_to_v1( struct snmp_pdu* template_v2pdu )
  795. {
  796.     struct snmp_pdu           *template_v1pdu;
  797.     struct variable_list *first_vb, *vblist;
  798.     struct variable_list *var;
  799.     size_t                 len;
  800.     /*
  801.      * Make a copy of the v2 Trap PDU
  802.      *   before starting to convert this
  803.      *   into a v1 Trap PDU.
  804.      */
  805.     template_v1pdu = snmp_clone_pdu( template_v2pdu);
  806.     if (!template_v1pdu) {
  807.         return NULL;
  808.     }
  809.     template_v1pdu->command = SNMP_MSG_TRAP;
  810.     first_vb = template_v1pdu->variables;
  811.     vblist   = template_v1pdu->variables;
  812.     /*
  813.      * The first varbind should be the system uptime.
  814.      */
  815.     if (!vblist ||
  816.         snmp_oid_compare(vblist->name,  vblist->name_length,
  817.                          sysuptime_oid, sysuptime_oid_len)) {
  818.         snmp_free_pdu(template_v1pdu);
  819.         return NULL;
  820.     }
  821.     template_v1pdu->time = *vblist->val.integer;
  822.     vblist = vblist->next_variable;
  823.             
  824.     /*
  825.      * The second varbind should be the snmpTrapOID.
  826.      */
  827.     if (!vblist ||
  828.         snmp_oid_compare(vblist->name, vblist->name_length,
  829.                          snmptrap_oid, snmptrap_oid_len)) {
  830.         snmp_free_pdu(template_v1pdu);
  831.         return NULL;
  832.     }
  833.     /*
  834.      * Set the generic & specific trap types,
  835.      *    and the enterprise field from the v2 varbind list.
  836.      * If there's an agentIPAddress varbind, set the agent_addr too
  837.      */
  838.     if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
  839.                           trap_prefix,       OID_LENGTH(trap_prefix))) {
  840.         /*
  841.          * For 'standard' traps, extract the generic trap type
  842.          *   from the snmpTrapOID value, and take the enterprise
  843.          *   value from the 'snmpEnterprise' varbind.
  844.          */
  845.         template_v1pdu->trap_type =
  846.             vblist->val.objid[OID_LENGTH(trap_prefix)] - 1;
  847.         template_v1pdu->specific_type = 0;
  848.         var = find_varbind_in_list( vblist,
  849.                              snmptrapenterprise_oid,
  850.                              snmptrapenterprise_oid_len);
  851.         if (var) {
  852.             snmp_memdup((u_char**)&template_v1pdu->enterprise,
  853.                    (const u_char*)var->val.objid, var->val_len);
  854.             template_v1pdu->enterprise_length = var->val_len/sizeof(oid);
  855.         } else {
  856.             template_v1pdu->enterprise        = NULL;
  857.             template_v1pdu->enterprise_length = 0; /* XXX ??? */
  858.         }
  859.     } else {
  860.         /*
  861.          * For enterprise-specific traps, split the snmpTrapOID value
  862.          *   into enterprise and specific trap
  863.          */
  864.         len = vblist->val_len / sizeof(oid);
  865.         template_v1pdu->trap_type     = SNMP_TRAP_ENTERPRISESPECIFIC;
  866.         template_v1pdu->specific_type = vblist->val.objid[len - 1];
  867.         len--;
  868.         if (vblist->val.objid[len-1] == 0)
  869.             len--;
  870.         SNMP_FREE(template_v1pdu->enterprise);
  871.         snmp_memdup((u_char**)&template_v1pdu->enterprise,
  872.                (u_char *)vblist->val.objid, len*sizeof(oid));
  873.         template_v1pdu->enterprise_length = len;
  874.     }
  875. #if 0
  876.     var = find_varbind_in_list( vblist, agentaddr_oid,
  877.                                         agentaddr_oid_len);
  878.     if (var) {
  879.         memcpy(template_v1pdu->agent_addr,
  880.                var->val.string, 4);
  881.     }
  882. #endif
  883.     /*
  884.      * The remainder of the v2 varbind list is kept
  885.      * as the v2 varbind list.  Update the PDU and
  886.      * free the two redundant varbinds.
  887.      */
  888.     template_v1pdu->variables = vblist->next_variable;
  889.     vblist->next_variable = NULL;
  890.     snmp_free_varbind( first_vb );
  891.             
  892.     return template_v1pdu;
  893. }
  894. struct snmp_pdu*
  895. convert_v1pdu_to_v2( struct snmp_pdu* template_v1pdu )
  896. {
  897.     struct snmp_pdu           *template_v2pdu;
  898.     struct variable_list *first_vb;
  899.     struct variable_list *var;
  900.     oid                    enterprise[MAX_OID_LEN];
  901.     size_t                 enterprise_len;
  902.     /*
  903.      * Make a copy of the v1 Trap PDU
  904.      *   before starting to convert this
  905.      *   into a v2 Trap PDU.
  906.      */
  907.     template_v2pdu = snmp_clone_pdu( template_v1pdu);
  908.     if (!template_v2pdu) {
  909.         return NULL;
  910.     }
  911.     template_v2pdu->command = SNMP_MSG_TRAP2;
  912.     first_vb = template_v2pdu->variables;
  913.     /*
  914.      * Insert an snmpTrapOID varbind before the original v1 varbind list
  915.      *   either using one of the standard defined trap OIDs,
  916.      *   or constructing this from the PDU enterprise & specific trap fields
  917.      */
  918.     if (template_v1pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
  919.         memcpy(enterprise, template_v1pdu->enterprise,
  920.                            template_v1pdu->enterprise_length*sizeof(oid));
  921.         enterprise_len               = template_v1pdu->enterprise_length;
  922.         enterprise[enterprise_len++] = 0;
  923.         enterprise[enterprise_len++] = template_v1pdu->specific_type;
  924.     } else {
  925.         memcpy(enterprise, cold_start_oid, sizeof(cold_start_oid));
  926. enterprise[9]  = template_v1pdu->trap_type+1;
  927.         enterprise_len = sizeof(cold_start_oid)/sizeof(oid);
  928.     }
  929.     var = NULL;
  930.     if (!snmp_varlist_add_variable( &var,
  931.              snmptrap_oid, snmptrap_oid_len,
  932.              ASN_OBJECT_ID,
  933.              (u_char*)enterprise, enterprise_len*sizeof(oid))) {
  934.         snmp_free_pdu(template_v2pdu);
  935.         return NULL;
  936.     }
  937.     var->next_variable        = template_v2pdu->variables;
  938.     template_v2pdu->variables = var;
  939.     /*
  940.      * Insert a sysUptime varbind at the head of the v2 varbind list
  941.      */
  942.     var = NULL;
  943.     if (!snmp_varlist_add_variable( &var,
  944.              sysuptime_oid, sysuptime_oid_len,
  945.              ASN_TIMETICKS,
  946.              (u_char*)&(template_v1pdu->time), 
  947.              sizeof(template_v1pdu->time))) {
  948.         snmp_free_pdu(template_v2pdu);
  949.         return NULL;
  950.     }
  951.     var->next_variable        = template_v2pdu->variables;
  952.     template_v2pdu->variables = var;
  953.     /*
  954.      * Append the other three conversion varbinds,
  955.      *  (snmpTrapAgentAddr, snmpTrapCommunity & snmpTrapEnterprise)
  956.      *  if they're not already present.
  957.      *  But don't bomb out completely if there are problems.
  958.      */
  959.      #if 0
  960.     var = find_varbind_in_list( template_v2pdu->variables,
  961.                                 agentaddr_oid, agentaddr_oid_len);
  962.     if (!var && template_v1pdu->agent_addr[0]
  963.              && template_v1pdu->agent_addr[1]
  964.              && template_v1pdu->agent_addr[2]
  965.              && template_v1pdu->agent_addr[3]) {
  966.         if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
  967.                  agentaddr_oid, agentaddr_oid_len,
  968.                  ASN_IPADDRESS,
  969.                  (u_char*)&(template_v1pdu->agent_addr), 
  970.                  sizeof(template_v1pdu->agent_addr)))
  971.             snmp_log(LOG_WARNING,
  972.                  "send_trap: failed to append snmpTrapAddr varbindn");
  973.     }
  974.     var = find_varbind_in_list( template_v2pdu->variables,
  975.                                 community_oid, community_oid_len);
  976.     if (!var && template_v1pdu->community) {
  977.         if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
  978.                  community_oid, community_oid_len,
  979.                  ASN_OCTET_STR,
  980.                  template_v1pdu->community, 
  981.                  strlen(template_v1pdu->community)))
  982.             snmp_log(LOG_WARNING,
  983.                  "send_trap: failed to append snmpTrapCommunity varbindn");
  984.     }
  985.    #endif
  986.     var = find_varbind_in_list( template_v2pdu->variables,
  987.                                 snmptrapenterprise_oid,
  988.                                 snmptrapenterprise_oid_len);
  989.     if (!var && 
  990.         template_v1pdu->trap_type != SNMP_TRAP_ENTERPRISESPECIFIC) {
  991.         if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
  992.                  snmptrapenterprise_oid, snmptrapenterprise_oid_len,
  993.                  ASN_OBJECT_ID,
  994.                  (u_char*)template_v1pdu->enterprise, 
  995.                  template_v1pdu->enterprise_length*sizeof(oid)))
  996.             snmp_log(LOG_WARNING,
  997.                  "send_trap: failed to append snmpEnterprise varbindn");
  998.     }
  999.     return template_v2pdu;
  1000. }
  1001. void
  1002. send_trap_to_sess(struct trap_sink *sink, struct snmp_pdu *template_pdu)
  1003. {
  1004.     struct snmp_pdu    *pdu;
  1005.     struct soaddr_in *pduIp;
  1006.     u_long addr;
  1007.     if (!sink->sesp || !template_pdu)
  1008.         return;
  1009.    template_pdu->version = sink->sesp->version;
  1010.    template_pdu->command = sink->pdutype;
  1011.    if (sink->sesp->version == SNMP_VERSION_1 &&
  1012.         (template_pdu->command == SNMP_MSG_TRAP2 ||
  1013.          template_pdu->command == SNMP_MSG_INFORM))
  1014.         return;                 /* Skip v1 sinks for v2 only traps */
  1015.   
  1016.     pdu = snmp_clone_pdu(template_pdu);
  1017.     pduIp = (struct soaddr_in *)&pdu->agent_addr;/*by yangyuhua 2006-8-29*/
  1018.     pduIp->sin_family  = AF_INET;
  1019. get_trapsrc_ip(&addr);
  1020. if(addr)
  1021. pduIp->sin_addr.s_addr = addr;
  1022. else
  1023. pduIp->sin_addr.s_addr = get_myaddr();
  1024.     if (!addr)
  1025. {
  1026. IP_ADDR dest_addr, src_addr;
  1027. if (sink->sesp->peername != NULL)
  1028. {
  1029. dest_addr = inet_addr (sink->sesp->peername);
  1030. if (ipof_iffordest(dest_addr, &src_addr) == 0) /*success*/
  1031. {
  1032. pduIp = (struct soaddr_in *)&pdu->agent_addr;
  1033. pduIp->sin_family  = AF_INET;
  1034. pduIp->sin_addr.s_addr = src_addr;
  1035. }
  1036. }
  1037. }
  1038.     pdu->sessid = sink->sesp->sessid; /* AgentX only ? */
  1039.     if ( snmp_send( sink->sesp, pdu) == 0 ) 
  1040. {
  1041. if (sink->sesp->s_snmp_errno == SNMPERR_BAD_SENDTO)
  1042. {
  1043. if (sink->pduCount+1 < snmp_para.queuelen)
  1044. {
  1045. struct trap_pdu_list *pPduList, *pTemp;
  1046. pPduList = (struct trap_pdu_list *) malloc (sizeof (struct trap_pdu_list));
  1047. if (pPduList == NULL)
  1048. {
  1049. snmp_sess_perror ("snmpd: send_trap", sink->sesp);
  1050. snmp_free_pdu( pdu );
  1051. }
  1052. pPduList->pdu = pdu;
  1053. if (sink->pduHead == NULL)
  1054. {
  1055. pPduList->next = NULL;
  1056. sink->pduHead = pPduList;
  1057. }
  1058. else
  1059. {
  1060. for (pTemp = sink->pduHead; pTemp->next != NULL; pTemp = pTemp->next)
  1061. ;
  1062. pTemp->next = pPduList;
  1063. pPduList->next = NULL;
  1064. }
  1065. sink->pduCount++;
  1066. }
  1067. }
  1068. else
  1069. {
  1070. snmp_sess_perror ("snmpd: send_trap", sink->sesp);
  1071. snmp_free_pdu( pdu );
  1072. }
  1073. }
  1074. else 
  1075. {
  1076. snmp_increment_statistic(STAT_SNMPOUTTRAPS);
  1077. snmp_increment_statistic(STAT_SNMPOUTPKTS);
  1078. }
  1079. }
  1080. void send_enterprise_trap_vars (int trap, 
  1081.      int specific,
  1082.      oid *enterprise, int enterprise_length,
  1083.      struct variable_list *vars)
  1084. {
  1085.   /*  struct variable_list uptime_var, snmptrap_var, enterprise_var;
  1086.     oid temp_oid[MAX_OID_LEN];*/
  1087.     struct variable_list *trap_vb, *var;
  1088.     struct snmp_pdu           *template_v1pdu;
  1089.     struct snmp_pdu           *template_v2pdu;
  1090.     struct timeval  now;
  1091.     long uptime;
  1092.     struct trap_sink *sink;
  1093.     struct variable_list *vblist = NULL;
  1094.     if (vars) {
  1095.         vblist = snmp_clone_varbind( vars );
  1096.         if (!vblist) {
  1097.             snmp_log(LOG_WARNING,
  1098.                      "send_trap: failed to clone varbind listn");
  1099.             return;
  1100.         }
  1101.     }
  1102.     gettimeofday(&now, NULL);
  1103.     uptime = calculate_time_diff(&now, &starttime);
  1104.     if ( trap == -1 ) {
  1105.         /*
  1106.          * Construct the SNMPv2-style notification PDU
  1107.          */
  1108.         if (!vblist)  return;
  1109.         template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
  1110.         if (!template_v2pdu) {
  1111.            snmp_free_varbind(vblist);
  1112.             return;
  1113.         }
  1114.         /*
  1115.          * Check the varbind list we've been given.
  1116.          * If it starts with a 'sysUptime.0' varbind, then use that.
  1117.          * Otherwise, prepend a suitable 'sysUptime.0' varbind.
  1118.          */
  1119.         if (!snmp_oid_compare( vblist->name,    vblist->name_length,
  1120.                                sysuptime_oid, sysuptime_oid_len )) {
  1121.             template_v2pdu->variables = vblist;
  1122.             trap_vb  = vblist->next_variable;
  1123.         } else {
  1124.             var = NULL;
  1125.             snmp_varlist_add_variable( &var,
  1126.                            sysuptime_oid, sysuptime_oid_len,
  1127.                            ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime));
  1128.             if (!var) {
  1129.   snmp_free_varbind(vblist);
  1130.                 snmp_free_pdu(template_v2pdu);
  1131.                 return ;
  1132.             }
  1133.             template_v2pdu->variables = var;
  1134.             var->next_variable        = vblist;
  1135.             trap_vb  = vblist;
  1136.         }
  1137.         /*
  1138.          * 'trap_vb' should point to the snmpTrapOID.0 varbind,
  1139.          *   identifying the requested trap.  If not then bomb out.
  1140.          * If it's a 'standard' trap, then we need to append an
  1141.          *   snmpEnterprise varbind (if there isn't already one).
  1142.          */
  1143.         if (!trap_vb ||
  1144.             snmp_oid_compare(trap_vb->name, trap_vb->name_length,
  1145.                              snmptrap_oid,  snmptrap_oid_len)) {
  1146.             snmp_free_pdu(template_v2pdu);
  1147.             return;
  1148.         }
  1149.         if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
  1150.                               trap_prefix,       OID_LENGTH(trap_prefix))) {/*查看warm_start_oid等有没有定义*/
  1151.             var = find_varbind_in_list( template_v2pdu->variables,
  1152.                                         snmptrapenterprise_oid,
  1153.                                         snmptrapenterprise_oid_len);
  1154.             if (!var &&
  1155.                 !snmp_varlist_add_variable( &(template_v2pdu->variables),
  1156.                      snmptrapenterprise_oid, snmptrapenterprise_oid_len,
  1157.                      ASN_OBJECT_ID,
  1158.                      (char*)enterprise, enterprise_length*sizeof(oid))) {
  1159.                 snmp_free_pdu(template_v2pdu);
  1160.                 return ;
  1161.             }
  1162.         }
  1163.         /*
  1164.          * If everything's OK, convert the v2 template into an SNMPv1 trap PDU.
  1165.          */
  1166.         template_v1pdu = convert_v2pdu_to_v1( template_v2pdu );
  1167.         if (!template_v1pdu) {
  1168.             snmp_free_pdu(template_v2pdu);
  1169.             return;
  1170.         }
  1171.     }else {
  1172.         /*
  1173.          * Construct the SNMPv1 trap PDU....
  1174.          */
  1175.         template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP);
  1176.         if (!template_v1pdu) {
  1177.      snmp_free_varbind(vblist);
  1178.             return ;
  1179.         }
  1180.         template_v1pdu->trap_type     = trap;
  1181.         template_v1pdu->specific_type = specific;
  1182.         template_v1pdu->time          = uptime;
  1183.         if (snmp_clone_mem((void **) &template_v1pdu->enterprise,
  1184.                        enterprise, enterprise_length * sizeof(oid))) {
  1185.             snmp_free_varbind(vblist);
  1186.             snmp_free_pdu(template_v1pdu);
  1187.             return;
  1188.         }
  1189.         template_v1pdu->enterprise_length = enterprise_length;
  1190.         template_v1pdu->flags    |= UCD_MSG_FLAG_FORCE_PDU_COPY;
  1191.         template_v1pdu->variables = vblist;
  1192.         /*
  1193.          * ... and convert it into an SNMPv2-style notification PDU.
  1194.          */
  1195.         template_v2pdu = convert_v1pdu_to_v2( template_v1pdu );
  1196.         if (!template_v2pdu) {
  1197.             snmp_free_pdu(template_v1pdu);
  1198.             return ;
  1199.         }
  1200.     }
  1201. /*
  1202.  *  Now loop through the list of trap sinks,
  1203.  *   sending an appropriately formatted PDU to each
  1204.  */
  1205. for ( sink = sinks ; sink ; sink=sink->next ) 
  1206. {
  1207. BOOL bContinue;
  1208. if ( sink->version == SNMP_VERSION_1 && trap == -1 )
  1209. continue; /* Skip v1 sinks for v2 only traps */
  1210. bContinue = TRUE;
  1211. switch ( trap )
  1212. {
  1213. case SNMP_TRAP_COLDSTART:
  1214. case SNMP_TRAP_WARMSTART:
  1215. case SNMP_TRAP_LINKDOWN:
  1216. case SNMP_TRAP_LINKUP:
  1217. if(sink->trapflags&SNMP_SNMPTYPE_TRAP)
  1218. bContinue = FALSE;
  1219. break;
  1220. case SNMP_TRAP_AUTHFAIL:
  1221. if(sink->trapflags&SNMP_AUTH_TRAP)
  1222. bContinue = FALSE;
  1223. break;
  1224. default:
  1225. bContinue = FALSE;
  1226. break;
  1227. }
  1228. if (bContinue)
  1229. continue;
  1230.  if (sink->version == SNMP_VERSION_1) {
  1231.             send_trap_to_sess(sink, template_v1pdu);
  1232.         } else {
  1233.             send_trap_to_sess(sink, template_v2pdu);
  1234.         }
  1235. }
  1236. /* Ensure we don't free anything we shouldn't */
  1237.     snmp_free_pdu( template_v1pdu );
  1238.     snmp_free_pdu( template_v2pdu );
  1239. }
  1240. #endif
  1241. void send_trap_vars (int trap, 
  1242.      int specific,
  1243.      struct variable_list *vars)
  1244. {
  1245.     if ( trap == SNMP_TRAP_ENTERPRISESPECIFIC )
  1246.         send_enterprise_trap_vars( trap, specific, default_enterprise,
  1247. OID_LENGTH(default_enterprise), vars );
  1248.     else
  1249.         send_enterprise_trap_vars( trap, specific, default_enterprise,
  1250. OID_LENGTH(default_enterprise), vars );
  1251. }
  1252. void send_easy_trap (int trap, 
  1253.      int specific)
  1254. {
  1255.     send_trap_vars( trap, specific, NULL );
  1256. }
  1257. void send_v2trap ( struct variable_list *vars)
  1258. {
  1259.     send_trap_vars( -1, -1, vars );
  1260. }
  1261. void
  1262. send_trap_pdu(struct snmp_pdu *pdu)
  1263. {
  1264.     send_trap_vars( -1, -1, pdu->variables );
  1265. }
  1266. /*******************
  1267.  *
  1268.  * Config file handling
  1269.  *
  1270.  *******************/
  1271. void snmpd_parse_config_authtrap(const char *token, 
  1272.  char *cptr)
  1273. {
  1274.     int i;
  1275.     i = atoi(cptr);
  1276.     if ( i == 0 ) {
  1277. if ( !strcmp( cptr, "enable" ))
  1278.     i = SNMP_AUTHENTICATED_TRAPS_ENABLED;
  1279. else if ( !strcmp( cptr, "disable" ))
  1280.     i = SNMP_AUTHENTICATED_TRAPS_DISABLED;
  1281.     }
  1282.     if (i < 1 || i > 2)
  1283. config_perror("authtrapenable must be 1 or 2");
  1284.     else
  1285. snmp_enableauthentraps = i;
  1286. }
  1287. void snmpd_parse_config_trapsink(const char *token, 
  1288.  char *cptr)
  1289. {
  1290.     char tmpbuf[1024];
  1291.     char *sp, *cp, *pp = NULL;
  1292.     u_short sinkport;
  1293.     
  1294.     if (!snmp_trapcommunity) snmp_trapcommunity = strdup("public");
  1295.     sp = strtok(cptr, " tn");
  1296.     cp = strtok(NULL, " tn");
  1297.     if (cp) pp = strtok(NULL, " tn");
  1298.     if (cp && pp) {
  1299. sinkport = (u_short) atoi(pp);
  1300. if ((sinkport < 1) || (sinkport > 0xffff)) {
  1301.     config_perror("trapsink port out of range");
  1302.     sinkport = SNMP_TRAP_PORT;
  1303. }
  1304.     } else {
  1305. sinkport = SNMP_TRAP_PORT;
  1306.     }
  1307.     if (create_v1_trap_session(sp, sinkport,
  1308.        cp ? cp : snmp_trapcommunity) == 0) {
  1309. sprintf(tmpbuf,"cannot create trapsink: %s", cptr);
  1310. config_perror(tmpbuf);
  1311.     }
  1312. }
  1313. void
  1314. snmpd_parse_config_trap2sink(const char *word, char *cptr)
  1315. {
  1316.     char tmpbuf[1024];
  1317.     char *sp, *cp, *pp = NULL;
  1318.     u_short sinkport;
  1319.   
  1320.     if (!snmp_trapcommunity) snmp_trapcommunity = strdup("public");
  1321.     sp = strtok(cptr, " tn");
  1322.     cp = strtok(NULL, " tn");
  1323.     if (cp) pp = strtok(NULL, " tn");
  1324.     if (cp && pp) {
  1325. sinkport = (u_short)atoi(pp);
  1326. if ((sinkport < 1) || (sinkport > 0xffff)) {
  1327.     config_perror("trapsink port out of range");
  1328.     sinkport = SNMP_TRAP_PORT;
  1329. }
  1330.     } else {
  1331. sinkport = SNMP_TRAP_PORT;
  1332.     }
  1333.     if (create_v2_trap_session(sp, sinkport,
  1334.        cp ? cp : snmp_trapcommunity) == 0) {
  1335. sprintf(tmpbuf,"cannot create trap2sink: %s", cptr);
  1336. config_perror(tmpbuf);
  1337.     }
  1338. }
  1339. void
  1340. snmpd_parse_config_informsink(const char *word, char *cptr)
  1341. {
  1342.     char tmpbuf[1024];
  1343.     char *sp, *cp, *pp = NULL;
  1344.     u_short sinkport;
  1345.   
  1346.     if (!snmp_trapcommunity) snmp_trapcommunity = strdup("public");
  1347.     sp = strtok(cptr, " tn");
  1348.     cp = strtok(NULL, " tn");
  1349.     if (cp) pp = strtok(NULL, " tn");
  1350.     if (cp && pp) {
  1351. sinkport = (u_short)atoi(pp);
  1352. if ((sinkport < 1) || (sinkport > 0xffff)) {
  1353.     config_perror("trapsink port out of range");
  1354.     sinkport = SNMP_TRAP_PORT;
  1355. }
  1356.     } else {
  1357. sinkport = SNMP_TRAP_PORT;
  1358.     }
  1359.     if (create_v2_inform_session(sp, sinkport,
  1360.  cp ? cp : snmp_trapcommunity) == 0) {
  1361. sprintf(tmpbuf,"cannot create informsink: %s", cptr);
  1362. config_perror(tmpbuf);
  1363.     }
  1364. }
  1365. void
  1366. snmpd_parse_config_trapcommunity(const char *word, char *cptr)
  1367. {
  1368.     if (snmp_trapcommunity) free(snmp_trapcommunity);
  1369.     snmp_trapcommunity = malloc (strlen(cptr)+1);
  1370.     copy_word(cptr, snmp_trapcommunity);
  1371. }
  1372. void snmpd_free_trapcommunity (void)
  1373. {
  1374.     if (snmp_trapcommunity) {
  1375. free(snmp_trapcommunity);
  1376. snmp_trapcommunity = NULL;
  1377.     }
  1378. }
  1379. #define MIB 1, 3, 6, 1, 2, 1
  1380. oid objid_ifIndex[]   = {MIB, 2, 2,1,1, 0};
  1381. static oid objid_ifDescr[]   = {MIB, 2,2,1, 2, 0};
  1382. static oid objid_ifType[]   = {MIB, 2,2,1, 3, 0};
  1383. static oid objid_ifAdminStatus[]   = {MIB, 2,2,1, 7, 0};
  1384. static oid objid_ifOpenStatus[]   = {MIB, 2,2,1, 8, 0};
  1385. static long ltmp;
  1386. void send_v1_link_trap(int trap_type,int if_index,int if_type,unsigned char *if_desr)
  1387. {
  1388. struct variable_list *vl = NULL;
  1389. int namelen;
  1390. UINT16 iAdminTemp=0;
  1391. namelen=sizeof (objid_ifIndex)/sizeof(oid);
  1392. objid_ifIndex[namelen-1]=if_index;
  1393. ltmp = if_index;
  1394. snmp_varlist_add_variable(&vl, objid_ifIndex, namelen, ASN_INTEGER,
  1395. (char*)&ltmp, sizeof (long));
  1396. namelen=sizeof (objid_ifDescr)/sizeof(oid);
  1397. objid_ifDescr[namelen-1]=if_index;
  1398. snmp_varlist_add_variable(&vl, objid_ifDescr, namelen, ASN_OCTET_STR,
  1399. (char*)if_desr, strlen (if_desr));
  1400. namelen=sizeof (objid_ifType)/sizeof(oid);
  1401. objid_ifType[namelen-1]=if_index;
  1402. ltmp = if_type;
  1403. snmp_varlist_add_variable(&vl, objid_ifType, namelen, ASN_INTEGER,
  1404. (char*)&ltmp, sizeof (long));
  1405. interface_omnivorous_callback_getshutdown(if_index, (UINT16 *)&iAdminTemp);
  1406. if (iAdminTemp & 1)
  1407. {
  1408. ltmp = 2;
  1409. else 
  1410. {
  1411. ltmp = 1;
  1412. }
  1413. namelen=sizeof (objid_ifAdminStatus)/sizeof(oid);
  1414. objid_ifAdminStatus[namelen-1]=if_index;
  1415. snmp_varlist_add_variable(&vl, objid_ifAdminStatus, namelen, ASN_INTEGER,
  1416. (char*)&ltmp, sizeof (long));
  1417. switch ( trap_type )
  1418. {
  1419. case SNMP_TRAP_LINKDOWN:
  1420. namelen=sizeof (objid_ifOpenStatus)/sizeof(oid);
  1421. objid_ifOpenStatus[namelen-1]=if_index;
  1422. ltmp = trap_type;
  1423. snmp_varlist_add_variable(&vl, objid_ifOpenStatus, namelen, ASN_INTEGER,
  1424. (char*)&ltmp, sizeof (long));
  1425. break;
  1426. case SNMP_TRAP_LINKUP:
  1427. namelen=sizeof (objid_ifOpenStatus)/sizeof(oid);
  1428. objid_ifOpenStatus[namelen-1]=if_index;
  1429. ltmp = 1;
  1430. snmp_varlist_add_variable(&vl, objid_ifOpenStatus, namelen, ASN_INTEGER,
  1431. (char*)&ltmp, sizeof (long));
  1432. break;
  1433. default:
  1434. break;
  1435. }
  1436.    
  1437. send_trap_vars (trap_type, -1, vl);
  1438. snmp_free_varbind (vl);
  1439. }
  1440. void send_link_trap(int version,int trap_type,int if_index,int if_type,unsigned char *if_desr)
  1441. {
  1442. send_v1_link_trap(trap_type,if_index,if_type,if_desr);
  1443. }
  1444. #ifndef OS_VXWORKS
  1445. static ULONG trapTimerID = 0;
  1446. #endif
  1447. static void retry_send_trap(ULONG arg)
  1448. {
  1449. struct trap_sink *sinkPtr;
  1450. struct trap_pdu_list *prevPtr, *curPtr;
  1451. for ( sinkPtr = sinks ; sinkPtr != NULL; sinkPtr=sinkPtr->next )
  1452. {
  1453. prevPtr = NULL;
  1454. for (curPtr = sinkPtr->pduHead; curPtr != NULL; )
  1455. {
  1456. IP_ADDR dest_addr, src_addr;
  1457. struct soaddr_in *pduIp;
  1458. if (sinkPtr->sesp->peername != NULL)
  1459. {
  1460. dest_addr = inet_addr (sinkPtr->sesp->peername);
  1461. if (ipof_iffordest(dest_addr, &src_addr) == 0) /*success*/
  1462. {
  1463. pduIp = (struct soaddr_in *)&(curPtr->pdu->agent_addr);
  1464. pduIp->sin_family  = AF_INET;
  1465. pduIp->sin_addr.s_addr = src_addr;
  1466. }
  1467. }
  1468. if (snmp_send( sinkPtr->sesp, curPtr->pdu) != 0)
  1469. {
  1470. if (prevPtr == NULL)
  1471. {
  1472. sinkPtr->pduHead = curPtr->next;
  1473. free (curPtr);
  1474. curPtr = sinkPtr->pduHead;
  1475. }
  1476. else
  1477. {
  1478. prevPtr->next = curPtr->next;
  1479. free (curPtr);
  1480. curPtr = prevPtr->next;
  1481. }
  1482. sinkPtr->pduCount --;
  1483. snmp_increment_statistic(STAT_SNMPOUTTRAPS);
  1484. snmp_increment_statistic(STAT_SNMPOUTPKTS);
  1485. }
  1486. else
  1487. {
  1488. prevPtr = curPtr;
  1489. curPtr = curPtr->next;
  1490. }
  1491. }
  1492. }
  1493. #ifndef OS_VXWORKS
  1494. sys_start_timer(trapTimerID,snmp_para.timeout);
  1495. #endif
  1496. }
  1497. #ifdef OS_VXWORKS
  1498. void snmp_retry_send_trap()
  1499. {
  1500.     while (1)
  1501.     {
  1502.         sys_task_delay(snmp_para.timeout * SYS_CLK_RATE);
  1503.         retry_send_trap(0);
  1504.     }
  1505. }
  1506. #endif
  1507. void init_trap_retry_timer(void)
  1508. {
  1509. #ifndef OS_VXWORKS
  1510. TIMER_USER_DATA user_data;
  1511. user_data.cb.fun=retry_send_trap;
  1512. user_data.cb.arg=0;
  1513. sys_add_timer(TIMER_CALLBACK_METHOD,&user_data,&trapTimerID);
  1514. sys_start_timer(trapTimerID,snmp_para.timeout);
  1515. #else
  1516.     sys_task_spawn("SNMT", SYS_TASK_PRI_NORMAL, T_OP_NOPREEMPT, 16*1024, snmp_retry_send_trap, NULL, 0);
  1517. #endif
  1518. }
  1519. void set_trapsinks(int cmd,long long value)
  1520. {
  1521. struct trap_sink *trapsink;
  1522. SNMP_DEBUG_ROUTINES("set_trapsinks()");
  1523. for(trapsink=sinks;trapsink!=NULL;trapsink=trapsink->next){
  1524. switch(cmd){
  1525. case SET_SNMP_TRAP_QUEUELEN:
  1526. trapsink->sesp->retries=(int)value;
  1527. break;
  1528. case SET_SNMP_TRAP_TIMEOUT:
  1529. trapsink->sesp->timeout=(int)value;
  1530. #ifndef OS_VXWORKS
  1531. sys_stop_timer (trapTimerID);
  1532. sys_start_timer(trapTimerID,snmp_para.timeout);
  1533. #endif
  1534. break;
  1535. case SET_SNMP_TRAP_SOURCE:
  1536. change_session_localaddr(trapsink->sesp,(DEVICE_ETERNAL_ID)value);
  1537. break;
  1538. }
  1539. }
  1540. }