static snmp_err_t do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn) { const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node; struct threadsync_data *call_data = &threadsync_node->instance->data; if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); return SNMP_ERR_NOSUCHINSTANCE; } memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); instance->reference.ptr = call_data; snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); call_data->proxy_instance.node = &threadsync_node->target->node; call_data->threadsync_node = threadsync_node; call_data->arg1.root_oid = root_oid; call_data->arg2.root_oid_len = root_oid_len; call_synced_function(call_data, fn); if (call_data->retval.err == SNMP_ERR_NOERROR) { instance->access = call_data->proxy_instance.access; instance->asn1_type = call_data->proxy_instance.asn1_type; instance->release_instance = threadsync_release_instance; instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL; instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL; instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL; snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); } return call_data->retval.err; }
static snmp_err_t ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) { struct netif *netif; struct snmp_next_oid_state state; u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); /* iterate over all possible OIDs to find the next one */ netif = netif_list; while (netif != NULL) { u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); netif = netif->next; } /* did we find a next one? */ if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* fill in object properties */ return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); } /* not found */ return SNMP_ERR_NOSUCHINSTANCE; }
static snmp_err_t sensor_table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) { size_t i; struct snmp_next_oid_state state; u32_t result_temp[LWIP_ARRAYSIZE(sensor_table_oid_ranges)]; LWIP_UNUSED_ARG(column); /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(sensor_table_oid_ranges)); /* iterate over all possible OIDs to find the next one */ for(i=0; i<LWIP_ARRAYSIZE(sensors); i++) { if(sensors[i].num != 0) { u32_t test_oid[LWIP_ARRAYSIZE(sensor_table_oid_ranges)]; test_oid[0] = sensors[i].num; /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(sensor_table_oid_ranges), (void*)i); } } /* did we find a next one? */ if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* store sensor index for subsequent operations (get/test/set) */ cell_instance->reference.u32 = LWIP_CONST_CAST(u32_t, state.reference); return SNMP_ERR_NOERROR; } /* not found */ return SNMP_ERR_NOSUCHINSTANCE; }
static snmp_err_t interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) { struct netif *netif; struct snmp_next_oid_state state; u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; LWIP_UNUSED_ARG(column); /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); /* iterate over all possible OIDs to find the next one */ netif = netif_list; while (netif != NULL) { u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; test_oid[0] = netif_to_num(netif); /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); netif = netif->next; } /* did we find a next one? */ if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* store netif pointer for subsequent operations (get/test/set) */ cell_instance->reference.ptr = /* (struct netif*) */state.reference; return SNMP_ERR_NOERROR; } /* not found */ return SNMP_ERR_NOSUCHINSTANCE; }
static snmp_err_t tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) { u8_t i; struct tcp_pcb *pcb; struct snmp_next_oid_state state; u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); /* iterate over all possible OIDs to find the next one */ for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { pcb = *tcp_pcb_lists[i]; while (pcb != NULL) { u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; if (IP_IS_V4_VAL(pcb->local_ip)) { snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); test_oid[4] = pcb->local_port; /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ if (pcb->state == LISTEN) { snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[5]); test_oid[9] = 0; } else { if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ continue; } snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); test_oid[9] = pcb->remote_port; } /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); } pcb = pcb->next; } } /* did we find a next one? */ if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* fill in object properties */ return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); } /* not found */ return SNMP_ERR_NOSUCHINSTANCE; }
static snmp_err_t udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) { struct udp_pcb *pcb; struct snmp_next_oid_state state; /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + * 1x udpEndpointInstance = 39 */ u32_t result_temp[39]; LWIP_UNUSED_ARG(value_len); /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); /* iterate over all possible OIDs to find the next one */ pcb = udp_pcbs; while (pcb != NULL) { u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; u8_t idx = 0; /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); test_oid[idx] = 0; /* udpEndpointInstance */ idx++; /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, idx, NULL); pcb = pcb->next; } /* did we find a next one? */ if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* fill in object properties */ return udp_endpointTable_get_cell_value_core(column, value); } else { /* not found */ return SNMP_ERR_NOSUCHINSTANCE; } }
static snmp_err_t tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) { struct tcp_pcb *pcb; struct snmp_next_oid_state state; /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ u32_t result_temp[38]; u8_t i; struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; LWIP_UNUSED_ARG(value_len); /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); /* iterate over all possible OIDs to find the next one */ for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { pcb = *tcp_pcb_nonlisten_lists[i]; while (pcb != NULL) { u8_t idx = 0; u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, idx, pcb); pcb = pcb->next; } } /* did we find a next one? */ if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* fill in object properties */ return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); } else { /* not found */ return SNMP_ERR_NOSUCHINSTANCE; } }
static snmp_err_t ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) { u8_t i; struct snmp_next_oid_state state; u32_t result_temp[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)]; /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); /* iterate over all possible OIDs to find the next one */ for (i=0; i<ARP_TABLE_SIZE; i++) { ip4_addr_t *ip; struct netif *netif; struct eth_addr *ethaddr; if (etharp_get_entry(i, &ip, &netif, ðaddr)) { u32_t test_oid[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)]; test_oid[0] = netif_to_num(netif); snmp_ip4_to_oid(ip, &test_oid[1]); /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i); } } /* did we find a next one? */ if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* fill in object properties */ return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len); } /* not found */ return SNMP_ERR_NOSUCHINSTANCE; }
static snmp_err_t udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) { struct udp_pcb *pcb; struct snmp_next_oid_state state; u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; /* init struct to search next oid */ snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); /* iterate over all possible OIDs to find the next one */ pcb = udp_pcbs; while (pcb != NULL) { u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; if(IP_IS_V4_VAL(pcb->local_ip)) { snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); test_oid[4] = pcb->local_port; /* check generated OID: is it a candidate for the next one? */ snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); } pcb = pcb->next; } /* did we find a next one? */ if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); /* fill in object properties */ return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len); } else { /* not found */ return SNMP_ERR_NOSUCHINSTANCE; } }
static void snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) { err_t err; struct snmp_node_instance node_instance; memset(&node_instance, 0, sizeof(node_instance)); if (get_next) { struct snmp_obj_id result_oid; request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance); if (request->error_status == SNMP_ERR_NOERROR) { snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); } } else { request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); if (request->error_status == SNMP_ERR_NOERROR) { /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); if (request->error_status != SNMP_ERR_NOERROR) { if (node_instance.release_instance != NULL) { node_instance.release_instance(&node_instance); } } } } if (request->error_status != SNMP_ERR_NOERROR) { if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { if (request->version == SNMP_VERSION_2c) { /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); vb->value_len = 0; err = snmp_append_outbound_varbind(request, vb); if (err == ERR_OK) { /* we stored the exception in varbind -> go on */ request->error_status = SNMP_ERR_NOERROR; } else if (err == ERR_BUF) { request->error_status = SNMP_ERR_TOOBIG; } else { request->error_status = SNMP_ERR_GENERROR; } } } else { /* according to RFC 1157/1905, all other errors only return genError */ request->error_status = SNMP_ERR_GENERROR; } } else { vb->type = node_instance.asn1_type; vb->value_len = node_instance.get_value(&node_instance, vb->value); LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); err = snmp_append_outbound_varbind(request, vb); if (err == ERR_BUF) { request->error_status = SNMP_ERR_TOOBIG; } else if (err != ERR_OK) { request->error_status = SNMP_ERR_GENERROR; } if (node_instance.release_instance != NULL) { node_instance.release_instance(&node_instance); } } }
snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) { const struct snmp_table_node* table_node = (const struct snmp_table_node*)instance->node; const struct snmp_table_col_def* col_def; struct snmp_obj_id row_oid; u32_t column = 0; snmp_err_t result; LWIP_UNUSED_ARG(root_oid); LWIP_UNUSED_ARG(root_oid_len); /* check that first part of id is 0 or 1, referencing fixed row entry */ if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { return SNMP_ERR_NOSUCHINSTANCE; } if (instance->instance_oid.len > 1) { column = instance->instance_oid.id[1]; } if (instance->instance_oid.len > 2) { snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); } else { row_oid.len = 0; } instance->get_value = table_node->get_value; instance->set_test = table_node->set_test; instance->set_value = table_node->set_value; /* resolve column and value */ do { u16_t i; const struct snmp_table_col_def* next_col_def = NULL; col_def = table_node->columns; for (i=0; i<table_node->column_count; i++) { if (col_def->index == column) { next_col_def = col_def; break; } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { next_col_def = col_def; } col_def++; } if (next_col_def == NULL) { /* no further column found */ return SNMP_ERR_NOSUCHINSTANCE; } instance->asn1_type = next_col_def->asn1_type; instance->access = next_col_def->access; result = table_node->get_next_cell_instance( &next_col_def->index, &row_oid, instance); if (result == SNMP_ERR_NOERROR) { col_def = next_col_def; break; } row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ column = next_col_def->index + 1; } while (1); /* build resulting oid */ instance->instance_oid.len = 2; instance->instance_oid.id[0] = 1; instance->instance_oid.id[1] = col_def->index; snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); return SNMP_ERR_NOERROR; }
snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) { const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)instance->node; const struct snmp_table_simple_col_def* col_def; struct snmp_obj_id row_oid; u32_t column = 0; snmp_err_t result; LWIP_UNUSED_ARG(root_oid); LWIP_UNUSED_ARG(root_oid_len); /* check that first part of id is 0 or 1, referencing fixed row entry */ if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { return SNMP_ERR_NOSUCHINSTANCE; } if (instance->instance_oid.len > 1) { column = instance->instance_oid.id[1]; } if (instance->instance_oid.len > 2) { snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); } else { row_oid.len = 0; } /* resolve column and value */ do { u32_t i; const struct snmp_table_simple_col_def* next_col_def = NULL; col_def = table_node->columns; for (i=0; i<table_node->column_count; i++) { if (col_def->index == column) { next_col_def = col_def; break; } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { next_col_def = col_def; } col_def++; } if (next_col_def == NULL) { /* no further column found */ return SNMP_ERR_NOSUCHINSTANCE; } result = table_node->get_next_cell_instance_and_value( &next_col_def->index, &row_oid, &instance->reference, &instance->reference_len); if (result == SNMP_ERR_NOERROR) { col_def = next_col_def; break; } row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ column = next_col_def->index + 1; } while (1); instance->asn1_type = col_def->asn1_type; instance->access = SNMP_NODE_INSTANCE_READ_ONLY; instance->set_test = NULL; instance->set_value = NULL; switch (col_def->data_type) { case SNMP_VARIANT_VALUE_TYPE_U32: instance->get_value = snmp_table_extract_value_from_u32ref; break; case SNMP_VARIANT_VALUE_TYPE_S32: instance->get_value = snmp_table_extract_value_from_s32ref; break; case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: instance->get_value = snmp_table_extract_value_from_refconstptr; break; default: LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); return SNMP_ERR_GENERROR; } /* build resulting oid */ instance->instance_oid.len = 2; instance->instance_oid.id[0] = 1; instance->instance_oid.id[1] = col_def->index; snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); return SNMP_ERR_NOERROR; }