Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_snmp_mib2_interfaces.c Source File

lwip_snmp_mib2_interfaces.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Management Information Base II (RFC1213) INTERFACES 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/netif.h"
00043 #include "lwip/stats.h"
00044 
00045 #include <string.h>
00046 
00047 #if LWIP_SNMP && SNMP_LWIP_MIB2
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 
00059 /* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
00060 
00061 static s16_t
00062 interfaces_get_value(struct snmp_node_instance* instance, void* value)
00063 {
00064   if (instance->node->oid == 1) {
00065     s32_t *sint_ptr = (s32_t*)value;
00066     s32_t num_netifs = 0;
00067 
00068     struct netif *netif = netif_list;
00069     while (netif != NULL) {
00070       num_netifs++;
00071       netif = netif->next;
00072     }
00073 
00074     *sint_ptr = num_netifs;
00075     return sizeof(*sint_ptr);
00076   }
00077 
00078   return 0;
00079 }
00080 
00081 /* list of allowed value ranges for incoming OID */
00082 static const struct snmp_oid_range interfaces_Table_oid_ranges[] = {
00083   { 1, 0xff } /* netif->num is u8_t */
00084 };
00085 
00086 static const u8_t iftable_ifOutQLen         = 0;
00087 
00088 static const u8_t iftable_ifOperStatus_up   = 1;
00089 static const u8_t iftable_ifOperStatus_down = 2;
00090 
00091 static const u8_t iftable_ifAdminStatus_up             = 1;
00092 static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7;
00093 static const u8_t iftable_ifAdminStatus_down           = 2;
00094 
00095 static snmp_err_t
00096 interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance)
00097 {
00098   u32_t ifIndex;
00099   struct netif *netif;
00100 
00101   LWIP_UNUSED_ARG(column);
00102 
00103   /* check if incoming OID length and if values are in plausible range */
00104   if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) {
00105     return SNMP_ERR_NOSUCHINSTANCE;
00106   }
00107 
00108   /* get netif index from incoming OID */
00109   ifIndex = row_oid[0];
00110 
00111   /* find netif with index */
00112   netif = netif_list;
00113   while (netif != NULL) {
00114     if (netif_to_num(netif) == ifIndex) {
00115       /* store netif pointer for subsequent operations (get/test/set) */
00116       cell_instance->reference.ptr = netif;
00117       return SNMP_ERR_NOERROR;
00118     }
00119     netif = netif->next;
00120   }
00121 
00122   /* not found */
00123   return SNMP_ERR_NOSUCHINSTANCE;
00124 }
00125 
00126 static snmp_err_t
00127 interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance)
00128 {
00129   struct netif *netif;
00130   struct snmp_next_oid_state state;
00131   u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
00132 
00133   LWIP_UNUSED_ARG(column);
00134 
00135   /* init struct to search next oid */
00136   snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges));
00137 
00138   /* iterate over all possible OIDs to find the next one */
00139   netif = netif_list;
00140   while (netif != NULL) {
00141     u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
00142     test_oid[0] = netif_to_num(netif);
00143 
00144     /* check generated OID: is it a candidate for the next one? */
00145     snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif);
00146 
00147     netif = netif->next;
00148   }
00149 
00150   /* did we find a next one? */
00151   if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
00152     snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
00153     /* store netif pointer for subsequent operations (get/test/set) */
00154     cell_instance->reference.ptr = /* (struct netif*) */state.reference;
00155     return SNMP_ERR_NOERROR;
00156   }
00157 
00158   /* not found */
00159   return SNMP_ERR_NOSUCHINSTANCE;
00160 }
00161 
00162 static s16_t
00163 interfaces_Table_get_value (struct snmp_node_instance* instance, void* value)
00164 {
00165   struct netif *netif = (struct netif*)instance->reference.ptr;
00166   u32_t* value_u32 = (u32_t*)value;
00167   s32_t* value_s32 = (s32_t*)value;
00168   u16_t value_len;
00169 
00170   switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id))
00171   {
00172   case 1: /* ifIndex */
00173     *value_s32 = netif_to_num(netif);
00174     value_len = sizeof(*value_s32);
00175     break;
00176   case 2: /* ifDescr */
00177     value_len = sizeof(netif->name);
00178     MEMCPY(value, netif->name, value_len);
00179     break;
00180   case 3: /* ifType */
00181     *value_s32 = netif->link_type;
00182     value_len = sizeof(*value_s32);
00183     break;
00184   case 4: /* ifMtu */
00185     *value_s32 = netif->mtu;
00186     value_len = sizeof(*value_s32);
00187     break;
00188   case 5: /* ifSpeed */
00189     *value_u32 = netif->link_speed;
00190     value_len = sizeof(*value_u32);
00191     break;
00192   case 6: /* ifPhysAddress */
00193     value_len = sizeof(netif->hwaddr);
00194     MEMCPY(value, &netif->hwaddr, value_len);
00195     break;
00196   case 7: /* ifAdminStatus */
00197     if (netif_is_up(netif)) {
00198       *value_s32 = iftable_ifOperStatus_up;
00199     } else {
00200       *value_s32 = iftable_ifOperStatus_down;
00201     }
00202     value_len = sizeof(*value_s32);
00203     break;
00204   case 8: /* ifOperStatus */
00205     if (netif_is_up(netif)) {
00206       if (netif_is_link_up(netif)) {
00207         *value_s32 = iftable_ifAdminStatus_up;
00208       } else {
00209         *value_s32 = iftable_ifAdminStatus_lowerLayerDown;
00210       }
00211     } else {
00212       *value_s32 = iftable_ifAdminStatus_down;
00213     }
00214     value_len = sizeof(*value_s32);
00215     break;
00216   case 9: /* ifLastChange */
00217     *value_u32 = netif->ts;
00218     value_len = sizeof(*value_u32);
00219     break;
00220   case 10: /* ifInOctets */
00221     *value_u32 = netif->mib2_counters.ifinoctets;
00222     value_len = sizeof(*value_u32);
00223     break;
00224   case 11: /* ifInUcastPkts */
00225     *value_u32 = netif->mib2_counters.ifinucastpkts;
00226     value_len = sizeof(*value_u32);
00227     break;
00228   case 12: /* ifInNUcastPkts */
00229     *value_u32 = netif->mib2_counters.ifinnucastpkts;
00230     value_len = sizeof(*value_u32);
00231     break;
00232   case 13: /* ifInDiscards */
00233     *value_u32 = netif->mib2_counters.ifindiscards;
00234     value_len = sizeof(*value_u32);
00235     break;
00236   case 14: /* ifInErrors */
00237     *value_u32 = netif->mib2_counters.ifinerrors;
00238     value_len = sizeof(*value_u32);
00239     break;
00240   case 15: /* ifInUnkownProtos */
00241     *value_u32 = netif->mib2_counters.ifinunknownprotos;
00242     value_len = sizeof(*value_u32);
00243     break;
00244   case 16: /* ifOutOctets */
00245     *value_u32 = netif->mib2_counters.ifoutoctets;
00246     value_len = sizeof(*value_u32);
00247     break;
00248   case 17: /* ifOutUcastPkts */
00249     *value_u32 = netif->mib2_counters.ifoutucastpkts;
00250     value_len = sizeof(*value_u32);
00251     break;
00252   case 18: /* ifOutNUcastPkts */
00253     *value_u32 = netif->mib2_counters.ifoutnucastpkts;
00254     value_len = sizeof(*value_u32);
00255     break;
00256   case 19: /* ifOutDiscarts */
00257     *value_u32 = netif->mib2_counters.ifoutdiscards;
00258     value_len = sizeof(*value_u32);
00259     break;
00260   case 20: /* ifOutErrors */
00261     *value_u32 = netif->mib2_counters.ifouterrors;
00262     value_len = sizeof(*value_u32);
00263     break;
00264   case 21: /* ifOutQLen */
00265     *value_u32 = iftable_ifOutQLen;
00266     value_len = sizeof(*value_u32);
00267     break;
00268   /** @note returning zeroDotZero (0.0) no media specific MIB support */
00269   case 22: /* ifSpecific */
00270     value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
00271     MEMCPY(value, snmp_zero_dot_zero.id, value_len);
00272     break;
00273   default:
00274     return 0;
00275   }
00276 
00277   return value_len;
00278 }
00279 
00280 #if !SNMP_SAFE_REQUESTS
00281 
00282 static snmp_err_t
00283 interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
00284 {
00285   s32_t *sint_ptr = (s32_t*)value;
00286 
00287   /* stack should never call this method for another column,
00288   because all other columns are set to readonly */
00289   LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
00290   LWIP_UNUSED_ARG(len);
00291 
00292   if (*sint_ptr == 1 || *sint_ptr == 2) {
00293     return SNMP_ERR_NOERROR;
00294   }
00295 
00296   return SNMP_ERR_WRONGVALUE;
00297 }
00298 
00299 static snmp_err_t
00300 interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
00301 {
00302   struct netif *netif = (struct netif*)instance->reference.ptr;
00303   s32_t *sint_ptr = (s32_t*)value;
00304 
00305   /* stack should never call this method for another column,
00306   because all other columns are set to readonly */
00307   LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
00308   LWIP_UNUSED_ARG(len);
00309 
00310   if (*sint_ptr == 1) {
00311     netif_set_up(netif);
00312   } else if (*sint_ptr == 2) {
00313     netif_set_down(netif);
00314   }
00315 
00316   return SNMP_ERR_NOERROR;
00317 }
00318 
00319 #endif /* SNMP_SAFE_REQUESTS */
00320 
00321 static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value);
00322 
00323 static const struct snmp_table_col_def interfaces_Table_columns[] = {
00324   {  1, SNMP_ASN1_TYPE_INTEGER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */
00325   {  2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */
00326   {  3, SNMP_ASN1_TYPE_INTEGER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */
00327   {  4, SNMP_ASN1_TYPE_INTEGER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */
00328   {  5, SNMP_ASN1_TYPE_GAUGE,        SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */
00329   {  6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */
00330 #if !SNMP_SAFE_REQUESTS
00331   {  7, SNMP_ASN1_TYPE_INTEGER,      SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */
00332 #else
00333   {  7, SNMP_ASN1_TYPE_INTEGER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */
00334 #endif
00335   {  8, SNMP_ASN1_TYPE_INTEGER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */
00336   {  9, SNMP_ASN1_TYPE_TIMETICKS,    SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */
00337   { 10, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */
00338   { 11, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */
00339   { 12, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */
00340   { 13, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */
00341   { 14, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */
00342   { 15, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */
00343   { 16, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */
00344   { 17, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */
00345   { 18, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */
00346   { 19, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */
00347   { 20, SNMP_ASN1_TYPE_COUNTER,      SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */
00348   { 21, SNMP_ASN1_TYPE_GAUGE,        SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */
00349   { 22, SNMP_ASN1_TYPE_OBJECT_ID,    SNMP_NODE_INSTANCE_READ_ONLY }  /* ifSpecific */
00350 };
00351 
00352 #if !SNMP_SAFE_REQUESTS
00353 static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
00354   2, interfaces_Table_columns,
00355   interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
00356   interfaces_Table_get_value , interfaces_Table_set_test, interfaces_Table_set_value);
00357 #else
00358 static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
00359   2, interfaces_Table_columns,
00360   interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
00361   interfaces_Table_get_value , NULL, NULL);
00362 #endif
00363 
00364 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
00365 CREATE_LWIP_SYNC_NODE(1, interfaces_Number)
00366 CREATE_LWIP_SYNC_NODE(2, interfaces_Table)
00367 
00368 static const struct snmp_node* const interface_nodes[] = {
00369   &SYNC_NODE_NAME(interfaces_Number).node.node,
00370   &SYNC_NODE_NAME(interfaces_Table).node.node
00371 };
00372 
00373 const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes);
00374 
00375 #endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */