Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_snmp_mib2_udp.c
00001 /** 00002 * @file 00003 * Management Information Base II (RFC1213) UDP objects and functions. 00004 */ 00005 00006 /* 00007 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without modification, 00011 * are permitted provided that the following conditions are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. The name of the author may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00024 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00026 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00029 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00030 * OF SUCH DAMAGE. 00031 * 00032 * Author: Dirk Ziegelmeier <dziegel@gmx.de> 00033 * Christiaan Simons <christiaan.simons@axon.tv> 00034 */ 00035 00036 #include "lwip/snmp.h" 00037 #include "lwip/apps/snmp.h" 00038 #include "lwip/apps/snmp_core.h" 00039 #include "lwip/apps/snmp_mib2.h" 00040 #include "lwip/apps/snmp_table.h" 00041 #include "lwip/apps/snmp_scalar.h" 00042 #include "lwip/udp.h" 00043 #include "lwip/stats.h" 00044 00045 #include <string.h> 00046 00047 #if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP 00048 00049 #if SNMP_USE_NETCONN 00050 #define SYNC_NODE_NAME(node_name) node_name ## _synced 00051 #define CREATE_LWIP_SYNC_NODE(oid, node_name) \ 00052 static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); 00053 #else 00054 #define SYNC_NODE_NAME(node_name) node_name 00055 #define CREATE_LWIP_SYNC_NODE(oid, node_name) 00056 #endif 00057 00058 /* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ 00059 00060 static s16_t 00061 udp_get_value(struct snmp_node_instance *instance, void *value) 00062 { 00063 u32_t *uint_ptr = (u32_t *)value; 00064 00065 switch (instance->node->oid) { 00066 case 1: /* udpInDatagrams */ 00067 *uint_ptr = STATS_GET(mib2.udpindatagrams); 00068 return sizeof(*uint_ptr); 00069 case 2: /* udpNoPorts */ 00070 *uint_ptr = STATS_GET(mib2.udpnoports); 00071 return sizeof(*uint_ptr); 00072 case 3: /* udpInErrors */ 00073 *uint_ptr = STATS_GET(mib2.udpinerrors); 00074 return sizeof(*uint_ptr); 00075 case 4: /* udpOutDatagrams */ 00076 *uint_ptr = STATS_GET(mib2.udpoutdatagrams); 00077 return sizeof(*uint_ptr); 00078 #if LWIP_HAVE_INT64 00079 case 8: { /* udpHCInDatagrams */ 00080 /* use the 32 bit counter for now... */ 00081 u64_t val64 = STATS_GET(mib2.udpindatagrams); 00082 *((u64_t *)value) = val64; 00083 } 00084 return sizeof(u64_t); 00085 case 9: { /* udpHCOutDatagrams */ 00086 /* use the 32 bit counter for now... */ 00087 u64_t val64 = STATS_GET(mib2.udpoutdatagrams); 00088 *((u64_t *)value) = val64; 00089 } 00090 return sizeof(u64_t); 00091 #endif 00092 default: 00093 LWIP_DEBUGF(SNMP_MIB_DEBUG, ("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); 00094 break; 00095 } 00096 00097 return 0; 00098 } 00099 00100 /* --- udpEndpointTable --- */ 00101 00102 static snmp_err_t 00103 udp_endpointTable_get_cell_value_core(const u32_t *column, union snmp_variant_value *value) 00104 { 00105 /* all items except udpEndpointProcess are declared as not-accessible */ 00106 switch (*column) { 00107 case 8: /* udpEndpointProcess */ 00108 value->u32 = 0; /* not supported */ 00109 break; 00110 default: 00111 return SNMP_ERR_NOSUCHINSTANCE; 00112 } 00113 00114 return SNMP_ERR_NOERROR; 00115 } 00116 00117 static snmp_err_t 00118 udp_endpointTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) 00119 { 00120 ip_addr_t local_ip, remote_ip; 00121 u16_t local_port, remote_port; 00122 struct udp_pcb *pcb; 00123 u8_t idx = 0; 00124 00125 LWIP_UNUSED_ARG(value_len); 00126 00127 /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ 00128 idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &local_ip, &local_port); 00129 if (idx == 0) { 00130 return SNMP_ERR_NOSUCHINSTANCE; 00131 } 00132 00133 /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ 00134 idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &remote_ip, &remote_port); 00135 if (idx == 0) { 00136 return SNMP_ERR_NOSUCHINSTANCE; 00137 } 00138 00139 /* udpEndpointInstance */ 00140 if (row_oid_len < (idx + 1)) { 00141 return SNMP_ERR_NOSUCHINSTANCE; 00142 } 00143 if (row_oid[idx] != 0) { 00144 return SNMP_ERR_NOSUCHINSTANCE; 00145 } 00146 00147 /* find udp_pcb with requested ip and port*/ 00148 pcb = udp_pcbs; 00149 while (pcb != NULL) { 00150 if (ip_addr_cmp(&local_ip, &pcb->local_ip) && 00151 (local_port == pcb->local_port) && 00152 ip_addr_cmp(&remote_ip, &pcb->remote_ip) && 00153 (remote_port == pcb->remote_port)) { 00154 /* fill in object properties */ 00155 return udp_endpointTable_get_cell_value_core(column, value); 00156 } 00157 pcb = pcb->next; 00158 } 00159 00160 /* not found */ 00161 return SNMP_ERR_NOSUCHINSTANCE; 00162 } 00163 00164 static snmp_err_t 00165 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) 00166 { 00167 struct udp_pcb *pcb; 00168 struct snmp_next_oid_state state; 00169 /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + 00170 * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + 00171 * 1x udpEndpointInstance = 39 00172 */ 00173 u32_t result_temp[39]; 00174 00175 LWIP_UNUSED_ARG(value_len); 00176 00177 /* init struct to search next oid */ 00178 snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); 00179 00180 /* iterate over all possible OIDs to find the next one */ 00181 pcb = udp_pcbs; 00182 while (pcb != NULL) { 00183 u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; 00184 u8_t idx = 0; 00185 00186 /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ 00187 idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); 00188 00189 /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ 00190 idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); 00191 00192 test_oid[idx] = 0; /* udpEndpointInstance */ 00193 idx++; 00194 00195 /* check generated OID: is it a candidate for the next one? */ 00196 snmp_next_oid_check(&state, test_oid, idx, NULL); 00197 00198 pcb = pcb->next; 00199 } 00200 00201 /* did we find a next one? */ 00202 if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { 00203 snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); 00204 /* fill in object properties */ 00205 return udp_endpointTable_get_cell_value_core(column, value); 00206 } else { 00207 /* not found */ 00208 return SNMP_ERR_NOSUCHINSTANCE; 00209 } 00210 } 00211 00212 /* --- udpTable --- */ 00213 00214 #if LWIP_IPV4 00215 00216 /* list of allowed value ranges for incoming OID */ 00217 static const struct snmp_oid_range udp_Table_oid_ranges[] = { 00218 { 0, 0xff }, /* IP A */ 00219 { 0, 0xff }, /* IP B */ 00220 { 0, 0xff }, /* IP C */ 00221 { 0, 0xff }, /* IP D */ 00222 { 1, 0xffff } /* Port */ 00223 }; 00224 00225 static snmp_err_t 00226 udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t *column, union snmp_variant_value *value, u32_t *value_len) 00227 { 00228 LWIP_UNUSED_ARG(value_len); 00229 00230 switch (*column) { 00231 case 1: /* udpLocalAddress */ 00232 /* set reference to PCB local IP and return a generic node that copies IP4 addresses */ 00233 value->u32 = ip_2_ip4(&pcb->local_ip)->addr; 00234 break; 00235 case 2: /* udpLocalPort */ 00236 /* set reference to PCB local port and return a generic node that copies u16_t values */ 00237 value->u32 = pcb->local_port; 00238 break; 00239 default: 00240 return SNMP_ERR_NOSUCHINSTANCE; 00241 } 00242 00243 return SNMP_ERR_NOERROR; 00244 } 00245 00246 static snmp_err_t 00247 udp_Table_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) 00248 { 00249 ip4_addr_t ip; 00250 u16_t port; 00251 struct udp_pcb *pcb; 00252 00253 /* check if incoming OID length and if values are in plausible range */ 00254 if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { 00255 return SNMP_ERR_NOSUCHINSTANCE; 00256 } 00257 00258 /* get IP and port from incoming OID */ 00259 snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ 00260 port = (u16_t)row_oid[4]; 00261 00262 /* find udp_pcb with requested ip and port*/ 00263 pcb = udp_pcbs; 00264 while (pcb != NULL) { 00265 if (IP_IS_V4_VAL(pcb->local_ip)) { 00266 if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { 00267 /* fill in object properties */ 00268 return udp_Table_get_cell_value_core(pcb, column, value, value_len); 00269 } 00270 } 00271 pcb = pcb->next; 00272 } 00273 00274 /* not found */ 00275 return SNMP_ERR_NOSUCHINSTANCE; 00276 } 00277 00278 static snmp_err_t 00279 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) 00280 { 00281 struct udp_pcb *pcb; 00282 struct snmp_next_oid_state state; 00283 u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; 00284 00285 /* init struct to search next oid */ 00286 snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); 00287 00288 /* iterate over all possible OIDs to find the next one */ 00289 pcb = udp_pcbs; 00290 while (pcb != NULL) { 00291 u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; 00292 00293 if (IP_IS_V4_VAL(pcb->local_ip)) { 00294 snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); 00295 test_oid[4] = pcb->local_port; 00296 00297 /* check generated OID: is it a candidate for the next one? */ 00298 snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); 00299 } 00300 00301 pcb = pcb->next; 00302 } 00303 00304 /* did we find a next one? */ 00305 if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { 00306 snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); 00307 /* fill in object properties */ 00308 return udp_Table_get_cell_value_core((struct udp_pcb *)state.reference, column, value, value_len); 00309 } else { 00310 /* not found */ 00311 return SNMP_ERR_NOSUCHINSTANCE; 00312 } 00313 } 00314 00315 #endif /* LWIP_IPV4 */ 00316 00317 static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); 00318 static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); 00319 static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); 00320 static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); 00321 #if LWIP_HAVE_INT64 00322 static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); 00323 static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); 00324 #endif 00325 00326 #if LWIP_IPV4 00327 static const struct snmp_table_simple_col_def udp_Table_columns[] = { 00328 { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ 00329 { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ 00330 }; 00331 static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); 00332 #endif /* LWIP_IPV4 */ 00333 00334 static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { 00335 /* all items except udpEndpointProcess are declared as not-accessible */ 00336 { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ 00337 }; 00338 00339 static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); 00340 00341 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ 00342 CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) 00343 CREATE_LWIP_SYNC_NODE(2, udp_noPorts) 00344 CREATE_LWIP_SYNC_NODE(3, udp_inErrors) 00345 CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) 00346 #if LWIP_IPV4 00347 CREATE_LWIP_SYNC_NODE(5, udp_Table) 00348 #endif /* LWIP_IPV4 */ 00349 CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) 00350 #if LWIP_HAVE_INT64 00351 CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) 00352 CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) 00353 #endif 00354 00355 static const struct snmp_node *const udp_nodes[] = { 00356 &SYNC_NODE_NAME(udp_inDatagrams).node.node, 00357 &SYNC_NODE_NAME(udp_noPorts).node.node, 00358 &SYNC_NODE_NAME(udp_inErrors).node.node, 00359 &SYNC_NODE_NAME(udp_outDatagrams).node.node, 00360 #if LWIP_IPV4 00361 &SYNC_NODE_NAME(udp_Table).node.node, 00362 #endif /* LWIP_IPV4 */ 00363 &SYNC_NODE_NAME(udp_endpointTable).node.node 00364 #if LWIP_HAVE_INT64 00365 , 00366 &SYNC_NODE_NAME(udp_HCInDatagrams).node.node, 00367 &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node 00368 #endif 00369 }; 00370 00371 const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); 00372 #endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */
Generated on Tue Jul 12 2022 13:54:30 by
