| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194 |
- #include "net-snmp/net-snmp-config.h"
- #include "net-snmp/net-snmp-features.h"
- #if HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <stdio.h>
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #include <ctype.h>
- #include <sys/types.h>
- #if HAVE_ARPA_INET_H
- #include <arpa/inet.h>
- #endif
- #if HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #if HAVE_NETDB_H
- #include <netdb.h>
- #endif
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
- extern "C" {
- #include "net-snmp/config_api.h"
- #include "net-snmp/output_api.h"
- #include "net-snmp/mib_api.h"
- #include "net-snmp/utilities.h"
-
- #include "net-snmp/net-snmp-includes.h"
- #include "net-snmp/agent/net-snmp-agent-includes.h"
- #include "net-snmp/agent/mibgroup/utilities/execute.h"
- #include "snmptrapd_handlers.h"
- #include "snmptrapd_auth.h"
- #include "snmptrapd_log.h"
- #include "net-snmp/agent/mibgroup/notification-log-mib/notification_log.h"
-
- netsnmp_feature_child_of(add_default_traphandler, snmptrapd);
- }
- char *syslog_format1 = NULL;
- char *syslog_format2 = NULL;
- char *print_format1 = NULL;
- char *print_format2 = NULL;
- char *exec_format1 = NULL;
- char *exec_format2 = NULL;
- int SyslogTrap = 0;
- int dropauth = 0;
- const char *trap1_std_str = "%.4y-%.2m-%.2l %.2h:%.2j:%.2k %B [%b] (via %A [%a]): %N\n\t%W Trap (%q) Uptime: %#T\n%v\n";
- const char *trap2_std_str = "%.4y-%.2m-%.2l %.2h:%.2j:%.2k %B [%b]:\n%v\n";
- void snmptrapd_free_traphandle(void);
- const char *
- trap_description(int trap)
- {
- switch (trap) {
- case SNMP_TRAP_COLDSTART:
- return "Cold Start";
- case SNMP_TRAP_WARMSTART:
- return "Warm Start";
- case SNMP_TRAP_LINKDOWN:
- return "Link Down";
- case SNMP_TRAP_LINKUP:
- return "Link Up";
- case SNMP_TRAP_AUTHFAIL:
- return "Authentication Failure";
- case SNMP_TRAP_EGPNEIGHBORLOSS:
- return "EGP Neighbor Loss";
- case SNMP_TRAP_ENTERPRISESPECIFIC:
- return "Enterprise Specific";
- default:
- return "Unknown Type";
- }
- }
- void
- snmptrapd_parse_traphandle(const char *token, char *line)
- {
- char buf[STRINGMAX];
- oid obuf[MAX_OID_LEN];
- size_t olen = MAX_OID_LEN;
- char *cptr, *cp;
- netsnmp_trapd_handler *traph;
- int flags = 0;
- char *format = NULL;
- memset(buf, 0, sizeof(buf));
- memset(obuf, 0, sizeof(obuf));
- cptr = copy_nword(line, buf, sizeof(buf));
- if (buf[0] == '-' && buf[1] == 'F') {
- cptr = copy_nword(cptr, buf, sizeof(buf));
- format = strdup(buf);
- cptr = copy_nword(cptr, buf, sizeof(buf));
- }
- if (!cptr) {
- netsnmp_config_error("Missing traphandle command (%s)", buf);
- free(format);
- return;
- }
- DEBUGMSGTL(("read_config:traphandle", "registering handler for: "));
- if (!strcmp(buf, "default")) {
- DEBUGMSG(("read_config:traphandle", "default"));
- traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
- command_handler);
- }
- else {
- cp = buf + strlen(buf) - 1;
- if (*cp == '*') {
- flags |= NETSNMP_TRAPHANDLER_FLAG_MATCH_TREE;
- *(cp--) = '\0';
- if (*cp == '.') {
- /*
- * Distinguish between 'oid.*' & 'oid*'
- */
- flags |= NETSNMP_TRAPHANDLER_FLAG_STRICT_SUBTREE;
- *(cp--) = '\0';
- }
- }
- if (!read_objid(buf, obuf, &olen)) {
- netsnmp_config_error("Bad trap OID in traphandle directive: %s",
- buf);
- free(format);
- return;
- }
- DEBUGMSGOID(("read_config:traphandle", obuf, olen));
- traph = netsnmp_add_traphandler(command_handler, obuf, olen);
- }
- DEBUGMSG(("read_config:traphandle", "\n"));
- if (traph) {
- traph->flags = flags;
- traph->authtypes = TRAP_AUTH_EXE;
- traph->token = strdup(cptr);
- if (format) {
- traph->format = format;
- format = NULL;
- }
- }
- free(format);
- }
- static void
- parse_forward(const char *token, char *line)
- {
- char buf[STRINGMAX];
- oid obuf[MAX_OID_LEN];
- size_t olen = MAX_OID_LEN;
- char *cptr, *cp;
- netsnmp_trapd_handler *traph;
- int flags = 0;
- char *format = NULL;
- memset(buf, 0, sizeof(buf));
- memset(obuf, 0, sizeof(obuf));
- cptr = copy_nword(line, buf, sizeof(buf));
- if (buf[0] == '-' && buf[1] == 'F') {
- cptr = copy_nword(cptr, buf, sizeof(buf));
- format = strdup(buf);
- cptr = copy_nword(cptr, buf, sizeof(buf));
- }
- DEBUGMSGTL(("read_config:forward", "registering forward for: "));
- if (!strcmp(buf, "default")) {
- DEBUGMSG(("read_config:forward", "default"));
- if (!strcmp(cptr, "agentx"))
- traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
- axforward_handler);
- else
- traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
- forward_handler);
- }
- else {
- cp = buf + strlen(buf) - 1;
- if (*cp == '*') {
- flags |= NETSNMP_TRAPHANDLER_FLAG_MATCH_TREE;
- *(cp--) = '\0';
- if (*cp == '.') {
- /*
- * Distinguish between 'oid.*' & 'oid*'
- */
- flags |= NETSNMP_TRAPHANDLER_FLAG_STRICT_SUBTREE;
- *(cp--) = '\0';
- }
- }
- if (!read_objid(buf, obuf, &olen)) {
- netsnmp_config_error("Bad trap OID in forward directive: %s", buf);
- free(format);
- return;
- }
- DEBUGMSGOID(("read_config:forward", obuf, olen));
- if (!strcmp(cptr, "agentx"))
- traph = netsnmp_add_traphandler(axforward_handler, obuf, olen);
- else
- traph = netsnmp_add_traphandler(forward_handler, obuf, olen);
- }
- DEBUGMSG(("read_config:forward", "\n"));
- if (traph) {
- traph->flags = flags;
- traph->authtypes = TRAP_AUTH_NET;
- traph->token = strdup(cptr);
- if (format)
- traph->format = format;
- }
- else {
- free(format);
- }
- }
- void
- parse_format(const char *token, char *line)
- {
- char *cp, *sep;
- /*
- * Extract the first token from the value
- * which tells us which style of format this is
- */
- cp = line;
- while (*cp && !isspace((unsigned char)(*cp)))
- cp++;
- if (!(*cp)) {
- /*
- * If we haven't got anything left,
- * then this entry is malformed.
- * So report this, and give up
- */
- return;
- }
- sep = cp;
- *(cp++) = '\0';
- while (*cp && isspace((unsigned char)(*cp)))
- cp++;
- /*
- * OK - now "line" contains the format type,
- * and cp points to the actual format string.
- * So update the appropriate pointer(s).
- */
- if (!strcmp(line, "print1")) {
- SNMP_FREE(print_format1);
- print_format1 = strdup(cp);
- }
- else if (!strcmp(line, "print2")) {
- SNMP_FREE(print_format2);
- print_format2 = strdup(cp);
- }
- else if (!strcmp(line, "print")) {
- SNMP_FREE(print_format1);
- SNMP_FREE(print_format2);
- print_format1 = strdup(cp);
- print_format2 = strdup(cp);
- }
- else if (!strcmp(line, "syslog1")) {
- SNMP_FREE(syslog_format1);
- syslog_format1 = strdup(cp);
- }
- else if (!strcmp(line, "syslog2")) {
- SNMP_FREE(syslog_format2);
- syslog_format2 = strdup(cp);
- }
- else if (!strcmp(line, "syslog")) {
- SNMP_FREE(syslog_format1);
- SNMP_FREE(syslog_format2);
- syslog_format1 = strdup(cp);
- syslog_format2 = strdup(cp);
- }
- else if (!strcmp(line, "execute1")) {
- SNMP_FREE(exec_format1);
- exec_format1 = strdup(cp);
- }
- else if (!strcmp(line, "execute2")) {
- SNMP_FREE(exec_format2);
- exec_format2 = strdup(cp);
- }
- else if (!strcmp(line, "execute")) {
- SNMP_FREE(exec_format1);
- SNMP_FREE(exec_format2);
- exec_format1 = strdup(cp);
- exec_format2 = strdup(cp);
- }
- *sep = ' ';
- }
- static void
- parse_trap1_fmt(const char *token, char *line)
- {
- print_format1 = strdup(line);
- }
- void
- free_trap1_fmt(void)
- {
- if (print_format1 && print_format1 != trap1_std_str)
- free((char *)print_format1);
- print_format1 = NULL;
- }
- static void
- parse_trap2_fmt(const char *token, char *line)
- {
- print_format2 = strdup(line);
- }
- void
- free_trap2_fmt(void)
- {
- if (print_format2 && print_format2 != trap2_std_str)
- free((char *)print_format2);
- print_format2 = NULL;
- }
- void
- snmptrapd_register_configs(void)
- {
- register_config_handler("snmptrapd", "traphandle",
- snmptrapd_parse_traphandle,
- snmptrapd_free_traphandle,
- "oid|\"default\" program [args ...] ");
- register_config_handler("snmptrapd", "format1",
- parse_trap1_fmt, free_trap1_fmt, "format");
- register_config_handler("snmptrapd", "format2",
- parse_trap2_fmt, free_trap2_fmt, "format");
- register_config_handler("snmptrapd", "format",
- parse_format, NULL,
- "[print{,1,2}|syslog{,1,2}|execute{,1,2}] format");
- register_config_handler("snmptrapd", "forward",
- parse_forward, NULL, "OID|\"default\" destination");
- }
- /*-----------------------------
- *
- * Routines to implement a "registry" of trap handlers
- *
- *-----------------------------*/
- netsnmp_trapd_handler *netsnmp_auth_global_traphandlers = NULL;
- netsnmp_trapd_handler *netsnmp_pre_global_traphandlers = NULL;
- netsnmp_trapd_handler *netsnmp_post_global_traphandlers = NULL;
- netsnmp_trapd_handler *netsnmp_default_traphandlers = NULL;
- netsnmp_trapd_handler *netsnmp_specific_traphandlers = NULL;
- typedef struct netsnmp_handler_map_t {
- netsnmp_trapd_handler **handler;
- const char *descr;
- } netsnmp_handler_map;
- static netsnmp_handler_map handlers[] = {
- { &netsnmp_auth_global_traphandlers, "auth trap" },
- { &netsnmp_pre_global_traphandlers, "pre-global trap" },
- { NULL, "trap specific" },
- { &netsnmp_post_global_traphandlers, "global" },
- { NULL, NULL }
- };
- /*
- * Register a new "global" traphandler,
- * to be applied to *all* incoming traps
- */
- netsnmp_trapd_handler * netsnmp_add_global_traphandler(int list, Netsnmp_Trap_Handler *handler)
- {
- netsnmp_trapd_handler *traph;
- if (!handler)
- return NULL;
- traph = SNMP_MALLOC_TYPEDEF(netsnmp_trapd_handler);
- if (!traph)
- return NULL;
- /*
- * Add this new handler to the front of the appropriate list
- * (or should it go on the end?)
- */
- traph->handler = handler;
- traph->authtypes = TRAP_AUTH_ALL; /* callers will likely change this */
- switch (list) {
- case NETSNMPTRAPD_AUTH_HANDLER:
- traph->nexth = netsnmp_auth_global_traphandlers;
- netsnmp_auth_global_traphandlers = traph;
- break;
- case NETSNMPTRAPD_PRE_HANDLER:
- traph->nexth = netsnmp_pre_global_traphandlers;
- netsnmp_pre_global_traphandlers = traph;
- break;
- case NETSNMPTRAPD_POST_HANDLER:
- traph->nexth = netsnmp_post_global_traphandlers;
- netsnmp_post_global_traphandlers = traph;
- break;
- case NETSNMPTRAPD_DEFAULT_HANDLER:
- traph->nexth = netsnmp_default_traphandlers;
- netsnmp_default_traphandlers = traph;
- break;
- default:
- free(traph);
- return NULL;
- }
- return traph;
- }
- #ifndef NETSNMP_FEATURE_REMOVE_ADD_DEFAULT_TRAPHANDLER
- /*
- * Register a new "default" traphandler, to be applied to all
- * traps with no specific trap handlers of their own.
- */
- netsnmp_trapd_handler *
- netsnmp_add_default_traphandler(Netsnmp_Trap_Handler *handler) {
- return netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
- handler);
- }
- #endif /* NETSNMP_FEATURE_REMOVE_ADD_DEFAULT_TRAPHANDLER */
- /*
- * Register a new trap-specific traphandler
- */
- netsnmp_trapd_handler *
- netsnmp_add_traphandler(Netsnmp_Trap_Handler* handler,
- oid *trapOid, int trapOidLen) {
- netsnmp_trapd_handler *traph, *traph2;
- if (!handler)
- return NULL;
- traph = SNMP_MALLOC_TYPEDEF(netsnmp_trapd_handler);
- if (!traph)
- return NULL;
- /*
- * Populate this new handler with the trap information
- * (NB: the OID fields were not used in the default/global lists)
- */
- traph->authtypes = TRAP_AUTH_ALL; /* callers will likely change this */
- traph->handler = handler;
- traph->trapoid_len = trapOidLen;
- traph->trapoid = snmp_duplicate_objid(trapOid, trapOidLen);
- /*
- * Now try to find the appropriate place in the trap-specific
- * list for this particular trap OID. If there's a matching OID
- * already, then find it. Otherwise find the one that follows.
- * If we run out of entried, the new one should be tacked onto the end.
- */
- for (traph2 = netsnmp_specific_traphandlers;
- traph2; traph2 = traph2->nextt) {
- /* XXX - check this! */
- if (snmp_oid_compare(traph2->trapoid, traph2->trapoid_len,
- trapOid, trapOidLen) <= 0)
- break;
- }
- if (traph2) {
- /*
- * OK - We've either got an exact match, or we've found the
- * entry *after* where the new one should go.
- */
- if (!snmp_oid_compare(traph->trapoid, traph->trapoid_len,
- traph2->trapoid, traph2->trapoid_len)) {
- /*
- * Exact match, so find the end of the *handler* list
- * and tack on this new entry...
- */
- while (traph2->nexth)
- traph2 = traph2->nexth;
- traph2->nexth = traph;
- traph->nextt = traph2->nextt; /* Might as well... */
- traph->prevt = traph2->prevt;
- }
- else {
- /*
- * .. or the following entry, so insert the new one before it.
- */
- traph->prevt = traph2->prevt;
- if (traph2->prevt)
- traph2->prevt->nextt = traph;
- else
- netsnmp_specific_traphandlers = traph;
- traph2->prevt = traph;
- traph->nextt = traph2;
- }
- }
- else {
- /*
- * If we've run out of entries without finding a suitable spot,
- * the new one should be tacked onto the end.....
- */
- if (netsnmp_specific_traphandlers) {
- traph2 = netsnmp_specific_traphandlers;
- while (traph2->nextt)
- traph2 = traph2->nextt;
- traph2->nextt = traph;
- traph->prevt = traph2;
- }
- else {
- /*
- * .... unless this is the very first entry, of course!
- */
- netsnmp_specific_traphandlers = traph;
- }
- }
- return traph;
- }
- void
- snmptrapd_free_traphandle(void)
- {
- netsnmp_trapd_handler *traph = NULL, *nextt = NULL, *nexth = NULL;
- DEBUGMSGTL(("snmptrapd", "Freeing trap handler lists\n"));
- /*
- * Free default trap handlers
- */
- traph = netsnmp_default_traphandlers;
- /* loop over handlers */
- while (traph) {
- DEBUGMSG(("snmptrapd", "Freeing default trap handler\n"));
- nexth = traph->nexth;
- SNMP_FREE(traph->token);
- SNMP_FREE(traph);
- traph = nexth;
- }
- netsnmp_default_traphandlers = NULL;
- /*
- * Free specific trap handlers
- */
- traph = netsnmp_specific_traphandlers;
- /* loop over traps */
- while (traph) {
- nextt = traph->nextt;
- /* loop over handlers for this trap */
- while (traph) {
- DEBUGMSG(("snmptrapd", "Freeing specific trap handler\n"));
- nexth = traph->nexth;
- SNMP_FREE(traph->token);
- SNMP_FREE(traph->trapoid);
- SNMP_FREE(traph);
- traph = nexth;
- }
- traph = nextt;
- }
- netsnmp_specific_traphandlers = NULL;
- }
- /*
- * Locate the list of handlers for this particular Trap OID
- * Returns NULL if there are no relevant traps
- */
- netsnmp_trapd_handler *
- netsnmp_get_traphandler(oid *trapOid, int trapOidLen) {
- netsnmp_trapd_handler *traph;
- if (!trapOid || !trapOidLen) {
- DEBUGMSGTL(("snmptrapd:lookup", "get_traphandler no OID!\n"));
- return NULL;
- }
- DEBUGMSGTL(("snmptrapd:lookup", "Looking up Trap OID: "));
- DEBUGMSGOID(("snmptrapd:lookup", trapOid, trapOidLen));
- DEBUGMSG(("snmptrapd:lookup", "\n"));
- /*
- * Look for a matching OID, and return that list...
- */
- for (traph = netsnmp_specific_traphandlers;
- traph; traph = traph->nextt) {
- /*
- * If the trap handler wasn't wildcarded, then the trapOID
- * should match the registered OID exactly.
- */
- if (!(traph->flags & NETSNMP_TRAPHANDLER_FLAG_MATCH_TREE)) {
- if (snmp_oid_compare(traph->trapoid, traph->trapoid_len,
- trapOid, trapOidLen) == 0) {
- DEBUGMSGTL(("snmptrapd:lookup",
- "get_traphandler exact match (%p)\n", traph));
- return traph;
- }
- }
- else {
- /*
- * If the trap handler *was* wildcarded, then the trapOID
- * should have the registered OID as a prefix...
- */
- if (snmp_oidsubtree_compare(traph->trapoid,
- traph->trapoid_len,
- trapOid, trapOidLen) == 0) {
- if (traph->flags & NETSNMP_TRAPHANDLER_FLAG_STRICT_SUBTREE) {
- /*
- * ... and (optionally) *strictly* as a prefix
- * i.e. not including an exact match.
- */
- if (snmp_oid_compare(traph->trapoid, traph->trapoid_len,
- trapOid, trapOidLen) != 0) {
- DEBUGMSGTL(("snmptrapd:lookup", "get_traphandler strict subtree match (%p)\n", traph));
- return traph;
- }
- }
- else {
- DEBUGMSGTL(("snmptrapd:lookup", "get_traphandler subtree match (%p)\n", traph));
- return traph;
- }
- }
- }
- }
- /*
- * .... or failing that, return the "default" list (which may be NULL)
- */
- DEBUGMSGTL(("snmptrapd:lookup", "get_traphandler default (%p)\n",
- netsnmp_default_traphandlers));
- return netsnmp_default_traphandlers;
- }
- /*-----------------------------
- *
- * Standard traphandlers for the common requirements
- *
- *-----------------------------*/
- #define SYSLOG_V1_STANDARD_FORMAT "%a: %W Trap (%q) Uptime: %#T%#v\n"
- #define SYSLOG_V1_ENTERPRISE_FORMAT "%a: %W Trap (%q) Uptime: %#T%#v\n" /* XXX - (%q) become (.N) ??? */
- #define SYSLOG_V23_NOTIFICATION_FORMAT "%B [%b]: Trap %#v\n" /* XXX - introduces a leading " ," */
- /*
- * Trap handler for logging via syslog
- */
- int syslog_handler(netsnmp_pdu *pdu,
- netsnmp_transport *transport,
- netsnmp_trapd_handler *handler)
- {
- u_char *rbuf = NULL;
- size_t r_len = 64, o_len = 0;
- int trunc = 0;
- DEBUGMSGTL(("snmptrapd", "syslog_handler\n"));
- if (SyslogTrap)
- return NETSNMPTRAPD_HANDLER_OK;
- if ((rbuf = (u_char *)calloc(r_len, 1)) == NULL) {
- snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n");
- return NETSNMPTRAPD_HANDLER_FAIL; /* Failed but keep going */
- }
- /*
- * If there's a format string registered for this trap, then use it.
- */
- if (handler && handler->format) {
- DEBUGMSGTL(("snmptrapd", "format = '%s'\n", handler->format));
- if (*handler->format) {
- trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- handler->format, pdu, transport);
- }
- else {
- free(rbuf);
- return NETSNMPTRAPD_HANDLER_OK; /* A 0-length format string means don't log */
- }
- /*
- * Otherwise (i.e. a NULL handler format string),
- * use a standard output format setting
- * either configurable, or hardwired
- *
- * XXX - v1 traps use a different hardwired formats for
- * standard and enterprise specific traps
- * Do we actually need this?
- */
- }
- else {
- if (pdu->command == SNMP_MSG_TRAP) {
- if (syslog_format1) {
- DEBUGMSGTL(("snmptrapd", "syslog_format v1 = '%s'\n", syslog_format1));
- trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- syslog_format1, pdu, transport);
- }
- else if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
- DEBUGMSGTL(("snmptrapd", "v1 enterprise format\n"));
- trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- SYSLOG_V1_ENTERPRISE_FORMAT,
- pdu, transport);
- }
- else {
- DEBUGMSGTL(("snmptrapd", "v1 standard trap format\n"));
- trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- SYSLOG_V1_STANDARD_FORMAT,
- pdu, transport);
- }
- }
- else { /* SNMPv2/3 notifications */
- if (syslog_format2) {
- DEBUGMSGTL(("snmptrapd", "syslog_format v1 = '%s'\n", syslog_format2));
- trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- syslog_format2, pdu, transport);
- }
- else {
- DEBUGMSGTL(("snmptrapd", "v2/3 format\n"));
- trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- SYSLOG_V23_NOTIFICATION_FORMAT,
- pdu, transport);
- }
- }
- }
- snmp_log(LOG_WARNING, "%s%s", rbuf, (trunc ? " [TRUNCATED]\n" : ""));
- free(rbuf);
- return NETSNMPTRAPD_HANDLER_OK;
- }
- #define EXECUTE_FORMAT "%B\n%b\n%V\n%v\n"
- /*
- * Trap handler for invoking a suitable script
- */
- int command_handler(netsnmp_pdu *pdu,
- netsnmp_transport *transport,
- netsnmp_trapd_handler *handler)
- {
- #ifndef USING_UTILITIES_EXECUTE_MODULE
- NETSNMP_LOGONCE((LOG_WARNING,
- "support for run_shell_command not available\n"));
- return NETSNMPTRAPD_HANDLER_FAIL;
- #else
- u_char *rbuf = NULL;
- size_t r_len = 64, o_len = 0;
- int oldquick;
- DEBUGMSGTL(("snmptrapd", "command_handler\n"));
- DEBUGMSGTL(("snmptrapd", "token = '%s'\n", handler->token));
- if (handler && handler->token && *handler->token) {
- netsnmp_pdu *v2_pdu = NULL;
- if (pdu->command == SNMP_MSG_TRAP)
- v2_pdu = convert_v1pdu_to_v2(pdu);
- else
- v2_pdu = pdu;
- oldquick = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_QUICK_PRINT);
- netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_QUICK_PRINT, 1);
- /*
- * Format the trap and pass this string to the external command
- */
- if ((rbuf = (u_char *)calloc(r_len, 1)) == NULL) {
- snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n");
- return NETSNMPTRAPD_HANDLER_FAIL; /* Failed but keep going */
- }
- /*
- * If there's a format string registered for this trap, then use it.
- * Otherwise use the standard execution format setting.
- */
- if (handler && handler->format && *handler->format) {
- DEBUGMSGTL(("snmptrapd", "format = '%s'\n", handler->format));
- realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- handler->format,
- v2_pdu, transport);
- }
- else {
- if (pdu->command == SNMP_MSG_TRAP && exec_format1) {
- DEBUGMSGTL(("snmptrapd", "exec v1 = '%s'\n", exec_format1));
- realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- exec_format1, pdu, transport);
- }
- else if (pdu->command != SNMP_MSG_TRAP && exec_format2) {
- DEBUGMSGTL(("snmptrapd", "exec v2/3 = '%s'\n", exec_format2));
- realloc_format_trap(&rbuf, &r_len, &o_len, 1,
- exec_format2, pdu, transport);
- }
- else {
- DEBUGMSGTL(("snmptrapd", "execute format\n"));
- realloc_format_trap(&rbuf, &r_len, &o_len, 1, EXECUTE_FORMAT,
- v2_pdu, transport);
- }
- }
- /*
- * and pass this formatted string to the command specified
- */
- run_shell_command(handler->token, (char*)rbuf, NULL, NULL); /* Not interested in output */
- netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_QUICK_PRINT, oldquick);
- if (pdu->command == SNMP_MSG_TRAP)
- snmp_free_pdu(v2_pdu);
- free(rbuf);
- }
- return NETSNMPTRAPD_HANDLER_OK;
- #endif /* !def USING_UTILITIES_EXECUTE_MODULE */
- }
- /*
- * Trap handler for forwarding to the AgentX master agent
- */
- int axforward_handler(netsnmp_pdu *pdu,
- netsnmp_transport *transport,
- netsnmp_trapd_handler *handler)
- {
- send_v2trap(pdu->variables);
- return NETSNMPTRAPD_HANDLER_OK;
- }
- static int add_forwarder_info(netsnmp_pdu *pdu, netsnmp_pdu *pdu2)
- {
- netsnmp_indexed_addr_pair *addr_pair1;
- struct sockaddr_in *to1 = NULL;
- struct sockaddr_in *to2 = NULL;
- int last_snmpTrapAddress_index = -1;
- /* snmpTrapAddress_oid.0 is also defined as agentaddr_oid */
- const oid snmpTrapAddress_oid[] = { 1,3,6,1,6,3,18,1,3 };
- /* each forwarder will add this OID with changed last index */
- oid forwarder_oid[] = { 1,3,6,1,6,3,18,1,3,0 };
- const size_t snmpTrapAddress_oid_size = OID_LENGTH(snmpTrapAddress_oid);
- const size_t forwarder_oid_len = OID_LENGTH(forwarder_oid);
- struct in_addr agent_addr;
- struct in_addr my_ip_addr;
- memset(&agent_addr, 0, sizeof(agent_addr));
- memset(&my_ip_addr, 0, sizeof(my_ip_addr));
- if (pdu && pdu->transport_data &&
- pdu->transport_data_length == sizeof(*addr_pair1)) {
- addr_pair1 = (netsnmp_indexed_addr_pair *)pdu->transport_data;
- /*
- * Get the IPv4 address of the host that this trap was sent from =
- * last forwarder's IP address.
- */
- if (addr_pair1->remote_addr.sa.sa_family == AF_INET) {
- to1 = (struct sockaddr_in *)&(addr_pair1->remote_addr);
- agent_addr = to1->sin_addr;
- }
- /*
- * Get the IPv4 address of the host that this trap was sent to =
- * this forwarder's IP address.
- */
- if (addr_pair1->local_addr.sa.sa_family == AF_INET) {
- to2 = (struct sockaddr_in *)&(addr_pair1->local_addr);
- my_ip_addr = to2->sin_addr;
- }
- }
- if (to1) {
- netsnmp_variable_list *vblist = NULL;
- netsnmp_variable_list *var = NULL;
- if (*(in_addr_t *)pdu2->agent_addr == INADDR_ANY) {
- /*
- * there was no agent address defined in PDU. copy the forwarding
- * agent IP address from the transport socket.
- */
- *(struct in_addr *)pdu2->agent_addr = agent_addr;
- }
- vblist = pdu2->variables;
- /*
- * Iterate over all varbinds in the PDU to see if it already has any
- * forwarder information.
- */
- for (var = vblist; var; var = var->next_variable) {
- if (snmp_oid_ncompare(var->name, var->name_length,
- snmpTrapAddress_oid,
- snmpTrapAddress_oid_size,
- snmpTrapAddress_oid_size) == 0) {
- int my_snmpTrapAddress_index =
- var->name[var->name_length - 1];
- DEBUGMSGTL(("snmptrapd", " my_snmpTrapAddress_index=%d, last_snmpTrapAddress_index=%d, my_ip_addr=%s\n",
- my_snmpTrapAddress_index,
- last_snmpTrapAddress_index,
- inet_ntoa(my_ip_addr)));
- if (last_snmpTrapAddress_index < my_snmpTrapAddress_index)
- last_snmpTrapAddress_index = my_snmpTrapAddress_index;
- /* Detect forwarding loop. */
- if (var->val_len < 4) {
- snmp_log(LOG_ERR, "Length of IP address of OID .1.3.6.1.6.3.18.1.3.%d in PDU is less than %d bytes = %d\n",
- my_snmpTrapAddress_index, 4,
- (int)var->val_len);
- }
- else {
- if (to2 &&
- memcmp(var->val.string, &my_ip_addr, 4) == 0) {
- snmp_log(LOG_ERR, "Forwarding loop detected, OID .1.3.6.1.6.3.18.1.3.%d already has this forwarder's IP address=%s, not forwarding this trap\n",
- my_snmpTrapAddress_index,
- inet_ntoa(my_ip_addr));
- return 0;
- }
- if (memcmp(var->val.string, &agent_addr, 4) == 0) {
- snmp_log(LOG_ERR, "Forwarding loop detected, OID .1.3.6.1.6.3.18.1.3.%d already has the sender's IP address=%s, not forwarding this trap\n",
- my_snmpTrapAddress_index,
- inet_ntoa(agent_addr));
- return 0;
- }
- }
- }
- } /* for var in vblist */
- DEBUGMSGTL(("snmptrapd",
- " last_snmpTrapAddress_index=%d, adding index=%d\n",
- last_snmpTrapAddress_index, last_snmpTrapAddress_index + 1));
- /* Change the last index of this OID to the next avaiable number. */
- forwarder_oid[forwarder_oid_len - 1] = last_snmpTrapAddress_index + 1;
- /*
- * Add forwarder IP address as OID to trap payload. Use the value
- * from the transport, so if a v1 PDU is sent, the same IP is not
- * duplicated you want every forwarder to add this OID with its
- * own IP address.
- */
- snmp_pdu_add_variable(pdu2, forwarder_oid, forwarder_oid_len,
- ASN_IPADDRESS, (u_char *)&agent_addr, 4);
- }
- return 1;
- }
- /*
- * Trap handler for forwarding to another destination
- */
- int forward_handler(netsnmp_pdu *pdu,
- netsnmp_transport *transport,
- netsnmp_trapd_handler *handler)
- {
- netsnmp_session session, *ss;
- netsnmp_pdu *pdu2;
- char buf[BUFSIZ], *cp;
- DEBUGMSGTL(("snmptrapd", "forward_handler (%s)\n", handler->token));
- snmp_sess_init(&session);
- if (strchr(handler->token, ':') == NULL) {
- snprintf(buf, BUFSIZ, "%s:%d", handler->token, SNMP_TRAP_PORT);
- cp = buf;
- }
- else {
- cp = handler->token;
- }
- session.peername = cp;
- session.version = pdu->version;
- ss = snmp_open(&session);
- if (!ss)
- return NETSNMPTRAPD_HANDLER_FAIL;
- /* XXX: wjh we should be caching sessions here and not always
- reopening a session. It's very ineffecient, especially with v3
- INFORMS which may require engineID probing */
- pdu2 = snmp_clone_pdu(pdu);
- if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_ADD_FORWARDER_INFO) &&
- !add_forwarder_info(pdu, pdu2)) {
- snmp_close(ss);
- return NETSNMPTRAPD_HANDLER_FAIL;
- }
- if (pdu2->transport_data) {
- free(pdu2->transport_data);
- pdu2->transport_data = NULL;
- pdu2->transport_data_length = 0;
- }
- ss->s_snmp_errno = SNMPERR_SUCCESS;
- if (!snmp_send(ss, pdu2) &&
- ss->s_snmp_errno != SNMPERR_SUCCESS) {
- snmp_sess_perror("Forward failed", ss);
- snmp_free_pdu(pdu2);
- }
- snmp_close(ss);
- return NETSNMPTRAPD_HANDLER_OK;
- }
- #if defined(USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE) && defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
- /*
- * "Notification" handler for implementing NOTIFICATION-MIB
- * (presumably)
- */
- int notification_handler(netsnmp_pdu *pdu,
- netsnmp_transport *transport,
- netsnmp_trapd_handler *handler)
- {
- DEBUGMSGTL(("snmptrapd", "notification_handler\n"));
- log_notification(pdu, transport);
- return NETSNMPTRAPD_HANDLER_OK;
- }
- #endif
- /*-----------------------------
- *
- * Main driving code, to process an incoming trap
- *
- *-----------------------------*/
- int
- snmp_input(int op, netsnmp_session *session,
- int reqid, netsnmp_pdu *pdu, void *magic)
- {
- oid stdTrapOidRoot[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
- oid snmpTrapOid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
- oid trapOid[MAX_OID_LEN + 2] = { 0 };
- int trapOidLen;
- netsnmp_variable_list *vars;
- netsnmp_trapd_handler *traph;
- netsnmp_transport *transport = (netsnmp_transport *)magic;
- int ret, idx;
- //printf("snmp_input \n");
- switch (op) {
- case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
- /*
- * Drops packets with reception problems
- */
- if (session->s_snmp_errno) {
- /* drop problem packets */
- return 1;
- }
- /*
- * Determine the OID that identifies the trap being handled
- */
- DEBUGMSGTL(("snmptrapd", "input: %x\n", pdu->command));
- switch (pdu->command) {
- case SNMP_MSG_TRAP:
- /*
- * Convert v1 traps into a v2-style trap OID
- * (following RFC 2576)
- */
- if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
- trapOidLen = pdu->enterprise_length;
- memcpy(trapOid, pdu->enterprise, sizeof(oid) * trapOidLen);
- if (trapOid[trapOidLen - 1] != 0) {
- trapOid[trapOidLen++] = 0;
- }
- trapOid[trapOidLen++] = pdu->specific_type;
- }
- else {
- memcpy(trapOid, stdTrapOidRoot, sizeof(stdTrapOidRoot));
- trapOidLen = OID_LENGTH(stdTrapOidRoot); /* 9 */
- trapOid[trapOidLen++] = pdu->trap_type + 1;
- }
- break;
- case SNMP_MSG_TRAP2:
- case SNMP_MSG_INFORM:
- /*
- * v2c/v3 notifications *should* have snmpTrapOID as the
- * second varbind, so we can go straight there.
- * But check, just to make sure
- */
- vars = pdu->variables;
- if (vars)
- vars = vars->next_variable;
- if (!vars || snmp_oid_compare(vars->name, vars->name_length,
- snmpTrapOid, OID_LENGTH(snmpTrapOid))) {
- /*
- * Didn't find it!
- * Let's look through the full list....
- */
- for (vars = pdu->variables; vars; vars = vars->next_variable) {
- if (!snmp_oid_compare(vars->name, vars->name_length,
- snmpTrapOid, OID_LENGTH(snmpTrapOid)))
- break;
- }
- if (!vars) {
- /*
- * Still can't find it! Give up.
- */
- snmp_log(LOG_ERR, "Cannot find TrapOID in TRAP2 PDU\n");
- return 1; /* ??? */
- }
- }
- memcpy(trapOid, vars->val.objid, vars->val_len);
- trapOidLen = vars->val_len / sizeof(oid);
- break;
- default:
- /* SHOULDN'T HAPPEN! */
- return 1; /* ??? */
- }
- DEBUGMSGTL(("snmptrapd", "Trap OID: "));
- DEBUGMSGOID(("snmptrapd", trapOid, trapOidLen));
- DEBUGMSG(("snmptrapd", "\n"));
- /*
- * OK - We've found the Trap OID used to identify this trap.
- * Call each of the various lists of handlers:
- * a) authentication-related handlers,
- * b) other handlers to be applied to all traps
- * (*before* trap-specific handlers)
- * c) the handler(s) specific to this trap
- t * d) any other global handlers
- *
- * In each case, a particular trap handler can abort further
- * processing - either just for that particular list,
- * or for the trap completely.
- *
- * This is particularly designed for authentication-related
- * handlers, but can also be used elsewhere.
- *
- * OK - Enough waffling, let's get to work.....
- */
- for (idx = 0; handlers[idx].descr; ++idx) {
- DEBUGMSGTL(("snmptrapd", "Running %s handlers\n",
- handlers[idx].descr));
- if (NULL == handlers[idx].handler) /* specific */
- traph = netsnmp_get_traphandler(trapOid, trapOidLen);
- else
- traph = *handlers[idx].handler;
- for (; traph; traph = traph->nexth) {
- if (!netsnmp_trapd_check_auth(traph->authtypes))
- continue; /* we continue on and skip this one */
- ret = (*(traph->handler))(pdu, transport, traph);
- if (NETSNMPTRAPD_HANDLER_FINISH == ret)
- return 1;
- if (ret == NETSNMPTRAPD_HANDLER_BREAK)
- break; /* move on to next type */
- } /* traph */
- } /* handlers */
- if (pdu->command == SNMP_MSG_INFORM) {
- netsnmp_pdu *reply = snmp_clone_pdu(pdu);
- if (!reply) {
- snmp_log(LOG_ERR, "couldn't clone PDU for INFORM response\n");
- }
- else {
- reply->command = SNMP_MSG_RESPONSE;
- reply->errstat = 0;
- reply->errindex = 0;
- if (!snmp_send(session, reply)) {
- snmp_sess_perror("snmptrapd: Couldn't respond to inform pdu",
- session);
- snmp_free_pdu(reply);
- }
- }
- }
- break;
- case NETSNMP_CALLBACK_OP_TIMED_OUT:
- snmp_log(LOG_ERR, "Timeout: This shouldn't happen!\n");
- break;
- case NETSNMP_CALLBACK_OP_SEND_FAILED:
- snmp_log(LOG_ERR, "Send Failed: This shouldn't happen either!\n");
- break;
- case NETSNMP_CALLBACK_OP_CONNECT:
- case NETSNMP_CALLBACK_OP_DISCONNECT:
- /* Ignore silently */
- break;
- default:
- snmp_log(LOG_ERR, "Unknown operation (%d): This shouldn't happen!\n", op);
- break;
- }
- return 0;
- }
|