xref: /nrf52832-nimble/rt-thread/components/net/lwip-2.1.0/src/apps/snmp/snmp_table.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /**
2*10465441SEvalZero  * @file
3*10465441SEvalZero  * SNMP table support implementation.
4*10465441SEvalZero  */
5*10465441SEvalZero 
6*10465441SEvalZero /*
7*10465441SEvalZero  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8*10465441SEvalZero  * All rights reserved.
9*10465441SEvalZero  *
10*10465441SEvalZero  * Redistribution and use in source and binary forms, with or without modification,
11*10465441SEvalZero  * are permitted provided that the following conditions are met:
12*10465441SEvalZero  *
13*10465441SEvalZero  * 1. Redistributions of source code must retain the above copyright notice,
14*10465441SEvalZero  *    this list of conditions and the following disclaimer.
15*10465441SEvalZero  * 2. Redistributions in binary form must reproduce the above copyright notice,
16*10465441SEvalZero  *    this list of conditions and the following disclaimer in the documentation
17*10465441SEvalZero  *    and/or other materials provided with the distribution.
18*10465441SEvalZero  * 3. The name of the author may not be used to endorse or promote products
19*10465441SEvalZero  *    derived from this software without specific prior written permission.
20*10465441SEvalZero  *
21*10465441SEvalZero  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22*10465441SEvalZero  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23*10465441SEvalZero  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24*10465441SEvalZero  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25*10465441SEvalZero  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26*10465441SEvalZero  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*10465441SEvalZero  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*10465441SEvalZero  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29*10465441SEvalZero  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30*10465441SEvalZero  * OF SUCH DAMAGE.
31*10465441SEvalZero  *
32*10465441SEvalZero  * This file is part of the lwIP TCP/IP stack.
33*10465441SEvalZero  *
34*10465441SEvalZero  * Author: Martin Hentschel <[email protected]>
35*10465441SEvalZero  *
36*10465441SEvalZero  */
37*10465441SEvalZero 
38*10465441SEvalZero #include "lwip/apps/snmp_opts.h"
39*10465441SEvalZero 
40*10465441SEvalZero #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
41*10465441SEvalZero 
42*10465441SEvalZero #include "lwip/apps/snmp_core.h"
43*10465441SEvalZero #include "lwip/apps/snmp_table.h"
44*10465441SEvalZero #include <string.h>
45*10465441SEvalZero 
snmp_table_get_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)46*10465441SEvalZero snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance)
47*10465441SEvalZero {
48*10465441SEvalZero   snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE;
49*10465441SEvalZero   const struct snmp_table_node *table_node = (const struct snmp_table_node *)(const void *)instance->node;
50*10465441SEvalZero 
51*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid);
52*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid_len);
53*10465441SEvalZero 
54*10465441SEvalZero   /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */
55*10465441SEvalZero   /* fixed row entry always has oid 1 */
56*10465441SEvalZero   if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) {
57*10465441SEvalZero     /* search column */
58*10465441SEvalZero     const struct snmp_table_col_def *col_def = table_node->columns;
59*10465441SEvalZero     u16_t i = table_node->column_count;
60*10465441SEvalZero     while (i > 0) {
61*10465441SEvalZero       if (col_def->index == instance->instance_oid.id[1]) {
62*10465441SEvalZero         break;
63*10465441SEvalZero       }
64*10465441SEvalZero 
65*10465441SEvalZero       col_def++;
66*10465441SEvalZero       i--;
67*10465441SEvalZero     }
68*10465441SEvalZero 
69*10465441SEvalZero     if (i > 0) {
70*10465441SEvalZero       /* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */
71*10465441SEvalZero       instance->asn1_type = col_def->asn1_type;
72*10465441SEvalZero       instance->access    = col_def->access;
73*10465441SEvalZero       instance->get_value = table_node->get_value;
74*10465441SEvalZero       instance->set_test  = table_node->set_test;
75*10465441SEvalZero       instance->set_value = table_node->set_value;
76*10465441SEvalZero 
77*10465441SEvalZero       ret = table_node->get_cell_instance(
78*10465441SEvalZero               &(instance->instance_oid.id[1]),
79*10465441SEvalZero               &(instance->instance_oid.id[2]),
80*10465441SEvalZero               instance->instance_oid.len - 2,
81*10465441SEvalZero               instance);
82*10465441SEvalZero     }
83*10465441SEvalZero   }
84*10465441SEvalZero 
85*10465441SEvalZero   return ret;
86*10465441SEvalZero }
87*10465441SEvalZero 
snmp_table_get_next_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)88*10465441SEvalZero snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance)
89*10465441SEvalZero {
90*10465441SEvalZero   const struct snmp_table_node *table_node = (const struct snmp_table_node *)(const void *)instance->node;
91*10465441SEvalZero   const struct snmp_table_col_def *col_def;
92*10465441SEvalZero   struct snmp_obj_id row_oid;
93*10465441SEvalZero   u32_t column = 0;
94*10465441SEvalZero   snmp_err_t result;
95*10465441SEvalZero 
96*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid);
97*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid_len);
98*10465441SEvalZero 
99*10465441SEvalZero   /* check that first part of id is 0 or 1, referencing fixed row entry */
100*10465441SEvalZero   if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) {
101*10465441SEvalZero     return SNMP_ERR_NOSUCHINSTANCE;
102*10465441SEvalZero   }
103*10465441SEvalZero   if (instance->instance_oid.len > 1) {
104*10465441SEvalZero     column = instance->instance_oid.id[1];
105*10465441SEvalZero   }
106*10465441SEvalZero   if (instance->instance_oid.len > 2) {
107*10465441SEvalZero     snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2);
108*10465441SEvalZero   } else {
109*10465441SEvalZero     row_oid.len = 0;
110*10465441SEvalZero   }
111*10465441SEvalZero 
112*10465441SEvalZero   instance->get_value    = table_node->get_value;
113*10465441SEvalZero   instance->set_test     = table_node->set_test;
114*10465441SEvalZero   instance->set_value    = table_node->set_value;
115*10465441SEvalZero 
116*10465441SEvalZero   /* resolve column and value */
117*10465441SEvalZero   do {
118*10465441SEvalZero     u16_t i;
119*10465441SEvalZero     const struct snmp_table_col_def *next_col_def = NULL;
120*10465441SEvalZero     col_def = table_node->columns;
121*10465441SEvalZero 
122*10465441SEvalZero     for (i = 0; i < table_node->column_count; i++) {
123*10465441SEvalZero       if (col_def->index == column) {
124*10465441SEvalZero         next_col_def = col_def;
125*10465441SEvalZero         break;
126*10465441SEvalZero       } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) {
127*10465441SEvalZero         next_col_def = col_def;
128*10465441SEvalZero       }
129*10465441SEvalZero       col_def++;
130*10465441SEvalZero     }
131*10465441SEvalZero 
132*10465441SEvalZero     if (next_col_def == NULL) {
133*10465441SEvalZero       /* no further column found */
134*10465441SEvalZero       return SNMP_ERR_NOSUCHINSTANCE;
135*10465441SEvalZero     }
136*10465441SEvalZero 
137*10465441SEvalZero     instance->asn1_type          = next_col_def->asn1_type;
138*10465441SEvalZero     instance->access             = next_col_def->access;
139*10465441SEvalZero 
140*10465441SEvalZero     result = table_node->get_next_cell_instance(
141*10465441SEvalZero                &next_col_def->index,
142*10465441SEvalZero                &row_oid,
143*10465441SEvalZero                instance);
144*10465441SEvalZero 
145*10465441SEvalZero     if (result == SNMP_ERR_NOERROR) {
146*10465441SEvalZero       col_def = next_col_def;
147*10465441SEvalZero       break;
148*10465441SEvalZero     }
149*10465441SEvalZero 
150*10465441SEvalZero     row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */
151*10465441SEvalZero     column = next_col_def->index + 1;
152*10465441SEvalZero   } while (1);
153*10465441SEvalZero 
154*10465441SEvalZero   /* build resulting oid */
155*10465441SEvalZero   instance->instance_oid.len   = 2;
156*10465441SEvalZero   instance->instance_oid.id[0] = 1;
157*10465441SEvalZero   instance->instance_oid.id[1] = col_def->index;
158*10465441SEvalZero   snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len);
159*10465441SEvalZero 
160*10465441SEvalZero   return SNMP_ERR_NOERROR;
161*10465441SEvalZero }
162*10465441SEvalZero 
163*10465441SEvalZero 
snmp_table_simple_get_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)164*10465441SEvalZero snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance)
165*10465441SEvalZero {
166*10465441SEvalZero   snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE;
167*10465441SEvalZero   const struct snmp_table_simple_node *table_node = (const struct snmp_table_simple_node *)(const void *)instance->node;
168*10465441SEvalZero 
169*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid);
170*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid_len);
171*10465441SEvalZero 
172*10465441SEvalZero   /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */
173*10465441SEvalZero   /* fixed row entry always has oid 1 */
174*10465441SEvalZero   if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) {
175*10465441SEvalZero     ret = table_node->get_cell_value(
176*10465441SEvalZero             &(instance->instance_oid.id[1]),
177*10465441SEvalZero             &(instance->instance_oid.id[2]),
178*10465441SEvalZero             instance->instance_oid.len - 2,
179*10465441SEvalZero             &instance->reference,
180*10465441SEvalZero             &instance->reference_len);
181*10465441SEvalZero 
182*10465441SEvalZero     if (ret == SNMP_ERR_NOERROR) {
183*10465441SEvalZero       /* search column */
184*10465441SEvalZero       const struct snmp_table_simple_col_def *col_def = table_node->columns;
185*10465441SEvalZero       u32_t i = table_node->column_count;
186*10465441SEvalZero       while (i > 0) {
187*10465441SEvalZero         if (col_def->index == instance->instance_oid.id[1]) {
188*10465441SEvalZero           break;
189*10465441SEvalZero         }
190*10465441SEvalZero 
191*10465441SEvalZero         col_def++;
192*10465441SEvalZero         i--;
193*10465441SEvalZero       }
194*10465441SEvalZero 
195*10465441SEvalZero       if (i > 0) {
196*10465441SEvalZero         instance->asn1_type = col_def->asn1_type;
197*10465441SEvalZero         instance->access    = SNMP_NODE_INSTANCE_READ_ONLY;
198*10465441SEvalZero         instance->set_test  = NULL;
199*10465441SEvalZero         instance->set_value = NULL;
200*10465441SEvalZero 
201*10465441SEvalZero         switch (col_def->data_type) {
202*10465441SEvalZero           case SNMP_VARIANT_VALUE_TYPE_U32:
203*10465441SEvalZero             instance->get_value = snmp_table_extract_value_from_u32ref;
204*10465441SEvalZero             break;
205*10465441SEvalZero           case SNMP_VARIANT_VALUE_TYPE_S32:
206*10465441SEvalZero             instance->get_value = snmp_table_extract_value_from_s32ref;
207*10465441SEvalZero             break;
208*10465441SEvalZero           case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */
209*10465441SEvalZero           case SNMP_VARIANT_VALUE_TYPE_CONST_PTR:
210*10465441SEvalZero             instance->get_value = snmp_table_extract_value_from_refconstptr;
211*10465441SEvalZero             break;
212*10465441SEvalZero           default:
213*10465441SEvalZero             LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type));
214*10465441SEvalZero             return SNMP_ERR_GENERROR;
215*10465441SEvalZero         }
216*10465441SEvalZero 
217*10465441SEvalZero         ret = SNMP_ERR_NOERROR;
218*10465441SEvalZero       } else {
219*10465441SEvalZero         ret = SNMP_ERR_NOSUCHINSTANCE;
220*10465441SEvalZero       }
221*10465441SEvalZero     }
222*10465441SEvalZero   }
223*10465441SEvalZero 
224*10465441SEvalZero   return ret;
225*10465441SEvalZero }
226*10465441SEvalZero 
snmp_table_simple_get_next_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)227*10465441SEvalZero snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance)
228*10465441SEvalZero {
229*10465441SEvalZero   const struct snmp_table_simple_node *table_node = (const struct snmp_table_simple_node *)(const void *)instance->node;
230*10465441SEvalZero   const struct snmp_table_simple_col_def *col_def;
231*10465441SEvalZero   struct snmp_obj_id row_oid;
232*10465441SEvalZero   u32_t column = 0;
233*10465441SEvalZero   snmp_err_t result;
234*10465441SEvalZero 
235*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid);
236*10465441SEvalZero   LWIP_UNUSED_ARG(root_oid_len);
237*10465441SEvalZero 
238*10465441SEvalZero   /* check that first part of id is 0 or 1, referencing fixed row entry */
239*10465441SEvalZero   if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) {
240*10465441SEvalZero     return SNMP_ERR_NOSUCHINSTANCE;
241*10465441SEvalZero   }
242*10465441SEvalZero   if (instance->instance_oid.len > 1) {
243*10465441SEvalZero     column = instance->instance_oid.id[1];
244*10465441SEvalZero   }
245*10465441SEvalZero   if (instance->instance_oid.len > 2) {
246*10465441SEvalZero     snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2);
247*10465441SEvalZero   } else {
248*10465441SEvalZero     row_oid.len = 0;
249*10465441SEvalZero   }
250*10465441SEvalZero 
251*10465441SEvalZero   /* resolve column and value */
252*10465441SEvalZero   do {
253*10465441SEvalZero     u32_t i;
254*10465441SEvalZero     const struct snmp_table_simple_col_def *next_col_def = NULL;
255*10465441SEvalZero     col_def = table_node->columns;
256*10465441SEvalZero 
257*10465441SEvalZero     for (i = 0; i < table_node->column_count; i++) {
258*10465441SEvalZero       if (col_def->index == column) {
259*10465441SEvalZero         next_col_def = col_def;
260*10465441SEvalZero         break;
261*10465441SEvalZero       } else if ((col_def->index > column) && ((next_col_def == NULL) ||
262*10465441SEvalZero                  (col_def->index < next_col_def->index))) {
263*10465441SEvalZero         next_col_def = col_def;
264*10465441SEvalZero       }
265*10465441SEvalZero       col_def++;
266*10465441SEvalZero     }
267*10465441SEvalZero 
268*10465441SEvalZero     if (next_col_def == NULL) {
269*10465441SEvalZero       /* no further column found */
270*10465441SEvalZero       return SNMP_ERR_NOSUCHINSTANCE;
271*10465441SEvalZero     }
272*10465441SEvalZero 
273*10465441SEvalZero     result = table_node->get_next_cell_instance_and_value(
274*10465441SEvalZero                &next_col_def->index,
275*10465441SEvalZero                &row_oid,
276*10465441SEvalZero                &instance->reference,
277*10465441SEvalZero                &instance->reference_len);
278*10465441SEvalZero 
279*10465441SEvalZero     if (result == SNMP_ERR_NOERROR) {
280*10465441SEvalZero       col_def = next_col_def;
281*10465441SEvalZero       break;
282*10465441SEvalZero     }
283*10465441SEvalZero 
284*10465441SEvalZero     row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */
285*10465441SEvalZero     column = next_col_def->index + 1;
286*10465441SEvalZero   } while (1);
287*10465441SEvalZero 
288*10465441SEvalZero   instance->asn1_type = col_def->asn1_type;
289*10465441SEvalZero   instance->access    = SNMP_NODE_INSTANCE_READ_ONLY;
290*10465441SEvalZero   instance->set_test  = NULL;
291*10465441SEvalZero   instance->set_value = NULL;
292*10465441SEvalZero 
293*10465441SEvalZero   switch (col_def->data_type) {
294*10465441SEvalZero     case SNMP_VARIANT_VALUE_TYPE_U32:
295*10465441SEvalZero       instance->get_value = snmp_table_extract_value_from_u32ref;
296*10465441SEvalZero       break;
297*10465441SEvalZero     case SNMP_VARIANT_VALUE_TYPE_S32:
298*10465441SEvalZero       instance->get_value = snmp_table_extract_value_from_s32ref;
299*10465441SEvalZero       break;
300*10465441SEvalZero     case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */
301*10465441SEvalZero     case SNMP_VARIANT_VALUE_TYPE_CONST_PTR:
302*10465441SEvalZero       instance->get_value = snmp_table_extract_value_from_refconstptr;
303*10465441SEvalZero       break;
304*10465441SEvalZero     default:
305*10465441SEvalZero       LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type));
306*10465441SEvalZero       return SNMP_ERR_GENERROR;
307*10465441SEvalZero   }
308*10465441SEvalZero 
309*10465441SEvalZero   /* build resulting oid */
310*10465441SEvalZero   instance->instance_oid.len   = 2;
311*10465441SEvalZero   instance->instance_oid.id[0] = 1;
312*10465441SEvalZero   instance->instance_oid.id[1] = col_def->index;
313*10465441SEvalZero   snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len);
314*10465441SEvalZero 
315*10465441SEvalZero   return SNMP_ERR_NOERROR;
316*10465441SEvalZero }
317*10465441SEvalZero 
318*10465441SEvalZero 
319*10465441SEvalZero s16_t
snmp_table_extract_value_from_s32ref(struct snmp_node_instance * instance,void * value)320*10465441SEvalZero snmp_table_extract_value_from_s32ref(struct snmp_node_instance *instance, void *value)
321*10465441SEvalZero {
322*10465441SEvalZero   s32_t *dst = (s32_t *)value;
323*10465441SEvalZero   *dst = instance->reference.s32;
324*10465441SEvalZero   return sizeof(*dst);
325*10465441SEvalZero }
326*10465441SEvalZero 
327*10465441SEvalZero s16_t
snmp_table_extract_value_from_u32ref(struct snmp_node_instance * instance,void * value)328*10465441SEvalZero snmp_table_extract_value_from_u32ref(struct snmp_node_instance *instance, void *value)
329*10465441SEvalZero {
330*10465441SEvalZero   u32_t *dst = (u32_t *)value;
331*10465441SEvalZero   *dst = instance->reference.u32;
332*10465441SEvalZero   return sizeof(*dst);
333*10465441SEvalZero }
334*10465441SEvalZero 
335*10465441SEvalZero s16_t
snmp_table_extract_value_from_refconstptr(struct snmp_node_instance * instance,void * value)336*10465441SEvalZero snmp_table_extract_value_from_refconstptr(struct snmp_node_instance *instance, void *value)
337*10465441SEvalZero {
338*10465441SEvalZero   MEMCPY(value, instance->reference.const_ptr, instance->reference_len);
339*10465441SEvalZero   return (u16_t)instance->reference_len;
340*10465441SEvalZero }
341*10465441SEvalZero 
342*10465441SEvalZero #endif /* LWIP_SNMP */
343