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