[457] | 1 | /**
|
---|
| 2 | * @file
|
---|
| 3 | * Management Information Base II (RFC1213) INTERFACES objects and functions.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
| 7 | * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
---|
| 8 | * All rights reserved.
|
---|
| 9 | *
|
---|
| 10 | * Redistribution and use in source and binary forms, with or without modification,
|
---|
| 11 | * are permitted provided that the following conditions are met:
|
---|
| 12 | *
|
---|
| 13 | * 1. Redistributions of source code must retain the above copyright notice,
|
---|
| 14 | * this list of conditions and the following disclaimer.
|
---|
| 15 | * 2. Redistributions in binary form must reproduce the above copyright notice,
|
---|
| 16 | * this list of conditions and the following disclaimer in the documentation
|
---|
| 17 | * and/or other materials provided with the distribution.
|
---|
| 18 | * 3. The name of the author may not be used to endorse or promote products
|
---|
| 19 | * derived from this software without specific prior written permission.
|
---|
| 20 | *
|
---|
| 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
---|
| 22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
---|
| 23 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
---|
| 24 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
---|
| 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
---|
| 26 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
| 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
| 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
---|
| 29 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
---|
| 30 | * OF SUCH DAMAGE.
|
---|
| 31 | *
|
---|
| 32 | * Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
---|
| 33 | * Christiaan Simons <christiaan.simons@axon.tv>
|
---|
| 34 | */
|
---|
| 35 |
|
---|
| 36 | #include "lwip/snmp.h"
|
---|
| 37 | #include "lwip/apps/snmp.h"
|
---|
| 38 | #include "lwip/apps/snmp_core.h"
|
---|
| 39 | #include "lwip/apps/snmp_mib2.h"
|
---|
| 40 | #include "lwip/apps/snmp_table.h"
|
---|
| 41 | #include "lwip/apps/snmp_scalar.h"
|
---|
| 42 | #include "lwip/netif.h"
|
---|
| 43 | #include "lwip/stats.h"
|
---|
| 44 |
|
---|
| 45 | #include <string.h>
|
---|
| 46 |
|
---|
| 47 | #if LWIP_SNMP && SNMP_LWIP_MIB2
|
---|
| 48 |
|
---|
| 49 | #if SNMP_USE_NETCONN
|
---|
| 50 | #define SYNC_NODE_NAME(node_name) node_name ## _synced
|
---|
| 51 | #define CREATE_LWIP_SYNC_NODE(oid, node_name) \
|
---|
| 52 | static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
|
---|
| 53 | #else
|
---|
| 54 | #define SYNC_NODE_NAME(node_name) node_name
|
---|
| 55 | #define CREATE_LWIP_SYNC_NODE(oid, node_name)
|
---|
| 56 | #endif
|
---|
| 57 |
|
---|
| 58 |
|
---|
| 59 | /* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
|
---|
| 60 |
|
---|
| 61 | static s16_t
|
---|
| 62 | interfaces_get_value(struct snmp_node_instance *instance, void *value)
|
---|
| 63 | {
|
---|
| 64 | if (instance->node->oid == 1) {
|
---|
| 65 | s32_t *sint_ptr = (s32_t *)value;
|
---|
| 66 | s32_t num_netifs = 0;
|
---|
| 67 |
|
---|
| 68 | struct netif *netif;
|
---|
| 69 | NETIF_FOREACH(netif) {
|
---|
| 70 | num_netifs++;
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | *sint_ptr = num_netifs;
|
---|
| 74 | return sizeof(*sint_ptr);
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | return 0;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | /* list of allowed value ranges for incoming OID */
|
---|
| 81 | static const struct snmp_oid_range interfaces_Table_oid_ranges[] = {
|
---|
| 82 | { 1, 0xff } /* netif->num is u8_t */
|
---|
| 83 | };
|
---|
| 84 |
|
---|
| 85 | static const u8_t iftable_ifOutQLen = 0;
|
---|
| 86 |
|
---|
| 87 | static const u8_t iftable_ifOperStatus_up = 1;
|
---|
| 88 | static const u8_t iftable_ifOperStatus_down = 2;
|
---|
| 89 |
|
---|
| 90 | static const u8_t iftable_ifAdminStatus_up = 1;
|
---|
| 91 | static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7;
|
---|
| 92 | static const u8_t iftable_ifAdminStatus_down = 2;
|
---|
| 93 |
|
---|
| 94 | static snmp_err_t
|
---|
| 95 | 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)
|
---|
| 96 | {
|
---|
| 97 | u32_t ifIndex;
|
---|
| 98 | struct netif *netif;
|
---|
| 99 |
|
---|
| 100 | LWIP_UNUSED_ARG(column);
|
---|
| 101 |
|
---|
| 102 | /* check if incoming OID length and if values are in plausible range */
|
---|
| 103 | if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) {
|
---|
| 104 | return SNMP_ERR_NOSUCHINSTANCE;
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | /* get netif index from incoming OID */
|
---|
| 108 | ifIndex = row_oid[0];
|
---|
| 109 |
|
---|
| 110 | /* find netif with index */
|
---|
| 111 | NETIF_FOREACH(netif) {
|
---|
| 112 | if (netif_to_num(netif) == ifIndex) {
|
---|
| 113 | /* store netif pointer for subsequent operations (get/test/set) */
|
---|
| 114 | cell_instance->reference.ptr = netif;
|
---|
| 115 | return SNMP_ERR_NOERROR;
|
---|
| 116 | }
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | /* not found */
|
---|
| 120 | return SNMP_ERR_NOSUCHINSTANCE;
|
---|
| 121 | }
|
---|
| 122 |
|
---|
| 123 | static snmp_err_t
|
---|
| 124 | interfaces_Table_get_next_cell_instance(const u32_t *column, struct snmp_obj_id *row_oid, struct snmp_node_instance *cell_instance)
|
---|
| 125 | {
|
---|
| 126 | struct netif *netif;
|
---|
| 127 | struct snmp_next_oid_state state;
|
---|
| 128 | u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
|
---|
| 129 |
|
---|
| 130 | LWIP_UNUSED_ARG(column);
|
---|
| 131 |
|
---|
| 132 | /* init struct to search next oid */
|
---|
| 133 | snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges));
|
---|
| 134 |
|
---|
| 135 | /* iterate over all possible OIDs to find the next one */
|
---|
| 136 | NETIF_FOREACH(netif) {
|
---|
| 137 | u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
|
---|
| 138 | test_oid[0] = netif_to_num(netif);
|
---|
| 139 |
|
---|
| 140 | /* check generated OID: is it a candidate for the next one? */
|
---|
| 141 | snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif);
|
---|
| 142 | }
|
---|
| 143 |
|
---|
| 144 | /* did we find a next one? */
|
---|
| 145 | if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
|
---|
| 146 | snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
|
---|
| 147 | /* store netif pointer for subsequent operations (get/test/set) */
|
---|
| 148 | cell_instance->reference.ptr = /* (struct netif*) */state.reference;
|
---|
| 149 | return SNMP_ERR_NOERROR;
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | /* not found */
|
---|
| 153 | return SNMP_ERR_NOSUCHINSTANCE;
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | static s16_t
|
---|
| 157 | interfaces_Table_get_value(struct snmp_node_instance *instance, void *value)
|
---|
| 158 | {
|
---|
| 159 | struct netif *netif = (struct netif *)instance->reference.ptr;
|
---|
| 160 | u32_t *value_u32 = (u32_t *)value;
|
---|
| 161 | s32_t *value_s32 = (s32_t *)value;
|
---|
| 162 | u16_t value_len;
|
---|
| 163 |
|
---|
| 164 | switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) {
|
---|
| 165 | case 1: /* ifIndex */
|
---|
| 166 | *value_s32 = netif_to_num(netif);
|
---|
| 167 | value_len = sizeof(*value_s32);
|
---|
| 168 | break;
|
---|
| 169 | case 2: /* ifDescr */
|
---|
| 170 | value_len = sizeof(netif->name);
|
---|
| 171 | MEMCPY(value, netif->name, value_len);
|
---|
| 172 | break;
|
---|
| 173 | case 3: /* ifType */
|
---|
| 174 | *value_s32 = netif->link_type;
|
---|
| 175 | value_len = sizeof(*value_s32);
|
---|
| 176 | break;
|
---|
| 177 | case 4: /* ifMtu */
|
---|
| 178 | *value_s32 = netif->mtu;
|
---|
| 179 | value_len = sizeof(*value_s32);
|
---|
| 180 | break;
|
---|
| 181 | case 5: /* ifSpeed */
|
---|
| 182 | *value_u32 = netif->link_speed;
|
---|
| 183 | value_len = sizeof(*value_u32);
|
---|
| 184 | break;
|
---|
| 185 | case 6: /* ifPhysAddress */
|
---|
| 186 | value_len = sizeof(netif->hwaddr);
|
---|
| 187 | MEMCPY(value, &netif->hwaddr, value_len);
|
---|
| 188 | break;
|
---|
| 189 | case 7: /* ifAdminStatus */
|
---|
| 190 | if (netif_is_up(netif)) {
|
---|
| 191 | *value_s32 = iftable_ifOperStatus_up;
|
---|
| 192 | } else {
|
---|
| 193 | *value_s32 = iftable_ifOperStatus_down;
|
---|
| 194 | }
|
---|
| 195 | value_len = sizeof(*value_s32);
|
---|
| 196 | break;
|
---|
| 197 | case 8: /* ifOperStatus */
|
---|
| 198 | if (netif_is_up(netif)) {
|
---|
| 199 | if (netif_is_link_up(netif)) {
|
---|
| 200 | *value_s32 = iftable_ifAdminStatus_up;
|
---|
| 201 | } else {
|
---|
| 202 | *value_s32 = iftable_ifAdminStatus_lowerLayerDown;
|
---|
| 203 | }
|
---|
| 204 | } else {
|
---|
| 205 | *value_s32 = iftable_ifAdminStatus_down;
|
---|
| 206 | }
|
---|
| 207 | value_len = sizeof(*value_s32);
|
---|
| 208 | break;
|
---|
| 209 | case 9: /* ifLastChange */
|
---|
| 210 | *value_u32 = netif->ts;
|
---|
| 211 | value_len = sizeof(*value_u32);
|
---|
| 212 | break;
|
---|
| 213 | case 10: /* ifInOctets */
|
---|
| 214 | *value_u32 = netif->mib2_counters.ifinoctets;
|
---|
| 215 | value_len = sizeof(*value_u32);
|
---|
| 216 | break;
|
---|
| 217 | case 11: /* ifInUcastPkts */
|
---|
| 218 | *value_u32 = netif->mib2_counters.ifinucastpkts;
|
---|
| 219 | value_len = sizeof(*value_u32);
|
---|
| 220 | break;
|
---|
| 221 | case 12: /* ifInNUcastPkts */
|
---|
| 222 | *value_u32 = netif->mib2_counters.ifinnucastpkts;
|
---|
| 223 | value_len = sizeof(*value_u32);
|
---|
| 224 | break;
|
---|
| 225 | case 13: /* ifInDiscards */
|
---|
| 226 | *value_u32 = netif->mib2_counters.ifindiscards;
|
---|
| 227 | value_len = sizeof(*value_u32);
|
---|
| 228 | break;
|
---|
| 229 | case 14: /* ifInErrors */
|
---|
| 230 | *value_u32 = netif->mib2_counters.ifinerrors;
|
---|
| 231 | value_len = sizeof(*value_u32);
|
---|
| 232 | break;
|
---|
| 233 | case 15: /* ifInUnkownProtos */
|
---|
| 234 | *value_u32 = netif->mib2_counters.ifinunknownprotos;
|
---|
| 235 | value_len = sizeof(*value_u32);
|
---|
| 236 | break;
|
---|
| 237 | case 16: /* ifOutOctets */
|
---|
| 238 | *value_u32 = netif->mib2_counters.ifoutoctets;
|
---|
| 239 | value_len = sizeof(*value_u32);
|
---|
| 240 | break;
|
---|
| 241 | case 17: /* ifOutUcastPkts */
|
---|
| 242 | *value_u32 = netif->mib2_counters.ifoutucastpkts;
|
---|
| 243 | value_len = sizeof(*value_u32);
|
---|
| 244 | break;
|
---|
| 245 | case 18: /* ifOutNUcastPkts */
|
---|
| 246 | *value_u32 = netif->mib2_counters.ifoutnucastpkts;
|
---|
| 247 | value_len = sizeof(*value_u32);
|
---|
| 248 | break;
|
---|
| 249 | case 19: /* ifOutDiscarts */
|
---|
| 250 | *value_u32 = netif->mib2_counters.ifoutdiscards;
|
---|
| 251 | value_len = sizeof(*value_u32);
|
---|
| 252 | break;
|
---|
| 253 | case 20: /* ifOutErrors */
|
---|
| 254 | *value_u32 = netif->mib2_counters.ifouterrors;
|
---|
| 255 | value_len = sizeof(*value_u32);
|
---|
| 256 | break;
|
---|
| 257 | case 21: /* ifOutQLen */
|
---|
| 258 | *value_u32 = iftable_ifOutQLen;
|
---|
| 259 | value_len = sizeof(*value_u32);
|
---|
| 260 | break;
|
---|
| 261 | /** @note returning zeroDotZero (0.0) no media specific MIB support */
|
---|
| 262 | case 22: /* ifSpecific */
|
---|
| 263 | value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
|
---|
| 264 | MEMCPY(value, snmp_zero_dot_zero.id, value_len);
|
---|
| 265 | break;
|
---|
| 266 | default:
|
---|
| 267 | return 0;
|
---|
| 268 | }
|
---|
| 269 |
|
---|
| 270 | return value_len;
|
---|
| 271 | }
|
---|
| 272 |
|
---|
| 273 | #if !SNMP_SAFE_REQUESTS
|
---|
| 274 |
|
---|
| 275 | static snmp_err_t
|
---|
| 276 | interfaces_Table_set_test(struct snmp_node_instance *instance, u16_t len, void *value)
|
---|
| 277 | {
|
---|
| 278 | s32_t *sint_ptr = (s32_t *)value;
|
---|
| 279 |
|
---|
| 280 | /* stack should never call this method for another column,
|
---|
| 281 | because all other columns are set to readonly */
|
---|
| 282 | LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
|
---|
| 283 | LWIP_UNUSED_ARG(len);
|
---|
| 284 |
|
---|
| 285 | if (*sint_ptr == 1 || *sint_ptr == 2) {
|
---|
| 286 | return SNMP_ERR_NOERROR;
|
---|
| 287 | }
|
---|
| 288 |
|
---|
| 289 | return SNMP_ERR_WRONGVALUE;
|
---|
| 290 | }
|
---|
| 291 |
|
---|
| 292 | static snmp_err_t
|
---|
| 293 | interfaces_Table_set_value(struct snmp_node_instance *instance, u16_t len, void *value)
|
---|
| 294 | {
|
---|
| 295 | struct netif *netif = (struct netif *)instance->reference.ptr;
|
---|
| 296 | s32_t *sint_ptr = (s32_t *)value;
|
---|
| 297 |
|
---|
| 298 | /* stack should never call this method for another column,
|
---|
| 299 | because all other columns are set to readonly */
|
---|
| 300 | LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
|
---|
| 301 | LWIP_UNUSED_ARG(len);
|
---|
| 302 |
|
---|
| 303 | if (*sint_ptr == 1) {
|
---|
| 304 | netif_set_up(netif);
|
---|
| 305 | } else if (*sint_ptr == 2) {
|
---|
| 306 | netif_set_down(netif);
|
---|
| 307 | }
|
---|
| 308 |
|
---|
| 309 | return SNMP_ERR_NOERROR;
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | #endif /* SNMP_SAFE_REQUESTS */
|
---|
| 313 |
|
---|
| 314 | static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value);
|
---|
| 315 |
|
---|
| 316 | static const struct snmp_table_col_def interfaces_Table_columns[] = {
|
---|
| 317 | { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */
|
---|
| 318 | { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */
|
---|
| 319 | { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */
|
---|
| 320 | { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */
|
---|
| 321 | { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */
|
---|
| 322 | { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */
|
---|
| 323 | #if !SNMP_SAFE_REQUESTS
|
---|
| 324 | { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */
|
---|
| 325 | #else
|
---|
| 326 | { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */
|
---|
| 327 | #endif
|
---|
| 328 | { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */
|
---|
| 329 | { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */
|
---|
| 330 | { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */
|
---|
| 331 | { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */
|
---|
| 332 | { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */
|
---|
| 333 | { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */
|
---|
| 334 | { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */
|
---|
| 335 | { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */
|
---|
| 336 | { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */
|
---|
| 337 | { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */
|
---|
| 338 | { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */
|
---|
| 339 | { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */
|
---|
| 340 | { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */
|
---|
| 341 | { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */
|
---|
| 342 | { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */
|
---|
| 343 | };
|
---|
| 344 |
|
---|
| 345 | #if !SNMP_SAFE_REQUESTS
|
---|
| 346 | static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
|
---|
| 347 | 2, interfaces_Table_columns,
|
---|
| 348 | interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
---|
| 349 | interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value);
|
---|
| 350 | #else
|
---|
| 351 | static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
|
---|
| 352 | 2, interfaces_Table_columns,
|
---|
| 353 | interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
---|
| 354 | interfaces_Table_get_value, NULL, NULL);
|
---|
| 355 | #endif
|
---|
| 356 |
|
---|
| 357 | /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
---|
| 358 | CREATE_LWIP_SYNC_NODE(1, interfaces_Number)
|
---|
| 359 | CREATE_LWIP_SYNC_NODE(2, interfaces_Table)
|
---|
| 360 |
|
---|
| 361 | static const struct snmp_node *const interface_nodes[] = {
|
---|
| 362 | &SYNC_NODE_NAME(interfaces_Number).node.node,
|
---|
| 363 | &SYNC_NODE_NAME(interfaces_Table).node.node
|
---|
| 364 | };
|
---|
| 365 |
|
---|
| 366 | const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes);
|
---|
| 367 |
|
---|
| 368 | #endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */
|
---|