void snmp_log_string (int priority, const char *string) { char sbuf[40]; struct snmp_log_message slm; #if HAVE_SYSLOG_H if (do_syslogging) { syslog(priority, string); } #endif if (do_log_callback) { slm.priority = priority; slm.msg = string; snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, &slm); } if (do_filelogging || do_stderrlogging) { if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_LOG_TIMESTAMP) && newline) { sprintf_stamp(NULL, (char *)&sbuf); } else { strcpy(sbuf, ""); } newline = string[strlen(string)-1] == '\n'; if (do_filelogging) fprintf(logfile, "%s%s", sbuf, string); if (do_stderrlogging) fprintf(stderr, "%s%s", sbuf, string); } }
/* * check a session validity for connectivity to the master agent. If * not functioning, close and start attempts to reopen the session */ void agentx_check_session(unsigned int clientreg, void *clientarg) { netsnmp_session *ss = (netsnmp_session *) clientarg; if (!ss) { if (clientreg) snmp_alarm_unregister(clientreg); return; } DEBUGMSGTL(("agentx/subagent", "checking status of session %p\n", ss)); if (!agentx_send_ping(ss)) { snmp_log(LOG_WARNING, "AgentX master agent failed to respond to ping. Attempting to re-register.\n"); /* * master agent disappeared? Try and re-register. * close first, just to be sure . */ agentx_unregister_callbacks(ss); agentx_close_session(ss, AGENTX_CLOSE_TIMEOUT); snmp_alarm_unregister(clientreg); /* delete ping alarm timer */ snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_STOP, (void *) ss); snmp_close(main_session); main_session = NULL; agentx_reopen_session(0, NULL); } else { DEBUGMSGTL(("agentx/subagent", "session %p responded to ping\n", ss)); } }
int in_a_view(oid *name, /* IN - name of var, OUT - name matched */ size_t *namelen, /* IN -number of sub-ids in name*/ struct snmp_pdu *pdu, /* IN - relevant auth info re PDU */ int type) /* IN - variable type being checked */ { struct view_parameters view_parms; view_parms.pdu = pdu; view_parms.name = name; if (namelen) view_parms.namelen = *namelen; else view_parms.namelen = 0; view_parms.errorcode = 0; if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW) return 0; /* Enable bypassing of view-based access control */ /* check for v1 and counter64s, since snmpv1 doesn't support it */ if (pdu->version == SNMP_VERSION_1 && type == ASN_COUNTER64) return 5; switch (pdu->version) { case SNMP_VERSION_1: case SNMP_VERSION_2c: #ifdef CYGPKG_SNMPAGENT_V3_SUPPORT case SNMP_VERSION_3: #endif snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK, &view_parms); return view_parms.errorcode; } return 1; }
/* in_a_view: determines if a given snmp_pdu is ever going to be allowed to do anynthing or if it's not going to ever be authenticated. */ int check_access(struct snmp_pdu *pdu) /* IN - pdu being checked */ { struct view_parameters view_parms; view_parms.pdu = pdu; view_parms.name = 0; view_parms.namelen = 0; view_parms.errorcode = 0; if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW) return 0; /* Enable bypassing of view-based access control */ switch (pdu->version) { case SNMP_VERSION_1: case SNMP_VERSION_2c: #ifdef CYGPKG_SNMPAGENT_V3_SUPPORT case SNMP_VERSION_3: #endif snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK_INITIAL, &view_parms); return view_parms.errorcode; } return 1; }
void update_config(void) { snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_PRE_UPDATE_CONFIG, NULL); free_config(); read_configs(); }
/* * check a session validity for connectivity to the master agent. If * not functioning, close and start attempts to reopen the session */ void agentx_check_session (unsigned int clientreg, void *clientarg) { netsnmp_session *ss = (netsnmp_session *) clientarg; if (!ss) { if (clientreg) snmp_alarm_unregister (clientreg); return; } DEBUGMSGTL (("agentx/subagent", "checking status of session %p\n", ss)); if (!agentx_send_ping (ss)) { snmp_log (LOG_WARNING, "AgentX master agent failed to respond to ping. Attempting to re-register.\n"); /* * master agent disappeared? Try and re-register. * close first, just to be sure . */ agentx_unregister_callbacks (ss); agentx_close_session (ss, AGENTX_CLOSE_TIMEOUT); snmp_alarm_unregister (clientreg); /* delete ping alarm timer */ snmp_call_callbacks (SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_STOP, (void *) ss); register_mib_detach (); if (main_session != NULL) { remove_trap_session (ss); snmp_close (main_session); /* * We need to remove the callbacks attached to the callback * session because they have a magic callback data structure * which includes a pointer to the main session * (which is no longer valid). * * Given that the main session is not responsive anyway. * it shoudn't matter if we lose some outstanding requests. */ if (agentx_callback_sess != NULL) { snmp_close (agentx_callback_sess); agentx_callback_sess = NULL; subagent_init_callback_session (); } main_session = NULL; agentx_reopen_session (0, NULL); } else { snmp_close (main_session); main_session = NULL; } } else { DEBUGMSGTL (("agentx/subagent", "session %p responded to ping\n", ss)); } }
void read_premib_configs (void) { DEBUGMSGTL(("read_config","reading premib configuration tokens\n")); if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS)) read_config_files(PREMIB_CONFIG); snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, NULL); }
int register_sysORTable_sess(oid *oidin, size_t oidlen, const char *descr, struct snmp_session *ss) { struct sysORTable **ptr=&table; struct register_sysOR_parameters reg_sysOR_parms; DEBUGMSGTL(("mibII/sysORTable", "sysORTable registering: ")); DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen)); DEBUGMSG(("mibII/sysORTable","\n")); while(*ptr != NULL) ptr = &((*ptr)->next); *ptr = (struct sysORTable *) malloc(sizeof(struct sysORTable)); if ( *ptr == NULL ) { return SYS_ORTABLE_REGISTRATION_FAILED; } (*ptr)->OR_descr = (char *) malloc(strlen(descr)+1); if ( (*ptr)->OR_descr == NULL ) { free( *ptr ); return SYS_ORTABLE_REGISTRATION_FAILED; } strcpy((*ptr)->OR_descr, descr); (*ptr)->OR_oidlen = oidlen; (*ptr)->OR_oid = (oid *) malloc(sizeof(oid)*oidlen); if ( (*ptr)->OR_oid == NULL ) { free( *ptr ); free( (*ptr)->OR_descr ); return SYS_ORTABLE_REGISTRATION_FAILED; } memcpy((*ptr)->OR_oid, oidin, sizeof(oid)*oidlen); gettimeofday(&((*ptr)->OR_uptime), NULL); (*ptr)->OR_sess = ss; (*ptr)->next = NULL; numEntries++; reg_sysOR_parms.name = oidin; reg_sysOR_parms.namelen = oidlen; reg_sysOR_parms.descr = descr; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REG_SYSOR, ®_sysOR_parms); return SYS_ORTABLE_REGISTERED_OK; }
int log_handler_callback(netsnmp_log_handler* logh, int pri, const char *str) { /* * XXX - perhaps replace 'snmp_call_callbacks' processing * with individual callback log_handlers ?? */ struct snmp_log_message slm; int dodebug = snmp_get_do_debugging(); slm.priority = pri; slm.msg = str; if (dodebug) /* turn off debugging inside the callbacks else will loop */ snmp_set_do_debugging(0); snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, &slm); if (dodebug) snmp_set_do_debugging(dodebug); return 1; }
void read_configs (void) { char *optional_config = ds_get_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG); char *type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE); DEBUGMSGTL(("read_config","reading normal configuration tokens\n")); if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS)) read_config_files(NORMAL_CONFIG); /* do this even when the normal above wasn't done */ if (optional_config && type) read_config_with_type(optional_config, type); snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, NULL); }
int unregister_sysORTable_sess(oid *oidin, size_t oidlen, struct snmp_session *ss) { struct sysORTable **ptr=&table, *prev=NULL; int found = SYS_ORTABLE_NO_SUCH_REGISTRATION; struct register_sysOR_parameters reg_sysOR_parms; DEBUGMSGTL(("mibII/sysORTable", "sysORTable unregistering: ")); DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen)); DEBUGMSG(("mibII/sysORTable","\n")); while(*ptr != NULL) { if ( snmp_oid_compare( oidin, oidlen, (*ptr)->OR_oid, (*ptr)->OR_oidlen) == 0 ) { if ( (*ptr)->OR_sess != ss ) continue; /* different session */ if ( prev == NULL ) table = (*ptr)->next; else prev->next = (*ptr)->next; free( (*ptr)->OR_descr ); free( (*ptr)->OR_oid ); free( (*ptr) ); numEntries--; found = SYS_ORTABLE_UNREGISTERED_OK; break; } prev = *ptr; ptr = &((*ptr)->next); } reg_sysOR_parms.name = oidin; reg_sysOR_parms.namelen = oidlen; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR, ®_sysOR_parms); return found; }
int add_trap_session(netsnmp_session * ss, int pdutype, int confirm, int version) { if (snmp_callback_available(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_NOTIFICATIONS) == SNMPERR_SUCCESS) { /* * something else wants to handle notification registrations */ struct agent_add_trap_args args; DEBUGMSGTL(("trap", "adding callback trap sink\n")); args.ss = ss; args.confirm = confirm; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_NOTIFICATIONS, (void *) &args); } else { /* * no other support exists, handle it ourselves. */ struct trap_sink *new_sink; DEBUGMSGTL(("trap", "adding internal trap sink\n")); new_sink = (struct trap_sink *) malloc(sizeof(*new_sink)); if (new_sink == NULL) return 0; new_sink->sesp = ss; new_sink->pdutype = pdutype; new_sink->version = version; new_sink->next = sinks; sinks = new_sink; } return 1; }
int writeSystem(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t name_len) { u_char *cp; char *buf = NULL, *oldbuf = NULL; int count, *setvar = NULL; switch ((char) name[7]) { case VERSION_DESCR: case VERSIONID: case UPTIME: snmp_log(LOG_ERR, "Attempt to write to R/O OID\n"); return SNMP_ERR_NOTWRITABLE; case SYSCONTACT: buf = sysContact; oldbuf = oldsysContact; setvar = &sysContactSet; break; case SYSTEMNAME: buf = sysName; oldbuf = oldsysName; setvar = &sysNameSet; break; case SYSLOCATION: buf = sysLocation; oldbuf = oldsysLocation; setvar = &sysLocationSet; break; case SYSSERVICES: case SYSORLASTCHANGE: snmp_log(LOG_ERR, "Attempt to write to R/O OID\n"); return SNMP_ERR_NOTWRITABLE; default: return SNMP_ERR_GENERR; /* ??? */ } switch (action) { case RESERVE1: /* Check values for acceptability */ if (var_val_type != ASN_OCTET_STR) { snmp_log(LOG_ERR, "not string\n"); return SNMP_ERR_WRONGTYPE; } if (var_val_len > sizeof(sysLocation) - 1) { snmp_log(LOG_ERR, "bad length\n"); return SNMP_ERR_WRONGLENGTH; } for (cp = var_val, count = 0; count < (int) var_val_len; count++, cp++) { if (!isprint(*cp)) { snmp_log(LOG_ERR, "not print %x\n", *cp); return SNMP_ERR_WRONGVALUE; } /* purpose : 0012435 author : Gavin.Lin date : 2010-08-04 */ /* description : Customer requirements */ else { if ((*cp == 0x22) || (*cp == 0x25) || (*cp == 0x27) || (*cp == 0x5C)) { return SNMP_ERR_WRONGVALUE; } } } if (setvar != NULL && *setvar < 0) { /* * The object is set in a read-only configuration file. */ return SNMP_ERR_NOTWRITABLE; } break; case RESERVE2: /* Allocate memory and similar resources */ /* * Using static strings, so nothing needs to be done */ break; case ACTION: /* Perform the SET action (if reversible) */ /* * Save the old value, in case of UNDO */ strcpy(oldbuf, buf); memcpy(buf, var_val, var_val_len); buf[var_val_len] = 0; break; case UNDO: /* Reverse the SET action and free resources */ strcpy(buf, oldbuf); oldbuf[0] = 0; break; case COMMIT: if (setvar != NULL) { *setvar = 1; } snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE)); (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, NULL); snmp_clean_persistent(netsnmp_ds_get_string (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE)); case FREE: /* Free any resources allocated */ /* * No resources have been allocated, but "empty" the 'oldbuf' */ oldbuf[0] = 0; break; } return SNMP_ERR_NOERROR; } /* end of writeSystem */
/*******************************************************************-o-****** */ int main(int argc, char **argv) { int rval = SNMPERR_SUCCESS; size_t oldKu_len = SNMP_MAXBUF_SMALL, newKu_len = SNMP_MAXBUF_SMALL, oldkul_len = SNMP_MAXBUF_SMALL, newkul_len = SNMP_MAXBUF_SMALL, keychange_len = SNMP_MAXBUF_SMALL; char *s = NULL; u_char oldKu[SNMP_MAXBUF_SMALL], newKu[SNMP_MAXBUF_SMALL], oldkul[SNMP_MAXBUF_SMALL], newkul[SNMP_MAXBUF_SMALL], keychange[SNMP_MAXBUF_SMALL]; int i; int arg = 1; local_progname = argv[0]; /* * Parse. */ for(; (arg < argc) && (argv[arg][0] == '-') ; arg++){ switch(argv[arg][1]){ case 'D': snmp_set_do_debugging(1); break; case 'E': engineid = (u_char *)argv[++arg]; break; case 'f': forcepassphrase = 1; break; case 'N': newpass = argv[++arg]; break; case 'O': oldpass = argv[++arg]; break; case 'P': promptindicator = 0; break; case 't': transform_type_input = argv[++arg]; break; case 'v': verbose = 1; break; case 'V': visible = 1; break; case 'h': rval = 0; default: usage_to_file(stdout); exit(rval); } } if ( !transform_type_input ) { fprintf(stderr, "The -t option is mandatory.\n"); usage_synopsis(stdout); exit(1000); } /* * Convert and error check transform_type. */ if ( !strcmp(transform_type_input, "md5") ) { transform_type = usmHMACMD5AuthProtocol; } else if ( !strcmp(transform_type_input, "sha1") ) { transform_type = usmHMACSHA1AuthProtocol; } else { fprintf(stderr, "Unrecognized hash transform: \"%s\".\n", transform_type_input); usage_synopsis(stderr); QUITFUN(rval = SNMPERR_GENERR, main_quit); } if (verbose) { fprintf(stderr, "Hash:\t\t%s\n", (transform_type == usmHMACMD5AuthProtocol) ? "usmHMACMD5AuthProtocol" : "usmHMACSHA1AuthProtocol" ); } /* * Build engineID. Accept hex engineID as the bits * "in-and-of-themselves", otherwise create an engineID with the * given string as text. * * If no engineID is given, lookup the first IP address for the * localhost and use that (see setup_engineID()). */ if ( engineid && (tolower(*(engineid+1)) == 'x') ) { engineid_len = hex_to_binary2( engineid+2, strlen((char *)engineid)-2, (char **) &engineid); DEBUGMSGTL(("encode_keychange","engineIDLen: %d\n", engineid_len)); } else { engineid_len = setup_engineID(&engineid, (char *)engineid); } #ifdef SNMP_TESTING_CODE if (verbose) { fprintf(stderr, "EngineID:\t%s\n", /* XXX = */ dump_snmpEngineID(engineid, &engineid_len)); } #endif /* * Get passphrases from user. */ rval = get_user_passphrases(); QUITFUN(rval, main_quit); if ( strlen(oldpass) < USM_LENGTH_P_MIN ) { fprintf(stderr, "Old passphrase must be greater than %d " "characters in length.\n", USM_LENGTH_P_MIN); QUITFUN(rval = SNMPERR_GENERR, main_quit); } else if ( strlen(newpass) < USM_LENGTH_P_MIN ) { fprintf(stderr, "New passphrase must be greater than %d " "characters in length.\n", USM_LENGTH_P_MIN); QUITFUN(rval = SNMPERR_GENERR, main_quit); } if (verbose) { fprintf(stderr, "Old passphrase:\t%s\nNew passphrase:\t%s\n", oldpass, newpass); } /* * Compute Ku and Kul's from old and new passphrases, then * compute the keychange string & print it out. */ rval = sc_init(); QUITFUN(rval, main_quit); rval = generate_Ku( transform_type, USM_LENGTH_OID_TRANSFORM, (u_char *)oldpass, strlen(oldpass), oldKu, &oldKu_len); QUITFUN(rval, main_quit); rval = generate_Ku( transform_type, USM_LENGTH_OID_TRANSFORM, (u_char *)newpass, strlen(newpass), newKu, &newKu_len); QUITFUN(rval, main_quit); DEBUGMSGTL(("encode_keychange", "EID (%d): ", engineid_len)); for(i=0; i < (int)engineid_len; i++) DEBUGMSGTL(("encode_keychange", "%02x",(int) (engineid[i]))); DEBUGMSGTL(("encode_keychange","\n")); DEBUGMSGTL(("encode_keychange", "old Ku (%d) (from %s): ", oldKu_len, oldpass)); for(i=0; i < (int)oldKu_len; i++) DEBUGMSGTL(("encode_keychange", "%02x",(int) (oldKu[i]))); DEBUGMSGTL(("encode_keychange","\n")); rval = generate_kul( transform_type, USM_LENGTH_OID_TRANSFORM, engineid, engineid_len, oldKu, oldKu_len, oldkul, &oldkul_len); QUITFUN(rval, main_quit); DEBUGMSGTL(("encode_keychange", "generating old Kul (%d) (from Ku): ", oldkul_len)); for(i=0; i < (int)oldkul_len; i++) DEBUGMSGTL(("encode_keychange", "%02x",(int) (oldkul[i]))); DEBUGMSGTL(("encode_keychange","\n")); rval = generate_kul( transform_type, USM_LENGTH_OID_TRANSFORM, engineid, engineid_len, newKu, newKu_len, newkul, &newkul_len); QUITFUN(rval, main_quit); DEBUGMSGTL(("encode_keychange", "generating new Kul (%d) (from Ku): ", oldkul_len)); for(i=0; i < (int)newkul_len; i++) DEBUGMSGTL(("encode_keychange", "%02x",newkul[i])); DEBUGMSGTL(("encode_keychange","\n")); rval = encode_keychange(transform_type, USM_LENGTH_OID_TRANSFORM, oldkul, oldkul_len, newkul, newkul_len, keychange, &keychange_len); QUITFUN(rval, main_quit); binary_to_hex(keychange, keychange_len, &s); printf("%s%s\n", (verbose) ? "KeyChange string:\t" : "", /* XXX stdout */ s); /* * Cleanup. */ main_quit: snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN, NULL); SNMP_ZERO(oldpass, strlen(oldpass)); SNMP_ZERO(newpass, strlen(newpass)); SNMP_ZERO(oldKu, oldKu_len); SNMP_ZERO(newKu, newKu_len); SNMP_ZERO(oldkul, oldkul_len); SNMP_ZERO(newkul, newkul_len); SNMP_ZERO(s, strlen(s)); return rval; } /* end main() */
void send_enterprise_trap_vars(int trap, int specific, oid * enterprise, int enterprise_length, netsnmp_variable_list * vars) { netsnmp_variable_list uptime_var, snmptrap_var, enterprise_var; netsnmp_variable_list *v2_vars, *last_var = NULL; netsnmp_pdu *template_pdu; u_long uptime; in_addr_t *pdu_in_addr_t; struct trap_sink *sink; #ifdef BRCM_SNMP_MIB_SUPPORT oid temp_oid[MAX_OID_LEN]; #endif /* * Initialise SNMPv2 required variables */ uptime = netsnmp_get_agent_uptime(); memset(&uptime_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&uptime_var, sysuptime_oid, OID_LENGTH(sysuptime_oid)); snmp_set_var_value(&uptime_var, (u_char *) & uptime, sizeof(uptime)); uptime_var.type = ASN_TIMETICKS; uptime_var.next_variable = &snmptrap_var; memset(&snmptrap_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&snmptrap_var, snmptrap_oid, OID_LENGTH(snmptrap_oid)); /* * value set later .... */ snmptrap_var.type = ASN_OBJECT_ID; if (vars) snmptrap_var.next_variable = vars; else snmptrap_var.next_variable = &enterprise_var; /* * find end of provided varbind list, * ready to append the enterprise info if necessary */ last_var = vars; while (last_var && last_var->next_variable) last_var = last_var->next_variable; memset(&enterprise_var, 0, sizeof(netsnmp_variable_list)); snmp_set_var_objid(&enterprise_var, snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid)); snmp_set_var_value(&enterprise_var, (u_char *) enterprise, enterprise_length * sizeof(oid)); enterprise_var.type = ASN_OBJECT_ID; enterprise_var.next_variable = NULL; v2_vars = &uptime_var; /* * Create a template PDU, ready for sending */ template_pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (template_pdu == NULL) { /* * Free memory if value stored dynamically */ snmp_set_var_value(&enterprise_var, NULL, 0); return; } template_pdu->trap_type = trap; template_pdu->specific_type = specific; if (snmp_clone_mem((void **) &template_pdu->enterprise, enterprise, enterprise_length * sizeof(oid))) { snmp_free_pdu(template_pdu); snmp_set_var_value(&enterprise_var, NULL, 0); return; } template_pdu->enterprise_length = enterprise_length; template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; pdu_in_addr_t = (in_addr_t *) template_pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); template_pdu->time = uptime; /* * Now use the parameters to determine * which v2 variables are needed, * and what values they should take. */ switch (trap) { case -1: /* * SNMPv2 only * Check to see whether the variables provided * are sufficient for SNMPv2 notifications */ if (vars && netsnmp_oid_equals(vars->name, vars->name_length, sysuptime_oid, OID_LENGTH(sysuptime_oid)) == 0) v2_vars = vars; else if (vars && netsnmp_oid_equals(vars->name, vars->name_length, snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0) uptime_var.next_variable = vars; else { /* * Hmmm... we don't seem to have a value - oops! */ snmptrap_var.next_variable = vars; } last_var = NULL; /* Don't need enterprise info */ convert_v2_to_v1(vars, template_pdu); break; /* * "Standard" SNMPv1 traps */ case SNMP_TRAP_COLDSTART: snmp_set_var_value(&snmptrap_var, (u_char *) cold_start_oid, sizeof(cold_start_oid)); break; case SNMP_TRAP_WARMSTART: snmp_set_var_value(&snmptrap_var, (u_char *) warm_start_oid, sizeof(warm_start_oid)); break; case SNMP_TRAP_LINKDOWN: snmp_set_var_value(&snmptrap_var, (u_char *) link_down_oid, sizeof(link_down_oid)); break; case SNMP_TRAP_LINKUP: snmp_set_var_value(&snmptrap_var, (u_char *) link_up_oid, sizeof(link_up_oid)); break; case SNMP_TRAP_AUTHFAIL: if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu(template_pdu); snmp_set_var_value(&enterprise_var, NULL, 0); return; } snmp_set_var_value(&snmptrap_var, (u_char *) auth_fail_oid, sizeof(auth_fail_oid)); break; case SNMP_TRAP_EGPNEIGHBORLOSS: snmp_set_var_value(&snmptrap_var, (u_char *) egp_xxx_oid, sizeof(egp_xxx_oid)); break; #ifdef BRCM_SNMP_MIB_SUPPORT case SNMP_TRAP_ENTERPRISESPECIFIC: memcpy(temp_oid, (char *) enterprise, (enterprise_length) * sizeof(oid)); temp_oid[enterprise_length] = 0; temp_oid[enterprise_length + 1] = specific; snmp_set_var_value(&snmptrap_var, (u_char *) temp_oid, (enterprise_length + 2) * sizeof(oid)); snmptrap_var.next_variable = vars; last_var = NULL; /* Don't need version info */ break; #endif /* BRCM_SNMP_MIB_SUPPORT */ } /* * Now loop through the list of trap sinks, * sending an appropriately formatted PDU to each */ for (sink = sinks; sink; sink = sink->next) { if (sink->version == SNMP_VERSION_1 && trap == -1) continue; /* Skip v1 sinks for v2 only traps */ template_pdu->command = sink->pdutype; if (sink->version != SNMP_VERSION_1) { template_pdu->variables = v2_vars; if (last_var) last_var->next_variable = &enterprise_var; } else template_pdu->variables = vars; send_trap_to_sess(sink->sesp, template_pdu); if (sink->version != SNMP_VERSION_1 && last_var) last_var->next_variable = NULL; } /* * send stuff to registered callbacks */ /* * v2 traps/informs */ template_pdu->variables = v2_vars; if (last_var) last_var->next_variable = &enterprise_var; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP2, template_pdu); if (last_var) last_var->next_variable = NULL; /* * v1 traps */ template_pdu->command = SNMP_MSG_TRAP; template_pdu->variables = vars; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP1, template_pdu); /* * Free memory if values stored dynamically */ snmp_set_var_value(&enterprise_var, NULL, 0); snmp_set_var_value(&snmptrap_var, NULL, 0); /* * Ensure we don't free anything we shouldn't */ if (last_var) last_var->next_variable = NULL; template_pdu->variables = NULL; snmp_free_pdu(template_pdu); }
int write_snmp(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t name_len) { long intval = 0; switch (action) { case RESERVE1: /* Check values for acceptability */ if (var_val_type != ASN_INTEGER) { DEBUGMSGTL(("mibII/snmp_mib", "%x not integer type", var_val_type)); return SNMP_ERR_WRONGTYPE; } intval = *((long *) var_val); if (intval != 1 && intval != 2) { DEBUGMSGTL(("mibII/snmp_mib", "not valid %x\n", intval)); return SNMP_ERR_WRONGVALUE; } if (snmp_enableauthentrapsset < 0) { /* * The object is set in a read-only configuration file. */ return SNMP_ERR_NOTWRITABLE; } break; case RESERVE2: /* Allocate memory and similar resources */ /* * Using static variables, so nothing needs to be done */ break; case ACTION: /* Perform the SET action (if reversible) */ /* * Save the old value, in case of UNDO */ intval = *((long *) var_val); old_snmp_enableauthentraps = snmp_enableauthentraps; snmp_enableauthentraps = intval; break; case UNDO: /* Reverse the SET action and free resources */ snmp_enableauthentraps = old_snmp_enableauthentraps; break; case COMMIT: snmp_enableauthentrapsset = 1; snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE)); (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, NULL); snmp_clean_persistent(netsnmp_ds_get_string (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE)); break; case FREE: /* Free any resources allocated */ break; } return SNMP_ERR_NOERROR; }
/* * Open a session to the master agent. */ int subagent_open_master_session(void) { netsnmp_session sess; DEBUGMSGTL(("agentx/subagent", "opening session...\n")); if (main_session) { snmp_log(LOG_WARNING, "AgentX session to master agent attempted to be re-opened."); return -1; } snmp_sess_init(&sess); sess.version = AGENTX_VERSION_1; sess.retries = SNMP_DEFAULT_RETRIES; sess.timeout = SNMP_DEFAULT_TIMEOUT; sess.flags |= SNMP_FLAGS_STREAM_SOCKET; if (netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)) { sess.peername = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET); } else { sess.peername = strdup(AGENTX_SOCKET); } sess.local_port = 0; /* client */ sess.remote_port = AGENTX_PORT; /* default port */ sess.callback = handle_agentx_packet; sess.authenticator = NULL; main_session = snmp_open_ex(&sess, NULL, agentx_parse, NULL, NULL, agentx_realloc_build, agentx_check_packet); if (main_session == NULL) { /* * Diagnose snmp_open errors with the input * netsnmp_session pointer. */ if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) { if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { netsnmp_sess_log_error(LOG_WARNING, "Error: Failed to connect to the agentx master agent", &sess); } else { snmp_sess_perror ("Error: Failed to connect to the agentx master agent", &sess); } } return -1; } if (agentx_open_session(main_session) < 0) { snmp_close(main_session); main_session = NULL; return -1; } if (add_trap_session(main_session, AGENTX_MSG_NOTIFY, 1, AGENTX_VERSION_1)) { DEBUGMSGTL(("agentx/subagent", " trap session registered OK\n")); } else { DEBUGMSGTL(("agentx/subagent", "trap session registration failed\n")); snmp_close(main_session); main_session = NULL; return -1; } agentx_register_callbacks(main_session); snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_START, (void *) main_session); DEBUGMSGTL(("agentx/subagent", "opening session... DONE (%p)\n", main_session)); return 0; }
int unregister_mib_range( oid *name, size_t len, int priority, int range_subid, oid range_ubound) { struct subtree *list, *myptr; struct subtree *prev, *child; /* loop through children */ struct register_parameters reg_parms; list = find_subtree( name, len, subtrees ); if ( list == NULL ) return MIB_NO_SUCH_REGISTRATION; for ( child=list, prev=NULL; child != NULL; prev=child, child=child->children ) { if (( snmp_oid_compare( child->name, child->namelen, name, len) == 0 ) && ( child->priority == priority )) break; /* found it */ } if ( child == NULL ) return MIB_NO_SUCH_REGISTRATION; unload_subtree( child, prev ); myptr = child; /* remember this for later */ /* * Now handle any occurances in the following subtrees, * as a result of splitting this range. Due to the * nature of the way such splits work, the first * subtree 'slice' that doesn't refer to the given * name marks the end of the original region. * * This should also serve to register ranges. */ for ( list = myptr->next ; list != NULL ; list=list->next ) { for ( child=list, prev=NULL; child != NULL; prev=child, child=child->children ) { if (( snmp_oid_compare( child->name, child->namelen, name, len) == 0 ) && ( child->priority == priority )) { unload_subtree( child, prev ); free_subtree( child ); break; } } if ( child == NULL ) /* Didn't find the given name */ break; } free_subtree( myptr ); reg_parms.name = name; reg_parms.namelen = len; reg_parms.priority = priority; reg_parms.range_subid = range_subid; reg_parms.range_ubound = range_ubound; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREGISTER_OID, ®_parms); return MIB_UNREGISTERED_OK; }
int register_mib_range(const char *moduleName, struct variable *var, size_t varsize, size_t numvars, oid *mibloc, size_t mibloclen, int priority, int range_subid, oid range_ubound, struct snmp_session *ss) { struct subtree *subtree, *sub2; int res, i; struct register_parameters reg_parms; subtree = (struct subtree *) malloc(sizeof(struct subtree)); if ( subtree == NULL ) return MIB_REGISTRATION_FAILED; memset(subtree, 0, sizeof(struct subtree)); DEBUGMSGTL(("register_mib", "registering \"%s\" at ", moduleName)); DEBUGMSGOID(("register_mib", mibloc, mibloclen)); DEBUGMSG(("register_mib","\n")); /* * Create the new subtree node being registered */ memcpy(subtree->name, mibloc, mibloclen*sizeof(oid)); subtree->namelen = (u_char) mibloclen; memcpy(subtree->start, mibloc, mibloclen*sizeof(oid)); subtree->start_len = (u_char) mibloclen; memcpy(subtree->end, mibloc, mibloclen*sizeof(oid)); subtree->end[ mibloclen-1 ]++; /* XXX - or use 'variables' info ? */ subtree->end_len = (u_char) mibloclen; memcpy(subtree->label, moduleName, strlen(moduleName)+1); if ( var ) { subtree->variables = (struct variable *) malloc(varsize*numvars); memcpy(subtree->variables, var, numvars*varsize); subtree->variables_len = numvars; subtree->variables_width = varsize; } subtree->priority = priority; subtree->session = ss; res = load_subtree(subtree); /* * If registering a range, * use the first subtree as a template * for the rest of the range */ if (( res == MIB_REGISTERED_OK ) && ( range_subid != 0 )) { for ( i = mibloc[range_subid-1] +1 ; i < (int)range_ubound ; i++ ) { sub2 = (struct subtree *) malloc(sizeof(struct subtree)); if ( sub2 == NULL ) { unregister_mib_range( mibloc, mibloclen, priority, range_subid, range_ubound); return MIB_REGISTRATION_FAILED; } memcpy( sub2, subtree, sizeof(struct subtree)); sub2->start[range_subid-1] = i; sub2->end[ range_subid-1] = i; /* XXX - ???? */ res = load_subtree(sub2); if ( res != MIB_REGISTERED_OK ) { unregister_mib_range( mibloc, mibloclen, priority, range_subid, range_ubound); return MIB_REGISTRATION_FAILED; } } } reg_parms.name = mibloc; reg_parms.namelen = mibloclen; reg_parms.priority = priority; reg_parms.range_subid = range_subid; reg_parms.range_ubound = range_ubound; snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_OID, ®_parms); return res; }
/** * This function allows you to make a distinction between generic * traps from different classes of equipment. For example, you may want * to handle a SNMP_TRAP_LINKDOWN trap for a particular device in a * different manner to a generic system SNMP_TRAP_LINKDOWN trap. * * * @param trap is the generic trap type. The trap types are: * - SNMP_TRAP_COLDSTART: * cold start * - SNMP_TRAP_WARMSTART: * warm start * - SNMP_TRAP_LINKDOWN: * link down * - SNMP_TRAP_LINKUP: * link up * - SNMP_TRAP_AUTHFAIL: * authentication failure * - SNMP_TRAP_EGPNEIGHBORLOSS: * egp neighbor loss * - SNMP_TRAP_ENTERPRISESPECIFIC: * enterprise specific * * @param specific is the specific trap value. * * @param enterprise is an enterprise oid in which you want to send specifc * traps from. * * @param enterprise_length is the length of the enterprise oid, use macro, * OID_LENGTH, to compute length. * * @param vars is used to supply list of variable bindings to form an SNMPv2 * trap. * * @param context currently unused * * @param flags currently unused * * @return void * * @see send_easy_trap * @see send_v2trap */ int netsnmp_send_traps(int trap, int specific, oid * enterprise, int enterprise_length, netsnmp_variable_list * vars, char * context, int flags) { netsnmp_pdu *template_v1pdu; netsnmp_pdu *template_v2pdu; netsnmp_variable_list *vblist = NULL; netsnmp_variable_list *trap_vb; netsnmp_variable_list *var; in_addr_t *pdu_in_addr_t; u_long uptime; struct trap_sink *sink; DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific)); DEBUGMSGOID(("trap", enterprise, enterprise_length)); DEBUGMSG(( "trap", "\n")); if (vars) { vblist = snmp_clone_varbind( vars ); if (!vblist) { snmp_log(LOG_WARNING, "send_trap: failed to clone varbind list\n"); return -1; } } if ( trap == -1 ) { /* * Construct the SNMPv2-style notification PDU */ if (!vblist) { snmp_log(LOG_WARNING, "send_trap: called with NULL v2 information\n"); return -1; } template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2); if (!template_v2pdu) { snmp_log(LOG_WARNING, "send_trap: failed to construct v2 template PDU\n"); snmp_free_varbind(vblist); return -1; } /* * Check the varbind list we've been given. * If it starts with a 'sysUptime.0' varbind, then use that. * Otherwise, prepend a suitable 'sysUptime.0' varbind. */ if (!snmp_oid_compare( vblist->name, vblist->name_length, sysuptime_oid, sysuptime_oid_len )) { template_v2pdu->variables = vblist; trap_vb = vblist->next_variable; } else { uptime = netsnmp_get_agent_uptime(); var = NULL; snmp_varlist_add_variable( &var, sysuptime_oid, sysuptime_oid_len, ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime)); if (!var) { snmp_log(LOG_WARNING, "send_trap: failed to insert sysUptime varbind\n"); snmp_free_pdu(template_v2pdu); snmp_free_varbind(vblist); return -1; } template_v2pdu->variables = var; var->next_variable = vblist; trap_vb = vblist; } /* * 'trap_vb' should point to the snmpTrapOID.0 varbind, * identifying the requested trap. If not then bomb out. * If it's a 'standard' trap, then we need to append an * snmpEnterprise varbind (if there isn't already one). */ if (!trap_vb || snmp_oid_compare(trap_vb->name, trap_vb->name_length, snmptrap_oid, snmptrap_oid_len)) { snmp_log(LOG_WARNING, "send_trap: no v2 trapOID varbind provided\n"); snmp_free_pdu(template_v2pdu); return -1; } if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix), trap_prefix, OID_LENGTH(trap_prefix))) { var = find_varbind_in_list( template_v2pdu->variables, snmptrapenterprise_oid, snmptrapenterprise_oid_len); if (!var && !snmp_varlist_add_variable( &(template_v2pdu->variables), snmptrapenterprise_oid, snmptrapenterprise_oid_len, ASN_OBJECT_ID, (char*)enterprise, enterprise_length*sizeof(oid))) { snmp_log(LOG_WARNING, "send_trap: failed to add snmpEnterprise to v2 trap\n"); snmp_free_pdu(template_v2pdu); return -1; } } /* * If everything's OK, convert the v2 template into an SNMPv1 trap PDU. */ template_v1pdu = convert_v2pdu_to_v1( template_v2pdu ); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to convert v2->v1 template PDU\n"); } } else { /* * Construct the SNMPv1 trap PDU.... */ template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP); if (!template_v1pdu) { snmp_log(LOG_WARNING, "send_trap: failed to construct v1 template PDU\n"); snmp_free_varbind(vblist); return -1; } template_v1pdu->trap_type = trap; template_v1pdu->specific_type = specific; template_v1pdu->time = netsnmp_get_agent_uptime(); if (snmp_clone_mem((void **) &template_v1pdu->enterprise, enterprise, enterprise_length * sizeof(oid))) { snmp_log(LOG_WARNING, "send_trap: failed to set v1 enterprise OID\n"); snmp_free_varbind(vblist); snmp_free_pdu(template_v1pdu); return -1; } template_v1pdu->enterprise_length = enterprise_length; template_v1pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY; template_v1pdu->variables = vblist; /* * ... and convert it into an SNMPv2-style notification PDU. */ template_v2pdu = convert_v1pdu_to_v2( template_v1pdu ); if (!template_v2pdu) { snmp_log(LOG_WARNING, "send_trap: failed to convert v1->v2 template PDU\n"); } } /* * Check whether we're ignoring authFail traps */ if (template_v1pdu) { if (template_v1pdu->trap_type == SNMP_TRAP_AUTHFAIL && snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) { snmp_free_pdu(template_v1pdu); snmp_free_pdu(template_v2pdu); return 0; } /* * Ensure that the v1 trap PDU includes the local IP address */ pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr; *pdu_in_addr_t = get_myaddr(); } /* * Now loop through the list of trap sinks * and call the trap callback routines, * providing an appropriately formatted PDU in each case */ for (sink = sinks; sink; sink = sink->next) { #ifndef NETSNMP_DISABLE_SNMPV1 if (sink->version == SNMP_VERSION_1) { if (template_v1pdu) { send_trap_to_sess(sink->sesp, template_v1pdu); } } else { #endif if (template_v2pdu) { template_v2pdu->command = sink->pdutype; send_trap_to_sess(sink->sesp, template_v2pdu); } #ifndef NETSNMP_DISABLE_SNMPV1 } #endif } if (template_v1pdu) snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP1, template_v1pdu); if (template_v2pdu) snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_SEND_TRAP2, template_v2pdu); snmp_free_pdu(template_v1pdu); snmp_free_pdu(template_v2pdu); return 0; }
/** registers a row within a mib table */ int netsnmp_register_mib_table_row(const char *moduleName, struct variable *var, size_t varsize, size_t numvars, oid * mibloc, size_t mibloclen, int priority, int var_subid, netsnmp_session * ss, const char *context, int timeout, int flags) { unsigned int i = 0, rc = 0; oid ubound = 0; for (i = 0; i < numvars; i++) { struct variable *vr = (struct variable *) ((char *) var + (i * varsize)); netsnmp_handler_registration *r; if ( var_subid > (int)mibloclen ) { break; /* doesn't make sense */ } r = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration); if (r == NULL) { /* * Unregister whatever we have registered so far, and * return an error. */ rc = MIB_REGISTRATION_FAILED; break; } memset(r, 0, sizeof(netsnmp_handler_registration)); r->handler = get_old_api_handler(); r->handlerName = strdup(moduleName); if (r->handlerName == NULL) { netsnmp_handler_registration_free(r); break; } r->rootoid_len = mibloclen; r->rootoid = (oid *) malloc(r->rootoid_len * sizeof(oid)); if (r->rootoid == NULL) { netsnmp_handler_registration_free(r); rc = MIB_REGISTRATION_FAILED; break; } memcpy(r->rootoid, mibloc, mibloclen * sizeof(oid)); memcpy((u_char *) (r->rootoid + (var_subid - vr->namelen)), vr->name, vr->namelen * sizeof(oid)); DEBUGMSGTL(("netsnmp_register_mib_table_row", "rootoid ")); DEBUGMSGOID(("netsnmp_register_mib_table_row", r->rootoid, r->rootoid_len)); DEBUGMSG(("netsnmp_register_mib_table_row", "(%d)\n", (var_subid - vr->namelen))); r->handler->myvoid = netsnmp_duplicate_variable(vr); r->handler->data_clone = (void *(*)(void *))netsnmp_duplicate_variable; r->handler->data_free = free; if (r->handler->myvoid == NULL) { netsnmp_handler_registration_free(r); rc = MIB_REGISTRATION_FAILED; break; } r->contextName = (context) ? strdup(context) : NULL; if (context != NULL && r->contextName == NULL) { netsnmp_handler_registration_free(r); rc = MIB_REGISTRATION_FAILED; break; } r->priority = priority; r->range_subid = 0; /* var_subid; */ r->range_ubound = 0; /* range_ubound; */ r->timeout = timeout; r->modes = HANDLER_CAN_RWRITE; /* * Register this column and row */ if ((rc = netsnmp_register_handler_nocallback(r)) != MIB_REGISTERED_OK) { DEBUGMSGTL(("netsnmp_register_mib_table_row", "register failed %d\n", rc)); netsnmp_handler_registration_free(r); break; } if (vr->namelen > 0) { if (vr->name[vr->namelen - 1] > ubound) { ubound = vr->name[vr->namelen - 1]; } } } if (rc == MIB_REGISTERED_OK) { struct register_parameters reg_parms; reg_parms.name = mibloc; reg_parms.namelen = mibloclen; reg_parms.priority = priority; reg_parms.flags = (u_char) flags; reg_parms.range_subid = var_subid; reg_parms.range_ubound = ubound; reg_parms.timeout = timeout; reg_parms.contextName = context; rc = snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_OID, ®_parms); } return rc; }
int handle_agentx_packet(int operation, netsnmp_session * session, int reqid, netsnmp_pdu *pdu, void *magic) { struct agent_netsnmp_set_info *asi = NULL; snmp_callback mycallback; netsnmp_pdu *internal_pdu = NULL; void *retmagic = NULL; ns_subagent_magic *smagic = NULL; if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) { struct synch_state *state = (struct synch_state *) magic; int period = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL); DEBUGMSGTL(("agentx/subagent", "transport disconnect indication\n")); /* * deal with existing session. This happend if agentx sends * a message to the master, but the master goes away before * a response is sent. agentx will spin in snmp_synch_response_cb, * waiting for a response. At the very least, the waiting * flag must be set to break that loop. The rest is copied * from disconnect handling in snmp_sync_input. */ if(state) { state->waiting = 0; state->pdu = NULL; state->status = STAT_ERROR; session->s_snmp_errno = SNMPERR_ABORT; SET_SNMP_ERROR(SNMPERR_ABORT); } /* * Deregister the ping alarm, if any, and invalidate all other * references to this session. */ if (session->securityModel != SNMP_DEFAULT_SECMODEL) { snmp_alarm_unregister(session->securityModel); } snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_STOP, (void *) session); agentx_unregister_callbacks(session); remove_trap_session(session); register_mib_detach(); main_session = NULL; if (period != 0) { /* * Pings are enabled, so periodically attempt to re-establish contact * with the master agent. Don't worry about the handle, * agentx_reopen_session unregisters itself if it succeeds in talking * to the master agent. */ snmp_alarm_register(period, SA_REPEAT, agentx_reopen_session, NULL); } return 0; } else if (operation != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { DEBUGMSGTL(("agentx/subagent", "unexpected callback op %d\n", operation)); return 1; } /* * ok, we have a pdu from the net. Modify as needed */ DEBUGMSGTL(("agentx/subagent", "handling agentx request (req=0x%x,trans=" "0x%x,sess=0x%x)\n", pdu->reqid,pdu->transid, pdu->sessid)); pdu->version = AGENTX_VERSION_1; pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW; if (pdu->command == AGENTX_MSG_GET || pdu->command == AGENTX_MSG_GETNEXT || pdu->command == AGENTX_MSG_GETBULK) { smagic = (ns_subagent_magic *) calloc(1, sizeof(ns_subagent_magic)); if (smagic == NULL) { DEBUGMSGTL(("agentx/subagent", "couldn't malloc() smagic\n")); return 1; } smagic->original_command = pdu->command; smagic->session = session; smagic->ovars = NULL; retmagic = (void *) smagic; } switch (pdu->command) { case AGENTX_MSG_GET: DEBUGMSGTL(("agentx/subagent", " -> get\n")); pdu->command = SNMP_MSG_GET; mycallback = handle_subagent_response; break; case AGENTX_MSG_GETNEXT: DEBUGMSGTL(("agentx/subagent", " -> getnext\n")); pdu->command = SNMP_MSG_GETNEXT; /* * We have to save a copy of the original variable list here because * if the master agent has requested scoping for some of the varbinds * that information is stored there. */ smagic->ovars = snmp_clone_varbind(pdu->variables); DEBUGMSGTL(("agentx/subagent", "saved variables\n")); mycallback = handle_subagent_response; break; case AGENTX_MSG_GETBULK: /* * WWWXXX */ DEBUGMSGTL(("agentx/subagent", " -> getbulk\n")); pdu->command = SNMP_MSG_GETBULK; /* * We have to save a copy of the original variable list here because * if the master agent has requested scoping for some of the varbinds * that information is stored there. */ smagic->ovars = snmp_clone_varbind(pdu->variables); DEBUGMSGTL(("agentx/subagent", "saved variables at %p\n", smagic->ovars)); mycallback = handle_subagent_response; break; case AGENTX_MSG_RESPONSE: SNMP_FREE(smagic); DEBUGMSGTL(("agentx/subagent", " -> response\n")); return 1; case AGENTX_MSG_TESTSET: /* * XXXWWW we have to map this twice to both RESERVE1 and RESERVE2 */ DEBUGMSGTL(("agentx/subagent", " -> testset\n")); asi = save_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "save_set_vars() failed\n"); return 1; } asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE1; mycallback = handle_subagent_set_response; retmagic = asi; break; case AGENTX_MSG_COMMITSET: DEBUGMSGTL(("agentx/subagent", " -> commitset\n")); asi = restore_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "restore_set_vars() failed\n"); return 1; } if (asi->mode != SNMP_MSG_INTERNAL_SET_RESERVE2) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "dropping bad AgentX request (wrong mode %d)\n", asi->mode); return 1; } asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_ACTION; mycallback = handle_subagent_set_response; retmagic = asi; break; case AGENTX_MSG_CLEANUPSET: DEBUGMSGTL(("agentx/subagent", " -> cleanupset\n")); asi = restore_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "restore_set_vars() failed\n"); return 1; } if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1 || asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE2) { asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_FREE; } else if (asi->mode == SNMP_MSG_INTERNAL_SET_ACTION) { asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_COMMIT; } else { snmp_log(LOG_WARNING, "dropping bad AgentX request (wrong mode %d)\n", asi->mode); SNMP_FREE(retmagic); return 1; } mycallback = handle_subagent_set_response; retmagic = asi; break; case AGENTX_MSG_UNDOSET: DEBUGMSGTL(("agentx/subagent", " -> undoset\n")); asi = restore_set_vars(session, pdu); if (asi == NULL) { SNMP_FREE(smagic); snmp_log(LOG_WARNING, "restore_set_vars() failed\n"); return 1; } asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_UNDO; mycallback = handle_subagent_set_response; retmagic = asi; break; default: SNMP_FREE(smagic); DEBUGMSGTL(("agentx/subagent", " -> unknown command %d (%02x)\n", pdu->command, pdu->command)); return 0; } /* * submit the pdu to the internal handler */ /* * We have to clone the PDU here, because when we return from this * callback, sess_process_packet will free(pdu), but this call also * free()s its argument PDU. */ internal_pdu = snmp_clone_pdu(pdu); internal_pdu->contextName = internal_pdu->community; internal_pdu->contextNameLen = internal_pdu->community_len; internal_pdu->community = NULL; internal_pdu->community_len = 0; snmp_async_send(agentx_callback_sess, internal_pdu, mycallback, retmagic); return 1; }
/* * Open a session to the master agent. */ int subagent_open_master_session(void) { netsnmp_transport *t; netsnmp_session sess; DEBUGMSGTL(("agentx/subagent", "opening session...\n")); if (main_session) { snmp_log(LOG_WARNING, "AgentX session to master agent attempted to be re-opened."); return -1; } snmp_sess_init(&sess); sess.version = AGENTX_VERSION_1; sess.retries = SNMP_DEFAULT_RETRIES; sess.timeout = SNMP_DEFAULT_TIMEOUT; sess.flags |= SNMP_FLAGS_STREAM_SOCKET; sess.callback = handle_agentx_packet; sess.authenticator = NULL; t = netsnmp_transport_open_client( "agentx", netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)); if (t == NULL) { /* * Diagnose snmp_open errors with the input * netsnmp_session pointer. */ if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) { char buf[1024]; const char *socket = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET); snprintf(buf, sizeof(buf), "Warning: " "Failed to connect to the agentx master agent (%s)", socket ? socket : "[NIL]"); if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { netsnmp_sess_log_error(LOG_WARNING, buf, &sess); } else { snmp_sess_perror(buf, &sess); } } return -1; } main_session = snmp_add_full(&sess, t, NULL, agentx_parse, NULL, NULL, agentx_realloc_build, agentx_check_packet, NULL); if (main_session == NULL) { if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) { char buf[1024]; snprintf(buf, sizeof(buf), "Error: " "Failed to create the agentx master agent session (%s)", netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)); snmp_sess_perror(buf, &sess); } netsnmp_transport_free(t); return -1; } /* * I don't know why 1 is success instead of the usual 0 = noerr, * but that's what the function returns. */ if (1 != agentx_open_session(main_session)) { snmp_close(main_session); main_session = NULL; return -1; } if (add_trap_session(main_session, AGENTX_MSG_NOTIFY, 1, AGENTX_VERSION_1)) { DEBUGMSGTL(("agentx/subagent", " trap session registered OK\n")); } else { DEBUGMSGTL(("agentx/subagent", "trap session registration failed\n")); snmp_close(main_session); main_session = NULL; return -1; } agentx_register_callbacks(main_session); snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_START, (void *) main_session); snmp_log(LOG_INFO, "NET-SNMP version %s AgentX subagent connected\n", netsnmp_get_version()); DEBUGMSGTL(("agentx/subagent", "opening session... DONE (%p)\n", main_session)); return 0; }