Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_snmp_mib2_udp.c Source File

lwip_snmp_mib2_udp.c

Go to the documentation of this file.
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   case 8: /* udpHCInDatagrams */
00079     memset(value, 0, 2*sizeof(u32_t)); /* not supported */
00080     return 2*sizeof(u32_t);
00081   case 9: /* udpHCOutDatagrams */
00082     memset(value, 0, 2*sizeof(u32_t)); /* not supported */
00083     return 2*sizeof(u32_t);
00084   default:
00085     LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
00086     break;
00087   }
00088 
00089   return 0;
00090 }
00091 
00092 /* --- udpEndpointTable --- */
00093 
00094 static snmp_err_t
00095 udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
00096 {
00097   /* all items except udpEndpointProcess are declared as not-accessible */
00098   switch (*column) {
00099   case 8: /* udpEndpointProcess */
00100     value->u32 = 0; /* not supported */
00101     break;
00102   default:
00103     return SNMP_ERR_NOSUCHINSTANCE;
00104   }
00105 
00106   return SNMP_ERR_NOERROR;
00107 }
00108 
00109 static snmp_err_t
00110 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)
00111 {
00112   ip_addr_t local_ip, remote_ip;
00113   u16_t local_port, remote_port;
00114   struct udp_pcb *pcb;
00115   u8_t idx = 0;
00116 
00117   LWIP_UNUSED_ARG(value_len);
00118 
00119   /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
00120   idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
00121   if (idx == 0) {
00122     return SNMP_ERR_NOSUCHINSTANCE;
00123   }
00124 
00125   /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
00126   idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
00127   if (idx == 0) {
00128     return SNMP_ERR_NOSUCHINSTANCE;
00129   }
00130 
00131   /* udpEndpointInstance */
00132   if (row_oid_len < (idx+1)) {
00133     return SNMP_ERR_NOSUCHINSTANCE;
00134   }
00135   if (row_oid[idx] != 0) {
00136     return SNMP_ERR_NOSUCHINSTANCE;
00137   }
00138   
00139   /* find udp_pcb with requested ip and port*/
00140   pcb = udp_pcbs;
00141   while (pcb != NULL) {
00142     if (ip_addr_cmp(&local_ip, &pcb->local_ip) &&
00143        (local_port == pcb->local_port) &&
00144        ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
00145        (remote_port == pcb->remote_port)) {
00146       /* fill in object properties */
00147       return udp_endpointTable_get_cell_value_core(column, value);
00148     }
00149     pcb = pcb->next;
00150   }
00151 
00152   /* not found */
00153   return SNMP_ERR_NOSUCHINSTANCE;
00154 }
00155 
00156 static snmp_err_t 
00157 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)
00158 {
00159   struct udp_pcb *pcb;
00160   struct snmp_next_oid_state state;
00161   /* 1x udpEndpointLocalAddressType  + 1x OID len + 16x udpEndpointLocalAddress  + 1x udpEndpointLocalPort  +
00162    * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort +
00163    * 1x udpEndpointInstance = 39
00164    */
00165   u32_t  result_temp[39];
00166 
00167   LWIP_UNUSED_ARG(value_len);
00168 
00169   /* init struct to search next oid */
00170   snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
00171 
00172   /* iterate over all possible OIDs to find the next one */
00173   pcb = udp_pcbs;
00174   while (pcb != NULL) {
00175     u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
00176     u8_t idx = 0;
00177 
00178     /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
00179     idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
00180 
00181     /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
00182     idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
00183 
00184     test_oid[idx] = 0; /* udpEndpointInstance */    
00185     idx++;
00186     
00187     /* check generated OID: is it a candidate for the next one? */
00188     snmp_next_oid_check(&state, test_oid, idx, NULL);
00189     
00190     pcb = pcb->next;
00191   }
00192 
00193   /* did we find a next one? */
00194   if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
00195     snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
00196     /* fill in object properties */
00197     return udp_endpointTable_get_cell_value_core(column, value);
00198   } else {
00199     /* not found */
00200     return SNMP_ERR_NOSUCHINSTANCE;
00201   }
00202 }
00203 
00204 /* --- udpTable --- */
00205 
00206 #if LWIP_IPV4
00207 
00208 /* list of allowed value ranges for incoming OID */
00209 static const struct snmp_oid_range udp_Table_oid_ranges[] = {
00210   { 0, 0xff   }, /* IP A        */
00211   { 0, 0xff   }, /* IP B        */
00212   { 0, 0xff   }, /* IP C        */
00213   { 0, 0xff   }, /* IP D        */
00214   { 1, 0xffff }  /* Port        */
00215 };
00216 
00217 static snmp_err_t 
00218 udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
00219 {
00220   LWIP_UNUSED_ARG(value_len);
00221 
00222   switch (*column) {
00223   case 1: /* udpLocalAddress */
00224     /* set reference to PCB local IP and return a generic node that copies IP4 addresses */
00225     value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
00226     break;
00227   case 2: /* udpLocalPort */
00228     /* set reference to PCB local port and return a generic node that copies u16_t values */
00229     value->u32 = pcb->local_port;
00230     break;
00231   default:
00232     return SNMP_ERR_NOSUCHINSTANCE;
00233   }
00234 
00235   return SNMP_ERR_NOERROR;
00236 }
00237 
00238 static snmp_err_t 
00239 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)
00240 {
00241   ip4_addr_t ip;
00242   u16_t port;
00243   struct udp_pcb *pcb;
00244 
00245   /* check if incoming OID length and if values are in plausible range */
00246   if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) {
00247     return SNMP_ERR_NOSUCHINSTANCE;
00248   }
00249 
00250   /* get IP and port from incoming OID */
00251   snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
00252   port = (u16_t)row_oid[4];
00253 
00254   /* find udp_pcb with requested ip and port*/
00255   pcb = udp_pcbs;
00256   while (pcb != NULL) {
00257     if (IP_IS_V4_VAL(pcb->local_ip)) {
00258       if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) {
00259         /* fill in object properties */
00260         return udp_Table_get_cell_value_core(pcb, column, value, value_len);
00261       }
00262     }
00263     pcb = pcb->next;
00264   }
00265 
00266   /* not found */
00267   return SNMP_ERR_NOSUCHINSTANCE;
00268 }
00269 
00270 static snmp_err_t 
00271 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)
00272 {
00273   struct udp_pcb *pcb;
00274   struct snmp_next_oid_state state;
00275   u32_t  result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
00276 
00277   /* init struct to search next oid */
00278   snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges));
00279 
00280   /* iterate over all possible OIDs to find the next one */
00281   pcb = udp_pcbs;
00282   while (pcb != NULL) {
00283     u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
00284 
00285     if (IP_IS_V4_VAL(pcb->local_ip)) {
00286       snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]);
00287       test_oid[4] = pcb->local_port;
00288 
00289       /* check generated OID: is it a candidate for the next one? */
00290       snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb);
00291     }
00292     
00293     pcb = pcb->next;
00294   }
00295 
00296   /* did we find a next one? */
00297   if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
00298     snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
00299     /* fill in object properties */
00300     return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len);
00301   } else {
00302     /* not found */
00303     return SNMP_ERR_NOSUCHINSTANCE;
00304   }
00305 }
00306 
00307 #endif /* LWIP_IPV4 */
00308 
00309 static const struct snmp_scalar_node udp_inDatagrams    = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER,   udp_get_value);
00310 static const struct snmp_scalar_node udp_noPorts        = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER,   udp_get_value);
00311 static const struct snmp_scalar_node udp_inErrors       = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER,   udp_get_value);
00312 static const struct snmp_scalar_node udp_outDatagrams   = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER,   udp_get_value);
00313 static const struct snmp_scalar_node udp_HCInDatagrams  = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
00314 static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
00315 
00316 #if LWIP_IPV4
00317 static const struct snmp_table_simple_col_def udp_Table_columns[] = {
00318   { 1, SNMP_ASN1_TYPE_IPADDR,  SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */
00319   { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }  /* udpLocalPort */
00320 };
00321 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);
00322 #endif /* LWIP_IPV4 */
00323 
00324 static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = {
00325   /* all items except udpEndpointProcess are declared as not-accessible */   
00326   { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 }  /* udpEndpointProcess */
00327 };
00328 
00329 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);
00330 
00331 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ 
00332 CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams)
00333 CREATE_LWIP_SYNC_NODE(2, udp_noPorts)
00334 CREATE_LWIP_SYNC_NODE(3, udp_inErrors)
00335 CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams)
00336 #if LWIP_IPV4
00337 CREATE_LWIP_SYNC_NODE(5, udp_Table)
00338 #endif /* LWIP_IPV4 */
00339 CREATE_LWIP_SYNC_NODE(7, udp_endpointTable)
00340 CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams)
00341 CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams)
00342 
00343 static const struct snmp_node* const udp_nodes[] = {
00344   &SYNC_NODE_NAME(udp_inDatagrams).node.node,
00345   &SYNC_NODE_NAME(udp_noPorts).node.node,
00346   &SYNC_NODE_NAME(udp_inErrors).node.node,
00347   &SYNC_NODE_NAME(udp_outDatagrams).node.node,
00348 #if LWIP_IPV4
00349   &SYNC_NODE_NAME(udp_Table).node.node,
00350 #endif /* LWIP_IPV4 */
00351   &SYNC_NODE_NAME(udp_endpointTable).node.node,
00352   &SYNC_NODE_NAME(udp_HCInDatagrams).node.node,
00353   &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node
00354 };
00355 
00356 const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes);
00357 #endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */