void add_responses(struct variable_list *vars, struct oid_value ***next_ov, oid *name, size_t *name_length) { int found = 0; for (struct variable_list *var = vars; var; var = var->next_variable) { if (var->name_length < PRINTER_OID_LEN || 0 != netsnmp_oid_equals(PRINTER_OID, PRINTER_OID_LEN, var->name, PRINTER_OID_LEN)) { // This OID does not have the printer OID prefix, so we're done. *name_length = 0; return; } oid *objid = malloc(var->name_length * sizeof(oid)); memmove(objid, var->name, var->name_length * sizeof(oid)); size_t value_length = 1, out_length = 0;; char *value = malloc(value_length); sprint_realloc_value((unsigned char **)&value, &value_length, &out_length, 1, var->name, var->name_length, var); **next_ov = calloc(1, sizeof(struct oid_value)); (**next_ov)->name = objid; (**next_ov)->name_length = var->name_length; (**next_ov)->value = value; *next_ov = &(**next_ov)->next; *name_length = var->name_length; memmove(name, var->name, *name_length * sizeof(oid)); } return; }
void convert_v2_to_v1(netsnmp_variable_list * vars, netsnmp_pdu *template_pdu) { netsnmp_variable_list *v, *trap_v = NULL, *ent_v = NULL; oid trap_prefix[] = { SNMPV2_TRAPS_PREFIX }; int len; for (v = vars; v; v = v->next_variable) { if (netsnmp_oid_equals(v->name, v->name_length, snmptrap_oid, OID_LENGTH(snmptrap_oid)) == 0) trap_v = v; if (netsnmp_oid_equals(v->name, v->name_length, snmptrapenterprise_oid, OID_LENGTH(snmptrapenterprise_oid)) == 0) ent_v = v; } if (!trap_v) return; /* Can't find v2 snmpTrapOID varbind */ /* * Is this a 'standard' trap? * Or at least, does it have the correct prefix? */ if (netsnmp_oid_equals(trap_v->val.objid, OID_LENGTH(trap_prefix), trap_prefix, OID_LENGTH(trap_prefix)) == 0) { template_pdu->trap_type = trap_v->val.objid[OID_LENGTH(trap_prefix)] - 1; template_pdu->specific_type = 0; } else { len = trap_v->val_len / sizeof(oid); template_pdu->trap_type = 6; /* enterprise specific */ template_pdu->specific_type = trap_v->val.objid[len - 1]; } /* * TODO: * Extract the appropriate enterprise value from 'ent_v' * Remove uptime/trapOID varbinds from 'vars' list */ }
void * header_complex_get_from_oid(struct header_complex_index *datalist, oid * searchfor, size_t searchfor_len) { struct header_complex_index *nptr; for (nptr = datalist; nptr != NULL; nptr = nptr->next) { if (netsnmp_oid_equals(searchfor, searchfor_len, nptr->name, nptr->namelen) == 0) return nptr->data; } return NULL; }
int my_test_handler(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { oid myoid1[] = { 1, 2, 3, 4, 5, 6 }; static u_long accesses = 0; DEBUGMSGTL(("testhandler", "Got request:\n")); /* * loop through requests */ while (requests) { netsnmp_variable_list *var = requests->requestvb; DEBUGMSGTL(("testhandler", " oid:")); DEBUGMSGOID(("testhandler", var->name, var->name_length)); DEBUGMSG(("testhandler", "\n")); switch (reqinfo->mode) { case MODE_GET: if (netsnmp_oid_equals(var->name, var->name_length, myoid1, 6) == 0) { snmp_set_var_typed_value(var, ASN_INTEGER, (u_char *) & accesses, sizeof(accesses)); return SNMP_ERR_NOERROR; } break; case MODE_GETNEXT: if (snmp_oid_compare(var->name, var->name_length, myoid1, 6) < 0) { snmp_set_var_objid(var, myoid1, 6); snmp_set_var_typed_value(var, ASN_INTEGER, (u_char *) & accesses, sizeof(accesses)); return SNMP_ERR_NOERROR; } break; default: netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); break; } requests = requests->next; } return SNMP_ERR_NOERROR; }
/** find existing cache */ netsnmp_cache * netsnmp_cache_find_by_oid(const oid * rootoid, int rootoid_len) { netsnmp_cache *cache; for (cache = cache_head; cache; cache = cache->next) { if (0 == netsnmp_oid_equals(cache->rootoid, cache->rootoid_len, rootoid, rootoid_len)) return cache; } return NULL; }
int netsnmp_tdomain_support(const oid * in_oid, size_t in_len, const oid ** out_oid, size_t * out_len) { netsnmp_tdomain *d = NULL; for (d = domain_list; d != NULL; d = d->next) { if (netsnmp_oid_equals(in_oid, in_len, d->name, d->name_length) == 0) { if (out_oid != NULL && out_len != NULL) { *out_oid = d->name; *out_len = d->name_length; } return 1; } } return 0; }
unsigned long count_indexes(oid * name, size_t namelen, int include_unallocated) { struct snmp_index *i = NULL, *j = NULL; unsigned long n = 0; for (i = snmp_index_head; i != NULL; i = i->next_oid) { if (netsnmp_oid_equals(name, namelen, i->varbind->name, i->varbind->name_length) == 0) { for (j = i; j != NULL; j = j->next_idx) { if (j->allocated || include_unallocated) { n++; } } } } return n; }
int netsnmp_tdomain_unregister(netsnmp_tdomain *n) { netsnmp_tdomain **prevNext = &domain_list, *d; if (n != NULL) { for (d = domain_list; d != NULL; d = d->next) { if (netsnmp_oid_equals(n->name, n->name_length, d->name, d->name_length) == 0) { *prevNext = n->next; SNMP_FREE(n->prefix); return 1; } prevNext = &(d->next); } return 0; } else { return 0; } }
int netsnmp_tdomain_register(netsnmp_tdomain *n) { netsnmp_tdomain **prevNext = &domain_list, *d; if (n != NULL) { for (d = domain_list; d != NULL; d = d->next) { if (netsnmp_oid_equals(n->name, n->name_length, d->name, d->name_length) == 0) { /* * Already registered. */ return 0; } prevNext = &(d->next); } n->next = NULL; *prevNext = n; return 1; } else { return 0; } }
static int noit_snmp_oid_to_checkid(oid *o, int l, uuid_t checkid, char *out) { int i; char _uuid_str[UUID_STR_LEN+1], *cp, *uuid_str; uuid_str = out ? out : _uuid_str; if(l != reconnoiter_check_oid_len) { noitL(nlerr, "unsupported (length) trap recieved\n"); return -1; } if(netsnmp_oid_equals(o, reconnoiter_check_prefix_oid_len, reconnoiter_check_prefix_oid, reconnoiter_check_prefix_oid_len) != 0) { noitL(nlerr, "unsupported (wrong namespace) trap recieved\n"); return -1; } /* encode this as a uuid */ cp = uuid_str; for(i=0; i < reconnoiter_check_oid_len - reconnoiter_check_prefix_oid_len; i++) { oid v = o[i + reconnoiter_check_prefix_oid_len]; if(v > 0xffff) { noitL(nlerr, "trap target oid [%ld] out of range\n", (long int)v); return -1; } snprintf(cp, 5, "%04x", (unsigned short)(v & 0xffff)); cp += 4; /* hyphens after index 1,2,3,4 */ if(i > 0 && i < 5) *cp++ = '-'; } if(uuid_parse(uuid_str, checkid) != 0) { noitL(nlerr, "unexpected error decoding trap uuid '%s'\n", uuid_str); return -1; } return 0; }
netsnmp_transport * netsnmp_tdomain_transport_oid(const oid * dom, size_t dom_len, const u_char * o, size_t o_len, int local) { netsnmp_tdomain *d; int i; DEBUGMSGTL(("tdomain", "domain \"")); DEBUGMSGOID(("tdomain", dom, dom_len)); DEBUGMSG(("tdomain", "\"\n")); for (d = domain_list; d != NULL; d = d->next) { for (i = 0; d->prefix[i] != NULL; i++) { if (netsnmp_oid_equals(dom, dom_len, d->name, d->name_length) == 0) { return d->f_create_from_ostring(o, o_len, local); } } } snmp_log(LOG_ERR, "No support for requested transport domain\n"); return NULL; }
static int snmp_get_rssi_cb(int operation, struct snmp_session *sp, int reqid, struct snmp_pdu *pdu, void *magic) { char value[15] = {0,}; char *endptr = NULL; int value_num = 0; struct variable_list *vars = NULL; repeater_t *repeater = NULL; in_addr_t ipaddr; flag_t dodbupdate = 0; if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { if (pdu->errstat == SNMP_ERR_NOERROR) { ipaddr = inet_addr(sp->peername); repeater = repeaters_findbyip((struct in_addr *)&ipaddr); for (vars = pdu->variables; vars; vars = vars->next_variable) { if (netsnmp_oid_equals(vars->name, vars->name_length, oid_rssi_ts1, oid_rssi_ts1_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG LOGLEVEL_SNMP "snmp: invalid ts1 rssi value received: %s\n", sp->peername); else { if (value_num > -200) { if (repeater != NULL) { repeater->slot[0].rssi = value_num; if (repeater->slot[0].avg_rssi == 0) repeater->slot[0].avg_rssi = value_num; else repeater->slot[0].avg_rssi = (repeater->slot[0].avg_rssi+value_num)/2.0; dodbupdate = 1; } console_log(LOGLEVEL_SNMP "snmp [%s]: got ts1 rssi value %d\n", sp->peername, value_num); } } } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_rssi_ts2, oid_rssi_ts2_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG LOGLEVEL_SNMP "snmp: invalid ts2 rssi value received: %s\n", value); else { if (value_num > -200) { if (repeater != NULL) { repeater->slot[1].rssi = value_num; if (repeater->slot[1].avg_rssi == 0) repeater->slot[1].avg_rssi = value_num; else repeater->slot[1].avg_rssi = (repeater->slot[1].avg_rssi+value_num)/2.0; dodbupdate = 1; } console_log(LOGLEVEL_SNMP "snmp [%s]: got ts2 rssi value %d\n", sp->peername, value_num); } } } } if (dodbupdate) remotedb_update(repeater); snmp_rssi_received = 1; } else console_log(LOGLEVEL_DEBUG "snmp: rssi read error\n"); } else console_log(LOGLEVEL_DEBUG "snmp: rssi read timeout\n"); return 1; }
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 tsm_process_in_msg(struct snmp_secmod_incoming_params *parms) { u_char type_value; size_t remaining; u_char *data_ptr; netsnmp_tmStateReference *tmStateRef; netsnmp_tsmSecurityReference *tsmSecRef; u_char ourEngineID[SNMP_MAX_ENG_SIZE]; static size_t ourEngineID_len = sizeof(ourEngineID); /* Section 5.2, step 1: Set the securityEngineID to the local snmpEngineID. */ ourEngineID_len = snmpv3_get_engineID((u_char*) ourEngineID, ourEngineID_len); netsnmp_assert_or_return(ourEngineID_len != 0 && ourEngineID_len <= *parms->secEngineIDLen, SNMPERR_GENERR); memcpy(parms->secEngineID, ourEngineID, *parms->secEngineIDLen); /* Section 5.2, step 2: If tmStateReference does not refer to a cache containing values for tmTransportDomain, tmTransportAddress, tmSecurityName, and tmTransportSecurityLevel, then the snmpTsmInvalidCaches counter is incremented, an error indication is returned to the calling module, and Security Model processing stops for this message. */ if (!parms->pdu->transport_data || sizeof(netsnmp_tmStateReference) != parms->pdu->transport_data_length) { /* if we're not coming in over a proper transport; bail! */ DEBUGMSGTL(("tsm","improper transport data\n")); return -1; } tmStateRef = (netsnmp_tmStateReference *) parms->pdu->transport_data; parms->pdu->transport_data = NULL; if (tmStateRef == NULL || /* not needed: tmStateRef->transportDomain == NULL || */ /* not needed: tmStateRef->transportAddress == NULL || */ tmStateRef->securityName[0] == '\0' ) { snmp_increment_statistic(STAT_TSM_SNMPTSMINVALIDCACHES); return SNMPERR_GENERR; } /* Section 5.2, step 3: Copy the tmSecurityName to securityName. */ if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_TSM_USE_PREFIX)) { /* Section 5.2, step 3: If the snmpTsmConfigurationUsePrefix object is set to true, then use the tmTransportDomain to look up the corresponding prefix. */ const char *prefix = NULL; /* possibilities: |--------------------+-------| | snmpTLSTCPDomain | tls: | | snmpDTLSUDPDomain | dtls: | | snmpSSHDomain | ssh: | |--------------------+-------| */ if (tmStateRef->transportDomain == NULL) { /* XXX: snmpTsmInvalidCaches++ ??? */ return SNMPERR_GENERR; } /* XXX: cache in session! */ #ifdef NETSNMP_TRANSPORT_SSH_DOMAIN if (netsnmp_oid_equals(netsnmp_snmpSSHDomain, netsnmp_snmpSSHDomain_len, tmStateRef->transportDomain, tmStateRef->transportDomainLen) == 0) { prefix = "ssh"; } #endif /* NETSNMP_TRANSPORT_SSH_DOMAIN */ #ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN if (netsnmp_oid_equals(netsnmpDTLSUDPDomain, netsnmpDTLSUDPDomain_len, tmStateRef->transportDomain, tmStateRef->transportDomainLen) == 0) { prefix = "dtls"; } #endif /* NETSNMP_TRANSPORT_DTLSUDP_DOMAIN */ #ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN if (netsnmp_oid_equals(netsnmpTLSTCPDomain, netsnmpTLSTCPDomain_len, tmStateRef->transportDomain, tmStateRef->transportDomainLen) == 0) { prefix = "tls"; } #endif /* NETSNMP_TRANSPORT_TLSTCP_DOMAIN */ /* Section 5.2, step 3: If the prefix lookup fails for any reason, then the snmpTsmUnknownPrefixes counter is incremented, an error indication is returned to the calling module, and message processing stops. */ if (prefix == NULL) { snmp_increment_statistic(STAT_TSM_SNMPTSMUNKNOWNPREFIXES); return SNMPERR_GENERR; } /* Section 5.2, step 3: If the lookup succeeds but the prefix length is less than 1 or greater than 4 octets, then the snmpTsmInvalidPrefixes counter is incremented, an error indication is returned to the calling module, and message processing stops. */ #ifdef NOT_USING_HARDCODED_PREFIXES /* the above code actually ensures this will never happen as we don't support a dynamic prefix database where this might happen. */ if (strlen(prefix) < 1 || strlen(prefix) > 4) { /* XXX: snmpTsmInvalidPrefixes++ */ return SNMPERR_GENERR; } #endif /* Section 5.2, step 3: Set the securityName to be the concatenation of the prefix, a ':' character (US-ASCII 0x3a), and the tmSecurityName. */ snprintf(parms->secName, *parms->secNameLen, "%s:%s", prefix, tmStateRef->securityName); } else { /* if the use prefix flag wasn't set, do a straight copy */ strncpy(parms->secName, tmStateRef->securityName, *parms->secNameLen); } /* set the length of the security name */ *parms->secNameLen = strlen(parms->secName); DEBUGMSGTL(("tsm", "user: %s/%d\n", parms->secName, (int)*parms->secNameLen)); /* Section 5.2 Step 4: Compare the value of tmTransportSecurityLevel in the tmStateReference cache to the value of the securityLevel parameter passed in the processIncomingMsg ASI. If securityLevel specifies privacy (Priv) and tmTransportSecurityLevel specifies no privacy (noPriv), or if securityLevel specifies authentication (auth) and tmTransportSecurityLevel specifies no authentication (noAuth) was provided by the Transport Model, then the snmpTsmInadequateSecurityLevels counter is incremented, an error indication (unsupportedSecurityLevel) together with the OID and value of the incremented counter is returned to the calling module, and Transport Security Model processing stops for this message.*/ if (parms->secLevel > tmStateRef->transportSecurityLevel) { snmp_increment_statistic(STAT_TSM_SNMPTSMINADEQUATESECURITYLEVELS); DEBUGMSGTL(("tsm", "inadequate security level: %d\n", parms->secLevel)); /* net-snmp returns error codes not OIDs, which are dealt with later */ return SNMPERR_UNSUPPORTED_SEC_LEVEL; } /* Section 5.2 Step 5 The tmStateReference is cached as cachedSecurityData so that a possible response to this message will use the same security parameters. Then securityStateReference is set for subsequent references to this cached data. */ if (NULL == *parms->secStateRef) { tsmSecRef = SNMP_MALLOC_TYPEDEF(netsnmp_tsmSecurityReference); } else { tsmSecRef = *parms->secStateRef; } netsnmp_assert_or_return(NULL != tsmSecRef, SNMPERR_GENERR); *parms->secStateRef = tsmSecRef; tsmSecRef->tmStateRef = tmStateRef; /* If this did not come through a tunneled connection, this security model is inappropriate (and would be a HUGE security hole to assume otherwise). This is functionally a double check since the pdu wouldn't have transport data otherwise. But this is safer though is functionally an extra step beyond the TSM RFC. */ DEBUGMSGTL(("tsm","checking how we got here\n")); if (!(parms->pdu->flags & UCD_MSG_FLAG_TUNNELED)) { DEBUGMSGTL(("tsm"," pdu not tunneled\n")); if (!(parms->sess->flags & NETSNMP_TRANSPORT_FLAG_TUNNELED)) { DEBUGMSGTL(("tsm"," session not tunneled\n")); return SNMPERR_USM_AUTHENTICATIONFAILURE; } DEBUGMSGTL(("tsm"," but session is tunneled\n")); } else { DEBUGMSGTL(("tsm"," tunneled\n")); } /* Section 5.2, Step 6: The scopedPDU component is extracted from the wholeMsg. */ /* * Eat the first octet header. */ remaining = parms->wholeMsgLen - (parms->secParams - parms->wholeMsg); if ((data_ptr = asn_parse_sequence(parms->secParams, &remaining, &type_value, (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), "tsm first octet")) == NULL) { /* * RETURN parse error */ return SNMPERR_ASN_PARSE_ERR; } *parms->scopedPdu = data_ptr; *parms->scopedPduLen = parms->wholeMsgLen - (data_ptr - parms->wholeMsg); /* Section 5.2, Step 7: The maxSizeResponseScopedPDU is calculated. This is the maximum size allowed for a scopedPDU for a possible Response message. */ *parms->maxSizeResponse = parms->maxMsgSize; /* XXX */ /* Section 5.2, Step 8: The statusInformation is set to success and a return is made to the calling module passing back the OUT parameters as specified in the processIncomingMsg ASI. */ return SNMPERR_SUCCESS; }
/** implements the old_api handler */ int netsnmp_old_api_helper(netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { #if MIB_CLIENTS_ARE_EVIL oid save[MAX_OID_LEN]; size_t savelen = 0; #endif struct variable compat_var, *cvp = &compat_var; int exact = 1; int status; struct variable *vp; netsnmp_old_api_cache *cacheptr; netsnmp_agent_session *oldasp = NULL; u_char *access = NULL; WriteMethod *write_method = NULL; size_t len; size_t tmp_len; oid tmp_name[MAX_OID_LEN]; vp = (struct variable *) handler->myvoid; /* * create old variable structure with right information */ memcpy(cvp->name, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid)); cvp->namelen = reginfo->rootoid_len; cvp->type = vp->type; cvp->magic = vp->magic; cvp->acl = vp->acl; cvp->findVar = vp->findVar; switch (reqinfo->mode) { case MODE_GETNEXT: case MODE_GETBULK: exact = 0; } for (; requests; requests = requests->next) { #if MIB_CLIENTS_ARE_EVIL savelen = requests->requestvb->name_length; memcpy(save, requests->requestvb->name, savelen * sizeof(oid)); #endif switch (reqinfo->mode) { case MODE_GET: case MODE_GETNEXT: #ifndef NETSNMP_NO_WRITE_SUPPORT case MODE_SET_RESERVE1: #endif /* !NETSNMP_NO_WRITE_SUPPORT */ /* * Actually call the old mib-module function */ if (vp && vp->findVar) { memcpy(tmp_name, requests->requestvb->name, requests->requestvb->name_length*sizeof(oid)); tmp_len = requests->requestvb->name_length; access = (*(vp->findVar)) (cvp, tmp_name, &tmp_len, exact, &len, &write_method); snmp_set_var_objid( requests->requestvb, tmp_name, tmp_len ); } else access = NULL; #ifdef WWW_FIX if (IS_DELEGATED(cvp->type)) { add_method = (AddVarMethod *) statP; requests->delayed = 1; have_delegated = 1; continue; /* WWW: This may not get to the right place */ } #endif /* * WWW: end range checking */ if (access) { /* * result returned */ #ifndef NETSNMP_NO_WRITE_SUPPORT if (reqinfo->mode != MODE_SET_RESERVE1) #endif /* !NETSNMP_NO_WRITE_SUPPORT */ snmp_set_var_typed_value(requests->requestvb, cvp->type, access, len); } else { /* * no result returned */ #if MIB_CLIENTS_ARE_EVIL if (access == NULL) { if (netsnmp_oid_equals(requests->requestvb->name, requests->requestvb->name_length, save, savelen) != 0) { DEBUGMSGTL(("old_api", "evil_client: %s\n", reginfo->handlerName)); memcpy(requests->requestvb->name, save, savelen * sizeof(oid)); requests->requestvb->name_length = savelen; } } #endif } /* * AAA: fall through for everything that is a set (see BBB) */ #ifndef NETSNMP_NO_WRITE_SUPPORT if (reqinfo->mode != MODE_SET_RESERVE1) #endif /* !NETSNMP_NO_WRITE_SUPPORT */ break; cacheptr = SNMP_MALLOC_TYPEDEF(netsnmp_old_api_cache); if (!cacheptr) return netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE); cacheptr->data = access; cacheptr->write_method = write_method; write_method = NULL; netsnmp_request_add_list_data(requests, netsnmp_create_data_list (OLD_API_NAME, cacheptr, &free_wrapper)); /* * BBB: fall through for everything that is a set (see AAA) */ default: /* * WWW: explicitly list the SET conditions */ /* * (the rest of the) SET contions */ cacheptr = (netsnmp_old_api_cache *) netsnmp_request_get_list_data(requests, OLD_API_NAME); if (cacheptr == NULL || cacheptr->write_method == NULL) { /* * WWW: try to set ourselves if possible? */ return netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_NOTWRITABLE); } oldasp = netsnmp_get_current_agent_session(); set_current_agent_session(reqinfo->asp); status = (*(cacheptr->write_method)) (reqinfo->mode, requests->requestvb->val. string, requests->requestvb->type, requests->requestvb->val_len, cacheptr->data, requests->requestvb->name, requests->requestvb-> name_length); set_current_agent_session(oldasp); if (status != SNMP_ERR_NOERROR) { netsnmp_set_request_error(reqinfo, requests, status); } /* * clean up is done by the automatic freeing of the * cache stored in the request. */ break; } } return SNMP_ERR_NOERROR; }
static int snmp_get_repeaterinfo_cb(int operation, struct snmp_session *sp, int reqid, struct snmp_pdu *pdu, void *magic) { char value[200] = {0,}; char *endptr = NULL; int value_num = 0; struct variable_list *vars = NULL; repeater_t *repeater = NULL; in_addr_t ipaddr; char value_utf16[sizeof(value)/2] = {0,}; char value_utf8[sizeof(value_utf16)/2] = {0,}; int length = 0; flag_t dodbupdate = 0; if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { if (pdu->errstat == SNMP_ERR_NOERROR) { ipaddr = inet_addr(sp->peername); repeater = repeaters_findbyip((struct in_addr *)&ipaddr); for (vars = pdu->variables; vars; vars = vars->next_variable) { if (netsnmp_oid_equals(vars->name, vars->name_length, oid_id, oid_id_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG "snmp [%s]: invalid id value received: %s\n", sp->peername, value); else { if (repeater != NULL) { repeater->id = value_num; dodbupdate = 1; } console_log("snmp [%s]: got id value %d\n", sp->peername, value_num); } } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_repeatertype, oid_repeatertype_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); length = snmp_hexstring_to_bytearray(value+12, value_utf16, sizeof(value_utf16)); // +12: cutting "Hex-STRING: " text returned by snprint_value(). snmp_utf16_to_utf8(value_utf16, length, value_utf8, sizeof(value_utf8)); if (repeater != NULL) { strncpy(repeater->type, value_utf8, sizeof(repeater->type)); dodbupdate = 1; } console_log("snmp [%s]: got repeater type value %s\n", sp->peername, value_utf8); } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_fwversion, oid_fwversion_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); length = snmp_hexstring_to_bytearray(value+12, value_utf16, sizeof(value_utf16)); // +12: cutting "Hex-STRING: " text returned by snprint_value(). snmp_utf16_to_utf8(value_utf16, length, value_utf8, sizeof(value_utf8)); if (repeater != NULL) { strncpy(repeater->fwversion, value_utf8, sizeof(repeater->fwversion)); dodbupdate = 1; } console_log("snmp [%s]: got repeater fw version value %s\n", sp->peername, value_utf8); } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_callsign, oid_callsign_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); length = snmp_hexstring_to_bytearray(value+12, value_utf16, sizeof(value_utf16)); // +12: cutting "Hex-STRING: " text returned by snprint_value(). snmp_utf16_to_utf8(value_utf16, length, value_utf8, sizeof(value_utf8)); if (repeater != NULL) { strncpy(repeater->callsign, value_utf8, sizeof(repeater->callsign)); dodbupdate = 1; } console_log("snmp [%s]: got repeater callsign value %s\n", sp->peername, value_utf8); } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_dlfreq, oid_dlfreq_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG "snmp [%s]: invalid dl freq value received: %s\n", sp->peername, value); else { if (repeater != NULL) { repeater->dlfreq = value_num; dodbupdate = 1; } console_log("snmp [%s]: got dl freq value %d\n", sp->peername, value_num); } } else if (netsnmp_oid_equals(vars->name, vars->name_length, oid_ulfreq, oid_ulfreq_length) == 0) { snprint_value(value, sizeof(value), vars->name, vars->name_length, vars); errno = 0; value_num = strtol(value+9, &endptr, 10); // +9: cutting "INTEGER: " text returned by snprint_value(). if (*endptr != 0 || errno != 0) console_log(LOGLEVEL_DEBUG "snmp [%s]: invalid dl freq value received: %s\n", sp->peername, value); else { if (repeater != NULL) { repeater->ulfreq = value_num; dodbupdate = 1; } console_log("snmp [%s]: got ul freq value %d\n", sp->peername, value_num); } } } if (dodbupdate) remotedb_update_repeater(repeater); snmp_repeaterinfo_received = 1; } else console_log(LOGLEVEL_DEBUG "snmp [%s]: repeater info read error\n", sp->peername); } else console_log(LOGLEVEL_DEBUG "snmp [%s]: repeater info read timeout\n", sp->peername); return 1; }
/** * Authorizes incoming notifications for further processing */ int netsnmp_trapd_auth(netsnmp_pdu *pdu, netsnmp_transport *transport, netsnmp_trapd_handler *handler) { int ret = 0; oid snmptrapoid[] = { 1,3,6,1,6,3,1,1,4,1,0 }; size_t snmptrapoid_len = OID_LENGTH(snmptrapoid); int i; netsnmp_pdu *newpdu = pdu; netsnmp_variable_list *var; /* check to see if authorization was not disabled */ if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_APP_NO_AUTHORIZATION)) { DEBUGMSGTL(("snmptrapd:auth", "authorization turned off: not checking\n")); return NETSNMPTRAPD_HANDLER_OK; } /* bail early if called illegally */ if (!pdu || !transport || !handler) return NETSNMPTRAPD_HANDLER_FINISH; /* convert to v2 so we can check it in a consistent manner */ #ifndef NETSNMP_DISABLE_SNMPV1 if (pdu->version == SNMP_VERSION_1) { newpdu = convert_v1pdu_to_v2(pdu); if (!newpdu) { snmp_log(LOG_ERR, "Failed to duplicate incoming PDU. Refusing to authorize.\n"); return NETSNMPTRAPD_HANDLER_FINISH; } } #endif if (!vacm_is_configured()) { #ifndef NETSNMP_DISABLE_SNMPV1 if (newpdu != pdu) snmp_free_pdu(newpdu); #endif snmp_log(LOG_WARNING, "No access configuration - dropping trap.\n"); return NETSNMPTRAPD_HANDLER_FINISH; } /* loop through each variable and find the snmpTrapOID.0 var indicating what the trap is we're staring at. */ for (var = newpdu->variables; var != NULL; var = var->next_variable) { if (netsnmp_oid_equals(var->name, var->name_length, snmptrapoid, snmptrapoid_len) == 0) break; } /* make sure we can continue: we found the snmpTrapOID.0 and its an oid */ if (!var || var->type != ASN_OBJECT_ID) { snmp_log(LOG_ERR, "Can't determine trap identifier; refusing to authorize it\n"); #ifndef NETSNMP_DISABLE_SNMPV1 if (newpdu != pdu) snmp_free_pdu(newpdu); #endif return NETSNMPTRAPD_HANDLER_FINISH; } #ifdef USING_MIBII_VACM_CONF_MODULE /* check the pdu against each typo of VACM access we may want to check up on later. We cache the results for future lookup on each call to netsnmp_trapd_check_auth */ for(i = 0; i < VACM_MAX_VIEWS; i++) { /* pass the PDU to the VACM routine for handling authorization */ DEBUGMSGTL(("snmptrapd:auth", "Calling VACM for checking phase %d:%s\n", i, se_find_label_in_slist(VACM_VIEW_ENUM_NAME, i))); if (vacm_check_view_contents(newpdu, var->val.objid, var->val_len/sizeof(oid), 0, i, VACM_CHECK_VIEW_CONTENTS_DNE_CONTEXT_OK) == VACM_SUCCESS) { DEBUGMSGTL(("snmptrapd:auth", " result: authorized\n")); ret |= 1 << i; } else { DEBUGMSGTL(("snmptrapd:auth", " result: not authorized\n")); } } DEBUGMSGTL(("snmptrapd:auth", "Final bitmask auth: %x\n", ret)); #endif if (ret) { /* we have policy to at least do "something". Remember and continue. */ lastlookup = ret; #ifndef NETSNMP_DISABLE_SNMPV1 if (newpdu != pdu) snmp_free_pdu(newpdu); #endif return NETSNMPTRAPD_HANDLER_OK; } /* No policy was met, so we drop the PDU from further processing */ DEBUGMSGTL(("snmptrapd:auth", "Dropping unauthorized message\n")); #ifndef NETSNMP_DISABLE_SNMPV1 if (newpdu != pdu) snmp_free_pdu(newpdu); #endif return NETSNMPTRAPD_HANDLER_FINISH; }