00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00020 #include <net-snmp/net-snmp-config.h>
00021
00022 #if HAVE_UNISTD_H
00023 #include <unistd.h>
00024 #endif
00025 #if HAVE_NETDB_H
00026 #include <netdb.h>
00027 #endif
00028 #if HAVE_STDLIB_H
00029 #include <stdlib.h>
00030 #endif
00031 #if HAVE_STRING_H
00032 #include <string.h>
00033 #else
00034 #include <strings.h>
00035 #endif
00036 #if TIME_WITH_SYS_TIME
00037 # ifdef WIN32
00038 # include <sys/timeb.h>
00039 # else
00040 # include <sys/time.h>
00041 # endif
00042 # include <time.h>
00043 #else
00044 # if HAVE_SYS_TIME_H
00045 # include <sys/time.h>
00046 # else
00047 # include <time.h>
00048 # endif
00049 #endif
00050 #if HAVE_SYS_SOCKET_H
00051 #include <sys/socket.h>
00052 #elif HAVE_WINSOCK_H
00053 #include <winsock.h>
00054 #endif
00055 #if HAVE_NETINET_IN_H
00056 #include <netinet/in.h>
00057 #endif
00058 #include <net-snmp/utilities.h>
00059
00060 #include <net-snmp/net-snmp-includes.h>
00061 #include <net-snmp/agent/net-snmp-agent-includes.h>
00062 #include <net-snmp/agent/agent_trap.h>
00063 #include <net-snmp/agent/snmp_agent.h>
00064 #include <net-snmp/agent/agent_callbacks.h>
00065
00066 #include <net-snmp/agent/agent_module_config.h>
00067 #include <net-snmp/agent/mib_module_config.h>
00068
00069 #ifdef USING_AGENTX_PROTOCOL_MODULE
00070 #include "agentx/protocol.h"
00071 #endif
00072
00073 struct trap_sink {
00074 netsnmp_session *sesp;
00075 struct trap_sink *next;
00076 int pdutype;
00077 int version;
00078 };
00079
00080 struct trap_sink *sinks = NULL;
00081
00082 extern struct timeval starttime;
00083
00084 oid objid_enterprisetrap[] = { NETSNMP_NOTIFICATION_MIB };
00085 oid trap_version_id[] = { NETSNMP_SYSTEM_MIB };
00086 int enterprisetrap_len;
00087 int trap_version_id_len;
00088
00089 #define SNMPV2_TRAPS_PREFIX SNMP_OID_SNMPMODULES,1,1,5
00090 oid trap_prefix[] = { SNMPV2_TRAPS_PREFIX };
00091 oid cold_start_oid[] = { SNMPV2_TRAPS_PREFIX, 1 };
00092 oid warm_start_oid[] = { SNMPV2_TRAPS_PREFIX, 2 };
00093 oid link_down_oid[] = { SNMPV2_TRAPS_PREFIX, 3 };
00094 oid link_up_oid[] = { SNMPV2_TRAPS_PREFIX, 4 };
00095 oid auth_fail_oid[] = { SNMPV2_TRAPS_PREFIX, 5 };
00096 oid egp_xxx_oid[] = { SNMPV2_TRAPS_PREFIX, 99 };
00097
00098 #define SNMPV2_TRAP_OBJS_PREFIX SNMP_OID_SNMPMODULES,1,1,4
00099 oid snmptrap_oid[] = { SNMPV2_TRAP_OBJS_PREFIX, 1, 0 };
00100 oid snmptrapenterprise_oid[] =
00101 { SNMPV2_TRAP_OBJS_PREFIX, 3, 0 };
00102 oid sysuptime_oid[] = { SNMP_OID_MIB2, 1, 3, 0 };
00103 size_t snmptrap_oid_len;
00104 size_t snmptrapenterprise_oid_len;
00105 size_t sysuptime_oid_len;
00106
00107 #define SNMPV2_COMM_OBJS_PREFIX SNMP_OID_SNMPMODULES,18,1
00108 oid agentaddr_oid[] = { SNMPV2_COMM_OBJS_PREFIX, 3, 0 };
00109 size_t agentaddr_oid_len;
00110 oid community_oid[] = { SNMPV2_COMM_OBJS_PREFIX, 4, 0 };
00111 size_t community_oid_len;
00112 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
00113 char *snmp_trapcommunity = NULL;
00114 #endif
00115
00116
00117 #define SNMP_AUTHENTICATED_TRAPS_ENABLED 1
00118 #define SNMP_AUTHENTICATED_TRAPS_DISABLED 2
00119
00120 int snmp_enableauthentraps = SNMP_AUTHENTICATED_TRAPS_DISABLED;
00121 int snmp_enableauthentrapsset = 0;
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 void
00143 init_traps(void)
00144 {
00145 enterprisetrap_len = OID_LENGTH(objid_enterprisetrap);
00146 trap_version_id_len = OID_LENGTH(trap_version_id);
00147 snmptrap_oid_len = OID_LENGTH(snmptrap_oid);
00148 snmptrapenterprise_oid_len = OID_LENGTH(snmptrapenterprise_oid);
00149 sysuptime_oid_len = OID_LENGTH(sysuptime_oid);
00150 agentaddr_oid_len = OID_LENGTH(agentaddr_oid);
00151 community_oid_len = OID_LENGTH(community_oid);
00152 }
00153
00154 static void
00155 free_trap_session(struct trap_sink *sp)
00156 {
00157 DEBUGMSGTL(("trap", "freeing callback trap session (%p, %p)\n", sp, sp->sesp));
00158 snmp_close(sp->sesp);
00159 free(sp);
00160 }
00161
00162 int
00163 add_trap_session(netsnmp_session * ss, int pdutype, int confirm,
00164 int version)
00165 {
00166 if (snmp_callback_available(SNMP_CALLBACK_APPLICATION,
00167 SNMPD_CALLBACK_REGISTER_NOTIFICATIONS) ==
00168 SNMPERR_SUCCESS) {
00169
00170
00171
00172 struct agent_add_trap_args args;
00173 DEBUGMSGTL(("trap", "adding callback trap sink (%p)\n", ss));
00174 args.ss = ss;
00175 args.confirm = confirm;
00176 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
00177 SNMPD_CALLBACK_REGISTER_NOTIFICATIONS,
00178 (void *) &args);
00179 } else {
00180
00181
00182
00183 struct trap_sink *new_sink;
00184
00185 DEBUGMSGTL(("trap", "adding internal trap sink\n"));
00186 new_sink = (struct trap_sink *) malloc(sizeof(*new_sink));
00187 if (new_sink == NULL)
00188 return 0;
00189
00190 new_sink->sesp = ss;
00191 new_sink->pdutype = pdutype;
00192 new_sink->version = version;
00193 new_sink->next = sinks;
00194 sinks = new_sink;
00195 }
00196 return 1;
00197 }
00198
00199 int
00200 remove_trap_session(netsnmp_session * ss)
00201 {
00202 struct trap_sink *sp = sinks, *prev = NULL;
00203
00204 DEBUGMSGTL(("trap", "removing trap sessions\n"));
00205 while (sp) {
00206 if (sp->sesp == ss) {
00207 if (prev) {
00208 prev->next = sp->next;
00209 } else {
00210 sinks = sp->next;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 DEBUGMSGTL(("trap", "removing trap session (%p, %p)\n", sp, sp->sesp));
00223 free(sp);
00224 return 1;
00225 }
00226 prev = sp;
00227 sp = sp->next;
00228 }
00229 return 0;
00230 }
00231
00232 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
00233 static int
00234 create_trap_session2(const char *sink, const char* sinkport,
00235 char *com, int version, int pdutype)
00236 {
00237 netsnmp_transport *t;
00238 netsnmp_session session, *sesp;
00239
00240 memset(&session, 0, sizeof(netsnmp_session));
00241 session.version = version;
00242 if (com) {
00243 session.community = (u_char *) com;
00244 session.community_len = strlen(com);
00245 }
00246
00247
00248
00249
00250 if (SNMP_MSG_INFORM == pdutype) {
00251 session.timeout = SNMP_DEFAULT_TIMEOUT;
00252 session.retries = SNMP_DEFAULT_RETRIES;
00253 }
00254
00255
00256
00257
00258 if ((NULL == netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00259 NETSNMP_DS_LIB_CLIENT_ADDR)) &&
00260 ((0 == strcmp("localhost",sink)) || (0 == strcmp("127.0.0.1",sink))))
00261 session.localname = strdup("localhost");
00262
00263 t = netsnmp_tdomain_transport_full("snmptrap", sink, 0, NULL, sinkport);
00264 if (t != NULL) {
00265 sesp = snmp_add(&session, t, NULL, NULL);
00266
00267 if (sesp) {
00268 return add_trap_session(sesp, pdutype,
00269 (pdutype == SNMP_MSG_INFORM), version);
00270 }
00271 }
00272
00273
00274
00275 snmp_sess_perror("snmpd: create_trap_session", &session);
00276 return 0;
00277 }
00278
00279 int
00280 create_trap_session(char *sink, u_short sinkport,
00281 char *com, int version, int pdutype)
00282 {
00283 char buf[sizeof(sinkport) * 3 + 2];
00284 if (sinkport != 0) {
00285 sprintf(buf, ":%hu", sinkport);
00286 snmp_log(LOG_NOTICE,
00287 "Using a separate port number is deprecated, please correct "
00288 "the sink specification instead");
00289 }
00290 return create_trap_session2(sink, sinkport ? buf : NULL, com, version,
00291 pdutype);
00292 }
00293
00294 #endif
00295
00296 #ifndef NETSNMP_DISABLE_SNMPV1
00297 static int
00298 create_v1_trap_session(char *sink, const char *sinkport, char *com)
00299 {
00300 return create_trap_session2(sink, sinkport, com,
00301 SNMP_VERSION_1, SNMP_MSG_TRAP);
00302 }
00303 #endif
00304
00305 #ifndef NETSNMP_DISABLE_SNMPV2C
00306 static int
00307 create_v2_trap_session(const char *sink, const char *sinkport, char *com)
00308 {
00309 return create_trap_session2(sink, sinkport, com,
00310 SNMP_VERSION_2c, SNMP_MSG_TRAP2);
00311 }
00312
00313 static int
00314 create_v2_inform_session(const char *sink, const char *sinkport, char *com)
00315 {
00316 return create_trap_session2(sink, sinkport, com,
00317 SNMP_VERSION_2c, SNMP_MSG_INFORM);
00318 }
00319 #endif
00320
00321 void
00322 snmpd_free_trapsinks(void)
00323 {
00324 struct trap_sink *sp = sinks;
00325 DEBUGMSGTL(("trap", "freeing trap sessions\n"));
00326 while (sp) {
00327 sinks = sinks->next;
00328 free_trap_session(sp);
00329 sp = sinks;
00330 }
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340 netsnmp_pdu*
00341 convert_v2pdu_to_v1( netsnmp_pdu* template_v2pdu )
00342 {
00343 netsnmp_pdu *template_v1pdu;
00344 netsnmp_variable_list *first_vb, *vblist;
00345 netsnmp_variable_list *var;
00346
00347
00348
00349
00350
00351
00352 template_v1pdu = snmp_clone_pdu( template_v2pdu);
00353 if (!template_v1pdu) {
00354 snmp_log(LOG_WARNING,
00355 "send_trap: failed to copy v1 template PDU\n");
00356 return NULL;
00357 }
00358 template_v1pdu->command = SNMP_MSG_TRAP;
00359 first_vb = template_v1pdu->variables;
00360 vblist = template_v1pdu->variables;
00361
00362
00363
00364
00365 if (!vblist ||
00366 snmp_oid_compare(vblist->name, vblist->name_length,
00367 sysuptime_oid, sysuptime_oid_len)) {
00368 snmp_log(LOG_WARNING,
00369 "send_trap: no v2 sysUptime varbind to set from\n");
00370 snmp_free_pdu(template_v1pdu);
00371 return NULL;
00372 }
00373 template_v1pdu->time = *vblist->val.integer;
00374 vblist = vblist->next_variable;
00375
00376
00377
00378
00379 if (!vblist ||
00380 snmp_oid_compare(vblist->name, vblist->name_length,
00381 snmptrap_oid, snmptrap_oid_len)) {
00382 snmp_log(LOG_WARNING,
00383 "send_trap: no v2 trapOID varbind to set from\n");
00384 snmp_free_pdu(template_v1pdu);
00385 return NULL;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 for (var = vblist->next_variable; var; var = var->next_variable) {
00397 if ( var->type == ASN_COUNTER64 ) {
00398 snmp_log(LOG_WARNING,
00399 "send_trap: v1 traps can't carry Counter64 varbinds\n");
00400 snmp_free_pdu(template_v1pdu);
00401 return NULL;
00402 }
00403 }
00404
00405
00406
00407
00408
00409
00410 if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
00411 trap_prefix, OID_LENGTH(trap_prefix))) {
00412
00413
00414
00415
00416
00417 template_v1pdu->trap_type =
00418 vblist->val.objid[OID_LENGTH(trap_prefix)] - 1;
00419 template_v1pdu->specific_type = 0;
00420
00421 var = find_varbind_in_list( vblist,
00422 snmptrapenterprise_oid,
00423 snmptrapenterprise_oid_len);
00424 if (var) {
00425 template_v1pdu->enterprise_length = var->val_len/sizeof(oid);
00426 template_v1pdu->enterprise =
00427 snmp_duplicate_objid(var->val.objid,
00428 template_v1pdu->enterprise_length);
00429 } else {
00430 template_v1pdu->enterprise = NULL;
00431 template_v1pdu->enterprise_length = 0;
00432 }
00433 } else {
00434
00435
00436
00437
00438 size_t len = vblist->val_len / sizeof(oid);
00439 if ( len <= 2 ) {
00440 snmp_log(LOG_WARNING,
00441 "send_trap: v2 trapOID too short (%d)\n", (int)len);
00442 snmp_free_pdu(template_v1pdu);
00443 return NULL;
00444 }
00445 template_v1pdu->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC;
00446 template_v1pdu->specific_type = vblist->val.objid[len - 1];
00447 len--;
00448 if (vblist->val.objid[len-1] == 0)
00449 len--;
00450 SNMP_FREE(template_v1pdu->enterprise);
00451 template_v1pdu->enterprise =
00452 snmp_duplicate_objid(vblist->val.objid, len);
00453 template_v1pdu->enterprise_length = len;
00454 }
00455 var = find_varbind_in_list( vblist, agentaddr_oid,
00456 agentaddr_oid_len);
00457 if (var) {
00458 memcpy(template_v1pdu->agent_addr,
00459 var->val.string, 4);
00460 }
00461
00462
00463
00464
00465
00466
00467 template_v1pdu->variables = vblist->next_variable;
00468 vblist->next_variable = NULL;
00469 snmp_free_varbind( first_vb );
00470
00471 return template_v1pdu;
00472 }
00473
00474 netsnmp_pdu*
00475 convert_v1pdu_to_v2( netsnmp_pdu* template_v1pdu )
00476 {
00477 netsnmp_pdu *template_v2pdu;
00478 netsnmp_variable_list *first_vb;
00479 netsnmp_variable_list *var;
00480 oid enterprise[MAX_OID_LEN];
00481 size_t enterprise_len;
00482
00483
00484
00485
00486
00487
00488 template_v2pdu = snmp_clone_pdu( template_v1pdu);
00489 if (!template_v2pdu) {
00490 snmp_log(LOG_WARNING,
00491 "send_trap: failed to copy v2 template PDU\n");
00492 return NULL;
00493 }
00494 template_v2pdu->command = SNMP_MSG_TRAP2;
00495 first_vb = template_v2pdu->variables;
00496
00497
00498
00499
00500
00501
00502 if (template_v1pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
00503 memcpy(enterprise, template_v1pdu->enterprise,
00504 template_v1pdu->enterprise_length*sizeof(oid));
00505 enterprise_len = template_v1pdu->enterprise_length;
00506 enterprise[enterprise_len++] = 0;
00507 enterprise[enterprise_len++] = template_v1pdu->specific_type;
00508 } else {
00509 memcpy(enterprise, cold_start_oid, sizeof(cold_start_oid));
00510 enterprise[9] = template_v1pdu->trap_type+1;
00511 enterprise_len = sizeof(cold_start_oid)/sizeof(oid);
00512 }
00513
00514 var = NULL;
00515 if (!snmp_varlist_add_variable( &var,
00516 snmptrap_oid, snmptrap_oid_len,
00517 ASN_OBJECT_ID,
00518 (u_char*)enterprise, enterprise_len*sizeof(oid))) {
00519 snmp_log(LOG_WARNING,
00520 "send_trap: failed to insert copied snmpTrapOID varbind\n");
00521 snmp_free_pdu(template_v2pdu);
00522 return NULL;
00523 }
00524 var->next_variable = template_v2pdu->variables;
00525 template_v2pdu->variables = var;
00526
00527
00528
00529
00530 var = NULL;
00531 if (!snmp_varlist_add_variable( &var,
00532 sysuptime_oid, sysuptime_oid_len,
00533 ASN_TIMETICKS,
00534 (u_char*)&(template_v1pdu->time),
00535 sizeof(template_v1pdu->time))) {
00536 snmp_log(LOG_WARNING,
00537 "send_trap: failed to insert copied sysUptime varbind\n");
00538 snmp_free_pdu(template_v2pdu);
00539 return NULL;
00540 }
00541 var->next_variable = template_v2pdu->variables;
00542 template_v2pdu->variables = var;
00543
00544
00545
00546
00547
00548
00549
00550 var = find_varbind_in_list( template_v2pdu->variables,
00551 agentaddr_oid, agentaddr_oid_len);
00552 if (!var && (template_v1pdu->agent_addr[0]
00553 || template_v1pdu->agent_addr[1]
00554 || template_v1pdu->agent_addr[2]
00555 || template_v1pdu->agent_addr[3])) {
00556 if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
00557 agentaddr_oid, agentaddr_oid_len,
00558 ASN_IPADDRESS,
00559 (u_char*)&(template_v1pdu->agent_addr),
00560 sizeof(template_v1pdu->agent_addr)))
00561 snmp_log(LOG_WARNING,
00562 "send_trap: failed to append snmpTrapAddr varbind\n");
00563 }
00564 var = find_varbind_in_list( template_v2pdu->variables,
00565 community_oid, community_oid_len);
00566 if (!var && template_v1pdu->community) {
00567 if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
00568 community_oid, community_oid_len,
00569 ASN_OCTET_STR,
00570 template_v1pdu->community,
00571 template_v1pdu->community_len))
00572 snmp_log(LOG_WARNING,
00573 "send_trap: failed to append snmpTrapCommunity varbind\n");
00574 }
00575 var = find_varbind_in_list( template_v2pdu->variables,
00576 snmptrapenterprise_oid,
00577 snmptrapenterprise_oid_len);
00578 if (!var) {
00579 if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
00580 snmptrapenterprise_oid, snmptrapenterprise_oid_len,
00581 ASN_OBJECT_ID,
00582 (u_char*)template_v1pdu->enterprise,
00583 template_v1pdu->enterprise_length*sizeof(oid)))
00584 snmp_log(LOG_WARNING,
00585 "send_trap: failed to append snmpEnterprise varbind\n");
00586 }
00587 return template_v2pdu;
00588 }
00589
00633 int
00634 netsnmp_send_traps(int trap, int specific,
00635 oid * enterprise, int enterprise_length,
00636 netsnmp_variable_list * vars,
00637 char * context, int flags)
00638 {
00639 netsnmp_pdu *template_v1pdu;
00640 netsnmp_pdu *template_v2pdu;
00641 netsnmp_variable_list *vblist = NULL;
00642 netsnmp_variable_list *trap_vb;
00643 netsnmp_variable_list *var;
00644 in_addr_t *pdu_in_addr_t;
00645 u_long uptime;
00646 struct trap_sink *sink;
00647 const char *v1trapaddress;
00648 int res;
00649
00650 DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific));
00651 DEBUGMSGOID(("trap", enterprise, enterprise_length));
00652 DEBUGMSG(( "trap", "\n"));
00653
00654 if (vars) {
00655 vblist = snmp_clone_varbind( vars );
00656 if (!vblist) {
00657 snmp_log(LOG_WARNING,
00658 "send_trap: failed to clone varbind list\n");
00659 return -1;
00660 }
00661 }
00662
00663 if ( trap == -1 ) {
00664
00665
00666
00667 if (!vblist) {
00668 snmp_log(LOG_WARNING,
00669 "send_trap: called with NULL v2 information\n");
00670 return -1;
00671 }
00672 template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
00673 if (!template_v2pdu) {
00674 snmp_log(LOG_WARNING,
00675 "send_trap: failed to construct v2 template PDU\n");
00676 snmp_free_varbind(vblist);
00677 return -1;
00678 }
00679
00680
00681
00682
00683
00684
00685 if (!snmp_oid_compare( vblist->name, vblist->name_length,
00686 sysuptime_oid, sysuptime_oid_len )) {
00687 template_v2pdu->variables = vblist;
00688 trap_vb = vblist->next_variable;
00689 } else {
00690 uptime = netsnmp_get_agent_uptime();
00691 var = NULL;
00692 snmp_varlist_add_variable( &var,
00693 sysuptime_oid, sysuptime_oid_len,
00694 ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime));
00695 if (!var) {
00696 snmp_log(LOG_WARNING,
00697 "send_trap: failed to insert sysUptime varbind\n");
00698 snmp_free_pdu(template_v2pdu);
00699 snmp_free_varbind(vblist);
00700 return -1;
00701 }
00702 template_v2pdu->variables = var;
00703 var->next_variable = vblist;
00704 trap_vb = vblist;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713 if (!trap_vb ||
00714 snmp_oid_compare(trap_vb->name, trap_vb->name_length,
00715 snmptrap_oid, snmptrap_oid_len)) {
00716 snmp_log(LOG_WARNING,
00717 "send_trap: no v2 trapOID varbind provided\n");
00718 snmp_free_pdu(template_v2pdu);
00719 return -1;
00720 }
00721 if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
00722 trap_prefix, OID_LENGTH(trap_prefix))) {
00723 var = find_varbind_in_list( template_v2pdu->variables,
00724 snmptrapenterprise_oid,
00725 snmptrapenterprise_oid_len);
00726 if (!var &&
00727 !snmp_varlist_add_variable( &(template_v2pdu->variables),
00728 snmptrapenterprise_oid, snmptrapenterprise_oid_len,
00729 ASN_OBJECT_ID,
00730 (char*)enterprise, enterprise_length*sizeof(oid))) {
00731 snmp_log(LOG_WARNING,
00732 "send_trap: failed to add snmpEnterprise to v2 trap\n");
00733 snmp_free_pdu(template_v2pdu);
00734 return -1;
00735 }
00736 }
00737
00738
00739
00740
00741
00742 template_v1pdu = convert_v2pdu_to_v1( template_v2pdu );
00743 if (!template_v1pdu) {
00744 snmp_log(LOG_WARNING,
00745 "send_trap: failed to convert v2->v1 template PDU\n");
00746 }
00747
00748 } else {
00749
00750
00751
00752 template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP);
00753 if (!template_v1pdu) {
00754 snmp_log(LOG_WARNING,
00755 "send_trap: failed to construct v1 template PDU\n");
00756 snmp_free_varbind(vblist);
00757 return -1;
00758 }
00759 template_v1pdu->trap_type = trap;
00760 template_v1pdu->specific_type = specific;
00761 template_v1pdu->time = netsnmp_get_agent_uptime();
00762
00763 if (snmp_clone_mem((void **) &template_v1pdu->enterprise,
00764 enterprise, enterprise_length * sizeof(oid))) {
00765 snmp_log(LOG_WARNING,
00766 "send_trap: failed to set v1 enterprise OID\n");
00767 snmp_free_varbind(vblist);
00768 snmp_free_pdu(template_v1pdu);
00769 return -1;
00770 }
00771 template_v1pdu->enterprise_length = enterprise_length;
00772
00773 template_v1pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;
00774 template_v1pdu->variables = vblist;
00775
00776
00777
00778
00779
00780 template_v2pdu = convert_v1pdu_to_v2( template_v1pdu );
00781 if (!template_v2pdu) {
00782 snmp_log(LOG_WARNING,
00783 "send_trap: failed to convert v1->v2 template PDU\n");
00784 }
00785 }
00786
00787
00788
00789
00790 if (template_v1pdu) {
00791 if (template_v1pdu->trap_type == SNMP_TRAP_AUTHFAIL &&
00792 snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) {
00793 snmp_free_pdu(template_v1pdu);
00794 snmp_free_pdu(template_v2pdu);
00795 return 0;
00796 }
00797
00798
00799
00800
00801 pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr;
00802 v1trapaddress = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
00803 NETSNMP_DS_AGENT_TRAP_ADDR);
00804 if (v1trapaddress != NULL) {
00805
00806 res = netsnmp_gethostbyname_v4(v1trapaddress, pdu_in_addr_t);
00807 }
00808 if (v1trapaddress == NULL || res < 0) {
00809
00810
00811 *pdu_in_addr_t = get_myaddr();
00812 }
00813
00814 }
00815
00816
00817
00818 if (context != NULL)
00819 {
00820 template_v2pdu->contextName = strdup(context);
00821 template_v2pdu->contextNameLen = strlen(context);
00822 }
00823
00824
00825
00826
00827
00828
00829 for (sink = sinks; sink; sink = sink->next) {
00830 #ifndef NETSNMP_DISABLE_SNMPV1
00831 if (sink->version == SNMP_VERSION_1) {
00832 if (template_v1pdu) {
00833 send_trap_to_sess(sink->sesp, template_v1pdu);
00834 }
00835 } else {
00836 #endif
00837 if (template_v2pdu) {
00838 template_v2pdu->command = sink->pdutype;
00839 send_trap_to_sess(sink->sesp, template_v2pdu);
00840 }
00841 #ifndef NETSNMP_DISABLE_SNMPV1
00842 }
00843 #endif
00844 }
00845 if (template_v1pdu)
00846 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
00847 SNMPD_CALLBACK_SEND_TRAP1, template_v1pdu);
00848 if (template_v2pdu)
00849 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
00850 SNMPD_CALLBACK_SEND_TRAP2, template_v2pdu);
00851 snmp_free_pdu(template_v1pdu);
00852 snmp_free_pdu(template_v2pdu);
00853 return 0;
00854 }
00855
00856
00857 void
00858 send_enterprise_trap_vars(int trap,
00859 int specific,
00860 oid * enterprise, int enterprise_length,
00861 netsnmp_variable_list * vars)
00862 {
00863 netsnmp_send_traps(trap, specific,
00864 enterprise, enterprise_length,
00865 vars, NULL, 0);
00866 return;
00867 }
00868
00874 int
00875 handle_inform_response(int op, netsnmp_session * session,
00876 int reqid, netsnmp_pdu *pdu,
00877 void *magic)
00878 {
00879
00880 switch (op) {
00881
00882 case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
00883 snmp_increment_statistic(STAT_SNMPINPKTS);
00884 DEBUGMSGTL(("trap", "received the inform response for reqid=%d\n",
00885 reqid));
00886 break;
00887
00888 case NETSNMP_CALLBACK_OP_TIMED_OUT:
00889 DEBUGMSGTL(("trap",
00890 "received a timeout sending an inform for reqid=%d\n",
00891 reqid));
00892 break;
00893
00894 case NETSNMP_CALLBACK_OP_SEND_FAILED:
00895 DEBUGMSGTL(("trap",
00896 "failed to send an inform for reqid=%d\n",
00897 reqid));
00898 break;
00899
00900 default:
00901 DEBUGMSGTL(("trap", "received op=%d for reqid=%d when trying to send an inform\n", op, reqid));
00902 }
00903
00904 return 1;
00905 }
00906
00907
00908
00909
00910
00911
00912 void
00913 send_trap_to_sess(netsnmp_session * sess, netsnmp_pdu *template_pdu)
00914 {
00915 netsnmp_pdu *pdu;
00916 int result;
00917 char tmp[SPRINT_MAX_LEN];
00918 int len;
00919
00920
00921 if (!sess || !template_pdu)
00922 return;
00923
00924 DEBUGMSGTL(("trap", "sending trap type=%d, version=%ld\n",
00925 template_pdu->command, sess->version));
00926
00927 #ifndef NETSNMP_DISABLE_SNMPV1
00928 if (sess->version == SNMP_VERSION_1 &&
00929 (template_pdu->command != SNMP_MSG_TRAP))
00930 return;
00931 if (sess->version != SNMP_VERSION_1 &&
00932 (template_pdu->command == SNMP_MSG_TRAP))
00933 return;
00934 #endif
00935 template_pdu->version = sess->version;
00936 pdu = snmp_clone_pdu(template_pdu);
00937 pdu->sessid = sess->sessid;
00938
00939 if ( template_pdu->command == SNMP_MSG_INFORM
00940 #ifdef USING_AGENTX_PROTOCOL_MODULE
00941 || template_pdu->command == AGENTX_MSG_NOTIFY
00942 #endif
00943 ) {
00944 result =
00945 snmp_async_send(sess, pdu, &handle_inform_response, NULL);
00946
00947 } else {
00948 if ((sess->version == SNMP_VERSION_3) &&
00949 (pdu->command == SNMP_MSG_TRAP2) &&
00950 (pdu->securityEngineIDLen == 0)) {
00951 len = snmpv3_get_engineID(tmp, sizeof(tmp));
00952 memdup(&pdu->securityEngineID, tmp, len);
00953 pdu->securityEngineIDLen = len;
00954 }
00955
00956 result = snmp_send(sess, pdu);
00957 }
00958
00959 if (result == 0) {
00960 snmp_sess_perror("snmpd: send_trap", sess);
00961 snmp_free_pdu(pdu);
00962 } else {
00963 snmp_increment_statistic(STAT_SNMPOUTTRAPS);
00964 snmp_increment_statistic(STAT_SNMPOUTPKTS);
00965 }
00966 }
00967
00968 void
00969 send_trap_vars(int trap, int specific, netsnmp_variable_list * vars)
00970 {
00971 if (trap == SNMP_TRAP_ENTERPRISESPECIFIC)
00972 send_enterprise_trap_vars(trap, specific, objid_enterprisetrap,
00973 OID_LENGTH(objid_enterprisetrap), vars);
00974 else
00975 send_enterprise_trap_vars(trap, specific, trap_version_id,
00976 OID_LENGTH(trap_version_id), vars);
00977 }
00978
00979
00980 void send_trap_vars_with_context(int trap, int specific,
00981 netsnmp_variable_list *vars, char *context)
00982 {
00983 if (trap == SNMP_TRAP_ENTERPRISESPECIFIC)
00984 netsnmp_send_traps(trap, specific, objid_enterprisetrap,
00985 OID_LENGTH(objid_enterprisetrap), vars,
00986 context, 0);
00987 else
00988 netsnmp_send_traps(trap, specific, trap_version_id,
00989 OID_LENGTH(trap_version_id), vars,
00990 context, 0);
00991
00992 }
00993
01017 void
01018 send_easy_trap(int trap, int specific)
01019 {
01020 send_trap_vars(trap, specific, NULL);
01021 }
01022
01046 void
01047 send_v2trap(netsnmp_variable_list * vars)
01048 {
01049 send_trap_vars(-1, -1, vars);
01050 }
01051
01064 void send_v3trap(netsnmp_variable_list *vars, char *context)
01065 {
01066 netsnmp_send_traps(-1, -1,
01067 trap_version_id, OID_LENGTH(trap_version_id),
01068 vars, context, 0);
01069 }
01070
01071 void
01072 send_trap_pdu(netsnmp_pdu *pdu)
01073 {
01074 send_trap_vars(-1, -1, pdu->variables);
01075 }
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085 void
01086 snmpd_parse_config_authtrap(const char *token, char *cptr)
01087 {
01088 int i;
01089
01090 i = atoi(cptr);
01091 if (i == 0) {
01092 if (strcmp(cptr, "enable") == 0) {
01093 i = SNMP_AUTHENTICATED_TRAPS_ENABLED;
01094 } else if (strcmp(cptr, "disable") == 0) {
01095 i = SNMP_AUTHENTICATED_TRAPS_DISABLED;
01096 }
01097 }
01098 if (i < 1 || i > 2) {
01099 config_perror("authtrapenable must be 1 or 2");
01100 } else {
01101 if (strcmp(token, "pauthtrapenable") == 0) {
01102 if (snmp_enableauthentrapsset < 0) {
01103
01104
01105
01106
01107
01108 snmp_log(LOG_WARNING,
01109 "ignoring attempted override of read-only snmpEnableAuthenTraps.0\n");
01110 return;
01111 } else {
01112 snmp_enableauthentrapsset++;
01113 }
01114 } else {
01115 if (snmp_enableauthentrapsset > 0) {
01116
01117
01118
01119
01120
01121 snmp_log(LOG_WARNING,
01122 "ignoring attempted override of read-only snmpEnableAuthenTraps.0\n");
01123
01124
01125
01126 }
01127 snmp_enableauthentrapsset = -1;
01128 }
01129 snmp_enableauthentraps = i;
01130 }
01131 }
01132
01133 #ifndef NETSNMP_DISABLE_SNMPV1
01134 void
01135 snmpd_parse_config_trapsink(const char *token, char *cptr)
01136 {
01137 char *sp, *cp, *pp = NULL;
01138 char *st;
01139
01140 if (!snmp_trapcommunity)
01141 snmp_trapcommunity = strdup("public");
01142 sp = strtok_r(cptr, " \t\n", &st);
01143 cp = strtok_r(NULL, " \t\n", &st);
01144 if (cp)
01145 pp = strtok_r(NULL, " \t\n", &st);
01146 if (pp)
01147 config_pwarn("The separate port argument to trapsink is deprecated");
01148 if (create_v1_trap_session(sp, pp, cp ? cp : snmp_trapcommunity) == 0) {
01149 netsnmp_config_error("cannot create trapsink: %s", cptr);
01150 }
01151 }
01152 #endif
01153
01154 #ifndef NETSNMP_DISABLE_SNMPV2C
01155 void
01156 snmpd_parse_config_trap2sink(const char *word, char *cptr)
01157 {
01158 char *st, *sp, *cp, *pp = NULL;
01159
01160 if (!snmp_trapcommunity)
01161 snmp_trapcommunity = strdup("public");
01162 sp = strtok_r(cptr, " \t\n", &st);
01163 cp = strtok_r(NULL, " \t\n", &st);
01164 if (cp)
01165 pp = strtok_r(NULL, " \t\n", &st);
01166 if (pp)
01167 config_pwarn("The separate port argument to trapsink2 is deprecated");
01168 if (create_v2_trap_session(sp, pp, cp ? cp : snmp_trapcommunity) == 0) {
01169 netsnmp_config_error("cannot create trap2sink: %s", cptr);
01170 }
01171 }
01172
01173 void
01174 snmpd_parse_config_informsink(const char *word, char *cptr)
01175 {
01176 char *st, *sp, *cp, *pp = NULL;
01177
01178 if (!snmp_trapcommunity)
01179 snmp_trapcommunity = strdup("public");
01180 sp = strtok_r(cptr, " \t\n", &st);
01181 cp = strtok_r(NULL, " \t\n", &st);
01182 if (cp)
01183 pp = strtok_r(NULL, " \t\n", &st);
01184 if (pp)
01185 config_pwarn("The separate port argument to informsink is deprecated");
01186 if (create_v2_inform_session(sp, pp, cp ? cp : snmp_trapcommunity) == 0) {
01187 netsnmp_config_error("cannot create informsink: %s", cptr);
01188 }
01189 }
01190 #endif
01191
01192
01193
01194
01195 #define MAX_ARGS 128
01196
01197 static int traptype;
01198
01199 static void
01200 trapOptProc(int argc, char *const *argv, int opt)
01201 {
01202 switch (opt) {
01203 case 'C':
01204 while (*optarg) {
01205 switch (*optarg++) {
01206 case 'i':
01207 traptype = SNMP_MSG_INFORM;
01208 break;
01209 default:
01210 config_perror("unknown argument passed to -C");
01211 break;
01212 }
01213 }
01214 break;
01215 }
01216 }
01217
01218
01219 void
01220 snmpd_parse_config_trapsess(const char *word, char *cptr)
01221 {
01222 char *argv[MAX_ARGS], *cp = cptr, tmp[SPRINT_MAX_LEN];
01223 int argn, arg;
01224 netsnmp_session session, *ss;
01225 size_t len;
01226
01227
01228
01229
01230 traptype = SNMP_MSG_TRAP2;
01231
01232
01233
01234
01235 argv[0] = strdup("snmpd-trapsess");
01236 for (argn = 1; cp && argn < MAX_ARGS; argn++) {
01237 cp = copy_nword(cp, tmp, SPRINT_MAX_LEN);
01238 argv[argn] = strdup(tmp);
01239 }
01240
01241 arg = snmp_parse_args(argn, argv, &session, "C:", trapOptProc);
01242
01243 ss = snmp_add(&session,
01244 netsnmp_transport_open_client("snmptrap", session.peername),
01245 NULL, NULL);
01246 for (; argn > 0; argn--) {
01247 free(argv[argn - 1]);
01248 }
01249
01250 if (!ss) {
01251 config_perror
01252 ("snmpd: failed to parse this line or the remote trap receiver is down. Possible cause:");
01253 snmp_sess_perror("snmpd: snmpd_parse_config_trapsess()", &session);
01254 return;
01255 }
01256
01257
01258
01259
01260
01261 if (ss->version == SNMP_VERSION_3 &&
01262 traptype != SNMP_MSG_INFORM &&
01263 ss->securityEngineIDLen == 0) {
01264 len = snmpv3_get_engineID( tmp, sizeof(tmp));
01265 memdup(&ss->securityEngineID, tmp, len);
01266 ss->securityEngineIDLen = len;
01267 }
01268
01269 #ifndef NETSNMP_DISABLE_SNMPV1
01270 if (ss->version == SNMP_VERSION_1) {
01271 add_trap_session(ss, SNMP_MSG_TRAP, 0, SNMP_VERSION_1);
01272 } else {
01273 #endif
01274 add_trap_session(ss, traptype, (traptype == SNMP_MSG_INFORM),
01275 ss->version);
01276 #ifndef NETSNMP_DISABLE_SNMPV1
01277 }
01278 #endif
01279 }
01280
01281 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
01282 void
01283 snmpd_parse_config_trapcommunity(const char *word, char *cptr)
01284 {
01285 if (snmp_trapcommunity != NULL) {
01286 free(snmp_trapcommunity);
01287 }
01288 snmp_trapcommunity = (char *) malloc(strlen(cptr) + 1);
01289 if (snmp_trapcommunity != NULL) {
01290 copy_nword(cptr, snmp_trapcommunity, strlen(cptr) + 1);
01291 }
01292 }
01293
01294 void
01295 snmpd_free_trapcommunity(void)
01296 {
01297 if (snmp_trapcommunity) {
01298 free(snmp_trapcommunity);
01299 snmp_trapcommunity = NULL;
01300 }
01301 }
01302 #endif
01303