void shutdown_snmp_logging(void) { snmp_disable_log(); while(NULL != logh_head) netsnmp_remove_loghandler( logh_head ); }
int snmp_log_options(char *optarg, int argc, char *const *argv) { char *cp = optarg; /* * Hmmm... this doesn't seem to work. * The main agent 'getopt' handling assumes * that the -L option takes an argument, * and objects if this is missing. * Trying to differentiate between * new-style "-Lx", and old-style "-L xx" * is likely to be a major headache. */ char missing_opt = 'e'; /* old -L is new -Le */ int priority = LOG_DEBUG; int pri_max = LOG_EMERG; int inc_optind = 0; netsnmp_log_handler *logh; DEBUGMSGT(("logging:options", "optarg: '%s', argc %d, argv '%s'\n", optarg, argc, argv ? argv[0] : "NULL")); optarg++; if (!*cp) cp = &missing_opt; /* * Support '... -Lx=value ....' syntax */ if (*optarg == '=') { optarg++; } /* * and '.... "-Lx value" ....' (*with* the quotes) */ while (*optarg && isspace((unsigned char)(*optarg))) { optarg++; } /* * Finally, handle ".... -Lx value ...." syntax * (*without* surrounding quotes) */ if ((!*optarg) && (NULL != argv)) { /* * We've run off the end of the argument * so move on to the next. * But we might not actually need it, so don't * increment optind just yet! */ optarg = argv[optind]; inc_optind = 1; } DEBUGMSGT(("logging:options", "*cp: '%c'\n", *cp)); switch (*cp) { #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_STDIO /* * Log to Standard Error */ case 'E': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; if (inc_optind) optind++; /* Fallthrough */ case 'e': logh = netsnmp_register_stdio_loghandler(0, priority, pri_max, "stderr"); break; /* * Log to Standard Output */ case 'O': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; if (inc_optind) optind++; /* Fallthrough */ case 'o': logh = netsnmp_register_stdio_loghandler( 1, priority, pri_max, "stdout" ); break; #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */ /* * Log to a named file */ #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_FILE case 'F': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; while (*optarg == ' ') optarg++; if (!*optarg && !argv) return -1; else if (!*optarg) optarg = argv[++optind]; /* FALL THROUGH */ case 'f': if (inc_optind) optind++; if (!optarg) { fprintf(stderr, "Missing log file\n"); return -1; } DEBUGMSGTL(("logging:options", "%d-%d: '%s'\n", priority, pri_max, optarg)); logh = netsnmp_register_filelog_handler(optarg, priority, pri_max, -1); break; #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_FILE */ #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG /* * Log to syslog */ case 'S': priority = decode_priority( &optarg, &pri_max ); if (priority == -1 || !argv) return -1; if (!optarg[0]) { /* The command line argument with priority does not contain log * facility. The facility must be in next argument then. */ optind++; if (optind < argc) optarg = argv[optind]; } /* Fallthrough */ case 's': if (inc_optind) optind++; if (!optarg) { fprintf(stderr, "Missing syslog facility\n"); return -1; } logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_SYSLOG, priority); if (logh) { int facility = decode_facility(optarg); if (facility == -1) { netsnmp_remove_loghandler(logh); return -1; } logh->pri_max = pri_max; logh->token = strdup(snmp_log_syslogname(NULL)); logh->magic = (void *)(intptr_t)facility; snmp_enable_syslog_ident(snmp_log_syslogname(NULL), facility); } break; #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ /* * Don't log */ case 'N': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; if (inc_optind) optind++; /* Fallthrough */ case 'n': /* * disable all logs to clean them up (close files, etc), * remove all log handlers, then register a null handler. */ snmp_disable_log(); while(NULL != logh_head) netsnmp_remove_loghandler( logh_head ); logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, priority); if (logh) { logh->pri_max = pri_max; } break; default: fprintf(stderr, "Unknown logging option passed to -L: %c.\n", *cp); return -1; } return 0; }
int snmp_log_options(char *optarg, int argc, char *const *argv) { char *cp = optarg; /* * Hmmm... this doesn't seem to work. * The main agent 'getopt' handling assumes * that the -L option takes an argument, * and objects if this is missing. * Trying to differentiate between * new-style "-Lx", and old-style "-L xx" * is likely to be a major headache. */ char missing_opt = 'e'; /* old -L is new -Le */ int priority = LOG_DEBUG; int pri_max = LOG_EMERG; int inc_optind = 0; netsnmp_log_handler *logh; optarg++; if (!*cp) cp = &missing_opt; /* * Support '... -Lx=value ....' syntax */ if (*optarg == '=') { optarg++; } /* * and '.... "-Lx value" ....' (*with* the quotes) */ while (*optarg && isspace(*optarg)) { optarg++; } /* * Finally, handle ".... -Lx value ...." syntax * (*without* surrounding quotes) */ if ((!*optarg) && (NULL != argv)) { /* * We've run off the end of the argument * so move on to the next. * But we might not actually need it, so don't * increment optind just yet! */ optarg = argv[optind]; inc_optind = 1; } switch (*cp) { /* * Log to Standard Error */ case 'E': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; if (inc_optind) optind++; /* Fallthrough */ case 'e': logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_STDERR, priority); if (logh) { logh->pri_max = pri_max; logh->token = strdup("stderr"); } break; /* * Log to Standard Output */ case 'O': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; if (inc_optind) optind++; /* Fallthrough */ case 'o': logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_STDERR, priority); if (logh) { logh->pri_max = pri_max; logh->token = strdup("stdout"); logh->imagic = 1; /* stdout, not stderr */ } break; /* * Log to a named file */ case 'F': priority = decode_priority( &optarg, &pri_max ); if (priority == -1 || !argv) return -1; optarg = argv[++optind]; /* Fallthrough */ case 'f': if (inc_optind) optind++; if (!optarg) { fprintf(stderr, "Missing log file\n"); return -1; } logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_FILE, priority); if (logh) { logh->pri_max = pri_max; logh->token = strdup(optarg); netsnmp_enable_filelog(logh, netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES)); } break; /* * Log to syslog */ case 'S': priority = decode_priority( &optarg, &pri_max ); if (priority == -1 || !argv) return -1; if (!optarg[0]) { /* The command line argument with priority does not contain log * facility. The facility must be in next argument then. */ optind++; if (optind < argc) optarg = argv[optind]; } /* Fallthrough */ case 's': if (inc_optind) optind++; if (!optarg) { fprintf(stderr, "Missing syslog facility\n"); return -1; } logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_SYSLOG, priority); if (logh) { int facility = decode_facility(optarg); if (facility == -1) return -1; logh->pri_max = pri_max; logh->token = strdup(snmp_log_syslogname(0)); logh->magic = (void *)(intptr_t)facility; snmp_enable_syslog_ident(snmp_log_syslogname(0), facility); } break; /* * Don't log */ case 'N': priority = decode_priority( &optarg, &pri_max ); if (priority == -1) return -1; if (inc_optind) optind++; /* Fallthrough */ case 'n': /* * disable all logs to clean them up (close files, etc), * remove all log handlers, then register a null handler. */ snmp_disable_log(); while(NULL != logh_head) netsnmp_remove_loghandler( logh_head ); logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, priority); if (logh) { logh->pri_max = pri_max; } break; default: fprintf(stderr, "Unknown logging option passed to -L: %c.\n", *cp); return -1; } return 0; }
int handle_nsLoggingTable(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { long temp; netsnmp_request_info *request = NULL; netsnmp_table_request_info *table_info = NULL; netsnmp_log_handler *logh = NULL; netsnmp_variable_list *idx = NULL; switch (reqinfo->mode) { case MODE_GET: for (request=requests; request; request=request->next) { if (request->processed != 0) continue; logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case NSLOGGING_TYPE: if (!logh) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } temp = logh->type; snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, (u_char*)&temp, sizeof(temp)); break; case NSLOGGING_MAXLEVEL: if (!logh) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } temp = logh->pri_max; snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, (u_char*)&temp, sizeof(temp)); break; case NSLOGGING_STATUS: if (!logh) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } temp = (logh->type ? (logh->enabled ? RS_ACTIVE: RS_NOTINSERVICE) : RS_NOTREADY); snmp_set_var_typed_value(request->requestvb, ASN_INTEGER, (u_char*)&temp, sizeof(temp)); break; default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); continue; } } break; #ifndef NETSNMP_NO_WRITE_SUPPORT case MODE_SET_RESERVE1: for (request=requests; request; request=request->next) { if ( request->status != 0 ) { return SNMP_ERR_NOERROR; /* Already got an error */ } logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case NSLOGGING_TYPE: if ( request->requestvb->type != ASN_INTEGER ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); return SNMP_ERR_WRONGTYPE; } if (*request->requestvb->val.integer < 0 ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); return SNMP_ERR_WRONGVALUE; } /* * It's OK to create a new logging entry * (either in one go, or built up using createAndWait) * but it's not possible to change the type of an entry * once it's been created. */ if (logh && logh->type) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE); return SNMP_ERR_NOTWRITABLE; } break; case NSLOGGING_MAXLEVEL: if ( request->requestvb->type != ASN_INTEGER ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); return SNMP_ERR_WRONGTYPE; } if (*request->requestvb->val.integer < 0 || *request->requestvb->val.integer > 7 ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); return SNMP_ERR_WRONGVALUE; } break; case NSLOGGING_STATUS: if ( request->requestvb->type != ASN_INTEGER ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE); return SNMP_ERR_WRONGTYPE; } switch ( *request->requestvb->val.integer ) { case RS_ACTIVE: case RS_NOTINSERVICE: /* * Can only work on existing rows */ if (!logh) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_INCONSISTENTVALUE); return SNMP_ERR_INCONSISTENTVALUE; } break; case RS_CREATEANDWAIT: case RS_CREATEANDGO: /* * Can only work with new rows */ if (logh) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_INCONSISTENTVALUE); return SNMP_ERR_INCONSISTENTVALUE; } /* * Normally, we'd create the row at a later stage * (probably during the RESERVE2 or ACTION passes) * * But we need to check that the values are * consistent during the ACTION pass (which is the * latest that an error can be safely handled), * so the values all need to be set up before this * (i.e. during the RESERVE2 pass) * So the new row needs to be created before that * in order to have somewhere to put them. * * That's why we're doing this here. */ idx = table_info->indexes; logh = netsnmp_register_loghandler( /* not really, but we need a valid type */ NETSNMP_LOGHANDLER_STDOUT, *idx->val.integer); if (!logh) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_GENERR); /* ??? */ return SNMP_ERR_GENERR; } idx = idx->next_variable; logh->type = 0; logh->token = strdup((char *) idx->val.string); netsnmp_insert_iterator_context(request, (void*)logh); break; case RS_DESTROY: /* * Can work with new or existing rows */ break; case RS_NOTREADY: default: netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE); return SNMP_ERR_WRONGVALUE; } break; default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); return SNMP_NOSUCHOBJECT; } } break; case MODE_SET_RESERVE2: for (request=requests; request; request=request->next) { if ( request->status != 0 ) { return SNMP_ERR_NOERROR; /* Already got an error */ } logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case NSLOGGING_TYPE: /* * If we're creating a row using createAndGo, * we need to set the type early, so that we * can validate it in the ACTION pass. * * Remember that we need to be able to reverse this */ if ( logh ) logh->type = *request->requestvb->val.integer; break; /* * Don't need to handle nsLogToken or nsLogStatus in this pass */ } } break; case MODE_SET_ACTION: for (request=requests; request; request=request->next) { if (request->processed != 0) continue; if ( request->status != 0 ) { return SNMP_ERR_NOERROR; /* Already got an error */ } logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case NSLOGGING_STATUS: /* * This is where we can check the internal consistency * of the request. Basically, for a row to be marked * 'active', then there needs to be a valid type value. */ switch ( *request->requestvb->val.integer ) { case RS_ACTIVE: case RS_CREATEANDGO: if ( !logh || !logh->type ) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_INCONSISTENTVALUE); return SNMP_ERR_INCONSISTENTVALUE; } break; } break; /* * Don't need to handle nsLogToken or nsLogType in this pass */ } } break; case MODE_SET_FREE: case MODE_SET_UNDO: /* * If any resources were allocated in either of the * two RESERVE passes, they need to be released here, * and any assignments (in RESERVE2) reversed. * * Nothing additional will have been done during ACTION * so this same code can do for UNDO as well. */ for (request=requests; request; request=request->next) { if (request->processed != 0) continue; logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case NSLOGGING_TYPE: /* * If we've been setting the type, and the request * has failed, then revert to an unset type. * * We need to be careful here - if the reason it failed is * that the type was already set, then we shouldn't "undo" * the assignment (since it won't actually have been made). * * Check the current value against the 'new' one. If they're * the same, then this is probably a successful assignment, * and the failure was elsewhere, so we need to undo it. * (Or else there was an attempt to write the same value!) */ if ( logh && logh->type == *request->requestvb->val.integer ) logh->type = 0; break; case NSLOGGING_STATUS: temp = *request->requestvb->val.integer; if ( logh && ( temp == RS_CREATEANDGO || temp == RS_CREATEANDWAIT)) { netsnmp_remove_loghandler( logh ); } break; /* * Don't need to handle nsLogToken in this pass */ } } break; case MODE_SET_COMMIT: for (request=requests; request; request=request->next) { if (request->processed != 0) continue; if ( request->status != 0 ) { return SNMP_ERR_NOERROR; /* Already got an error */ } logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request); if (!logh) { netsnmp_set_request_error(reqinfo, request, SNMP_ERR_COMMITFAILED); return SNMP_ERR_COMMITFAILED; /* Shouldn't happen! */ } table_info = netsnmp_extract_table_info(request); switch (table_info->colnum) { case NSLOGGING_MAXLEVEL: logh->pri_max = *request->requestvb->val.integer; break; case NSLOGGING_STATUS: switch (*request->requestvb->val.integer) { case RS_ACTIVE: case RS_CREATEANDGO: netsnmp_enable_this_loghandler(logh); break; case RS_NOTINSERVICE: case RS_CREATEANDWAIT: netsnmp_disable_this_loghandler(logh); break; case RS_DESTROY: netsnmp_remove_loghandler( logh ); break; } break; } } break; #endif /* !NETSNMP_NO_WRITE_SUPPORT */ } return SNMP_ERR_NOERROR; }