STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
snmp_mib2.c
Go to the documentation of this file.
1 
9 /*
10  * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  * this list of conditions and the following disclaimer in the documentation
20  * and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  * derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * Author: Dirk Ziegelmeier <dziegel@gmx.de>
36  */
37 
38 #include "lwip/apps/snmp_opts.h"
39 
40 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
41 #if SNMP_LWIP_MIB2
42 
43 #if !LWIP_STATS
44 #error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2)
45 #endif
46 #if !MIB2_STATS
47 #error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2)
48 #endif
49 
50 #include "lwip/snmp.h"
51 #include "lwip/apps/snmp.h"
52 #include "lwip/apps/snmp_core.h"
53 #include "lwip/apps/snmp_mib2.h"
54 #include "lwip/apps/snmp_scalar.h"
55 #include "lwip/apps/snmp_table.h"
57 #include "lwip/netif.h"
58 #include "lwip/ip.h"
59 #include "lwip/ip_frag.h"
60 #include "lwip/mem.h"
61 #include "lwip/priv/tcp_priv.h"
62 #include "lwip/udp.h"
63 #include "lwip/sys.h"
64 #include "netif/etharp.h"
65 #include "lwip/stats.h"
66 
67 #include <string.h>
68 
69 static u8_t
70 netif_to_num(const struct netif *netif)
71 {
72  u8_t result = 0;
73  struct netif *netif_iterator = netif_list;
74 
75  while (netif_iterator != NULL) {
76  result++;
77 
78  if(netif_iterator == netif) {
79  return result;
80  }
81 
82  netif_iterator = netif_iterator->next;
83  }
84 
85  LWIP_ASSERT("netif not found in netif_list", 0);
86  return 0;
87 }
88 
89 #define MIB2_AUTH_TRAPS_ENABLED 1
90 #define MIB2_AUTH_TRAPS_DISABLED 2
91 
92 #if SNMP_USE_NETCONN
93 #include "lwip/tcpip.h"
94 void
95 snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg)
96 {
97  tcpip_callback_with_block(fn, arg, 1);
98 }
99 
100 struct snmp_threadsync_instance snmp_mib2_lwip_locks;
101 
102 #define SYNC_NODE_NAME(node_name) node_name ## _synced
103 #define CREATE_LWIP_SYNC_NODE(oid, node_name) \
104  static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks);
105 #else
106 #define SYNC_NODE_NAME(node_name) node_name
107 #define CREATE_LWIP_SYNC_NODE(oid, node_name)
108 #endif
109 
110 /* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */
111 static u16_t snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value);
112 static snmp_err_t snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value);
113 static snmp_err_t snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value);
114 
115 /* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */
116 static const struct snmp_scalar_array_node_def snmp_nodes[] = {
117  { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */
118  { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */
119  { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */
120  { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */
121  { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */
122  { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */
123  { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */
124  { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */
125  {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */
126  {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */
127  {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */
128  {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */
129  {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */
130  {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */
131  {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */
132  {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */
133  {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */
134  {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */
135  {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */
136  {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */
137  {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */
138  {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */
139  {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */
140  {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */
141  {27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */
142  {28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */
143  {29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */
144  {30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */
145  {31, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */
146  {32, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */
147 };
148 static const struct snmp_scalar_array_node snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value);
149 
150 /* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */
151 /* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */
152 /* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */
153 
154 /* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */
155 #if LWIP_UDP
156 static u16_t udp_get_value(struct snmp_node_instance* instance, void* value);
157 
158 static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
159 static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
160 static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
161 static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value);
162 static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
163 static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value);
164 
165 #if LWIP_IPV4
166 static snmp_err_t 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);
167 static snmp_err_t 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);
168 
169 static const struct snmp_table_simple_col_def udp_Table_columns[] = {
170  { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */
171  { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */
172 };
173 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);
174 #endif /* LWIP_IPV4 */
175 
176 static snmp_err_t 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);
177 static snmp_err_t 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);
178 
179 static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = {
180  /* all items except udpEndpointProcess are declared as not-accessible */
181  { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */
182 };
183 
184 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);
185 
186 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
187 CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams)
188 CREATE_LWIP_SYNC_NODE(2, udp_noPorts)
189 CREATE_LWIP_SYNC_NODE(3, udp_inErrors)
190 CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams)
191 #if LWIP_IPV4
192 CREATE_LWIP_SYNC_NODE(5, udp_Table)
193 #endif /* LWIP_IPV4 */
194 CREATE_LWIP_SYNC_NODE(7, udp_endpointTable)
195 CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams)
196 CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams)
197 
198 static const struct snmp_node* udp_nodes[] = {
199  &SYNC_NODE_NAME(udp_inDatagrams).node.node,
200  &SYNC_NODE_NAME(udp_noPorts).node.node,
201  &SYNC_NODE_NAME(udp_inErrors).node.node,
202  &SYNC_NODE_NAME(udp_outDatagrams).node.node,
203 #if LWIP_IPV4
204  &SYNC_NODE_NAME(udp_Table).node.node,
205 #endif /* LWIP_IPV4 */
206  &SYNC_NODE_NAME(udp_endpointTable).node.node,
207  &SYNC_NODE_NAME(udp_HCInDatagrams).node.node,
208  &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node
209 };
210 
211 static const struct snmp_tree_node udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes);
212 #endif /* LWIP_UDP */
213 
214 
215 /* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */
216 /* implement this group only, if the TCP protocol is available */
217 #if LWIP_TCP
218 static u16_t tcp_get_value(struct snmp_node_instance* instance, void* value);
219 
220 static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
221 static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
222 static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
223 static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value);
224 static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
225 static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
226 static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
227 static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
228 static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value);
229 static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
230 static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
231 static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
232 static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
233 static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value);
234 static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value);
235 static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value);
236 
237 #if LWIP_IPV4
238 static snmp_err_t tcp_ConnTable_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);
239 static snmp_err_t tcp_ConnTable_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);
240 
241 static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = {
242  { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */
243  { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */
244  { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */
245  { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */
246  { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */
247 };
248 
249 static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value);
250 #endif /* LWIP_IPV4 */
251 
252 static snmp_err_t tcp_ConnectionTable_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);
253 static snmp_err_t tcp_ConnectionTable_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);
254 
255 static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = {
256  /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
257  { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */
258  { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */
259 };
260 
261 static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value);
262 
263 
264 static snmp_err_t tcp_ListenerTable_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);
265 static snmp_err_t tcp_ListenerTable_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);
266 
267 static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = {
268  /* all items except tcpListenerProcess are declared as not-accessible */
269  { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */
270 };
271 
272 static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value);
273 
274 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
275 CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm)
276 CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin)
277 CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax)
278 CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn)
279 CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens)
280 CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens)
281 CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails)
282 CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets)
283 CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab)
284 CREATE_LWIP_SYNC_NODE(10, tcp_InSegs)
285 CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs)
286 CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs)
287 #if LWIP_IPV4
288 CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable)
289 #endif /* LWIP_IPV4 */
290 CREATE_LWIP_SYNC_NODE(14, tcp_InErrs)
291 CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts)
292 CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs)
293 CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs)
294 CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable)
295 CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable)
296 
297 static const struct snmp_node* tcp_nodes[] = {
298  &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node,
299  &SYNC_NODE_NAME(tcp_RtoMin).node.node,
300  &SYNC_NODE_NAME(tcp_RtoMax).node.node,
301  &SYNC_NODE_NAME(tcp_MaxConn).node.node,
302  &SYNC_NODE_NAME(tcp_ActiveOpens).node.node,
303  &SYNC_NODE_NAME(tcp_PassiveOpens).node.node,
304  &SYNC_NODE_NAME(tcp_AttemptFails).node.node,
305  &SYNC_NODE_NAME(tcp_EstabResets).node.node,
306  &SYNC_NODE_NAME(tcp_CurrEstab).node.node,
307  &SYNC_NODE_NAME(tcp_InSegs).node.node,
308  &SYNC_NODE_NAME(tcp_OutSegs).node.node,
309  &SYNC_NODE_NAME(tcp_RetransSegs).node.node,
310 #if LWIP_IPV4
311  &SYNC_NODE_NAME(tcp_ConnTable).node.node,
312 #endif /* LWIP_IPV4 */
313  &SYNC_NODE_NAME(tcp_InErrs).node.node,
314  &SYNC_NODE_NAME(tcp_OutRsts).node.node,
315  &SYNC_NODE_NAME(tcp_HCInSegs).node.node,
316  &SYNC_NODE_NAME(tcp_HCOutSegs).node.node,
317  &SYNC_NODE_NAME(tcp_ConnectionTable).node.node,
318  &SYNC_NODE_NAME(tcp_ListenerTable).node.node
319 };
320 
321 static const struct snmp_tree_node tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes);
322 #endif /* LWIP_TCP */
323 
324 /* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */
325 #if LWIP_ICMP
326 static u16_t icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value);
327 
328 static const struct snmp_scalar_array_node_def icmp_nodes[] = {
329  { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
330  { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
331  { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
332  { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
333  { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
334  { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
335  { 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
336  { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
337  { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
338  {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
339  {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
340  {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
341  {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
342  {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
343  {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
344  {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
345  {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
346  {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
347  {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
348  {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
349  {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
350  {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
351  {23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
352  {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
353  {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY},
354  {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}
355 };
356 static const struct snmp_scalar_array_node icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL);
357 #endif /* LWIP_ICMP */
358 
359 #if LWIP_IPV4
360 /* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */
361 static u16_t ip_get_value(struct snmp_node_instance* instance, void* value);
362 static snmp_err_t ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value);
363 static snmp_err_t ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value);
364 
365 static snmp_err_t ip_AddrTable_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);
366 static snmp_err_t ip_AddrTable_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);
367 static snmp_err_t ip_RouteTable_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);
368 static snmp_err_t ip_RouteTable_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);
369 static snmp_err_t ip_NetToMediaTable_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);
370 static snmp_err_t ip_NetToMediaTable_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);
371 
372 static const struct snmp_scalar_node ip_Forwarding = SNMP_SCALAR_CREATE_NODE(1, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value);
373 static const struct snmp_scalar_node ip_DefaultTTL = SNMP_SCALAR_CREATE_NODE(2, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value);
374 static const struct snmp_scalar_node ip_InReceives = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
375 static const struct snmp_scalar_node ip_InHdrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
376 static const struct snmp_scalar_node ip_InAddrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
377 static const struct snmp_scalar_node ip_ForwDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
378 static const struct snmp_scalar_node ip_InUnknownProtos = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
379 static const struct snmp_scalar_node ip_InDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
380 static const struct snmp_scalar_node ip_InDelivers = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
381 static const struct snmp_scalar_node ip_OutRequests = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
382 static const struct snmp_scalar_node ip_OutDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
383 static const struct snmp_scalar_node ip_OutNoRoutes = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
384 static const struct snmp_scalar_node ip_ReasmTimeout = SNMP_SCALAR_CREATE_NODE_READONLY(13, SNMP_ASN1_TYPE_INTEGER, ip_get_value);
385 static const struct snmp_scalar_node ip_ReasmReqds = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
386 static const struct snmp_scalar_node ip_ReasmOKs = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
387 static const struct snmp_scalar_node ip_ReasmFails = SNMP_SCALAR_CREATE_NODE_READONLY(16, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
388 static const struct snmp_scalar_node ip_FragOKs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
389 static const struct snmp_scalar_node ip_FragFails = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
390 static const struct snmp_scalar_node ip_FragCreates = SNMP_SCALAR_CREATE_NODE_READONLY(19, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
391 static const struct snmp_scalar_node ip_RoutingDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(23, SNMP_ASN1_TYPE_COUNTER, ip_get_value);
392 
393 static const struct snmp_table_simple_col_def ip_AddrTable_columns[] = {
394  { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntAddr */
395  { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntIfIndex */
396  { 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntNetMask */
397  { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntBcastAddr */
398  { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipAdEntReasmMaxSize */
399 };
400 
401 static const struct snmp_table_simple_node ip_AddrTable = SNMP_TABLE_CREATE_SIMPLE(20, ip_AddrTable_columns, ip_AddrTable_get_cell_value, ip_AddrTable_get_next_cell_instance_and_value);
402 
403 static const struct snmp_table_simple_col_def ip_RouteTable_columns[] = {
404  { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteDest */
405  { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteIfIndex */
406  { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric1 */
407  { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric2 */
408  { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric3 */
409  { 6, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric4 */
410  { 7, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteNextHop */
411  { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteType */
412  { 9, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteProto */
413  { 10, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteAge */
414  { 11, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteMask */
415  { 12, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric5 */
416  { 13, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_VARIANT_VALUE_TYPE_PTR } /* ipRouteInfo */
417 };
418 
419 static const struct snmp_table_simple_node ip_RouteTable = SNMP_TABLE_CREATE_SIMPLE(21, ip_RouteTable_columns, ip_RouteTable_get_cell_value, ip_RouteTable_get_next_cell_instance_and_value);
420 #endif /* LWIP_IPV4 */
421 
422 #if LWIP_ARP && LWIP_IPV4
423 static const struct snmp_table_simple_col_def ip_NetToMediaTable_columns[] = {
424  { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaIfIndex */
425  { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* ipNetToMediaPhysAddress */
426  { 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaNetAddress */
427  { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipNetToMediaType */
428 };
429 
430 static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREATE_SIMPLE(22, ip_NetToMediaTable_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value);
431 #endif /* LWIP_ARP && LWIP_IPV4 */
432 
433 #if LWIP_IPV4
434 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
435 CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding)
436 CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL)
437 CREATE_LWIP_SYNC_NODE( 3, ip_InReceives)
438 CREATE_LWIP_SYNC_NODE( 4, ip_InHdrErrors)
439 CREATE_LWIP_SYNC_NODE( 5, ip_InAddrErrors)
440 CREATE_LWIP_SYNC_NODE( 6, ip_ForwDatagrams)
441 CREATE_LWIP_SYNC_NODE( 7, ip_InUnknownProtos)
442 CREATE_LWIP_SYNC_NODE( 8, ip_InDiscards)
443 CREATE_LWIP_SYNC_NODE( 9, ip_InDelivers)
444 CREATE_LWIP_SYNC_NODE(10, ip_OutRequests)
445 CREATE_LWIP_SYNC_NODE(11, ip_OutDiscards)
446 CREATE_LWIP_SYNC_NODE(12, ip_OutNoRoutes)
447 CREATE_LWIP_SYNC_NODE(13, ip_ReasmTimeout)
448 CREATE_LWIP_SYNC_NODE(14, ip_ReasmReqds)
449 CREATE_LWIP_SYNC_NODE(15, ip_ReasmOKs)
450 CREATE_LWIP_SYNC_NODE(15, ip_ReasmFails)
451 CREATE_LWIP_SYNC_NODE(17, ip_FragOKs)
452 CREATE_LWIP_SYNC_NODE(18, ip_FragFails)
453 CREATE_LWIP_SYNC_NODE(19, ip_FragCreates)
454 CREATE_LWIP_SYNC_NODE(20, ip_AddrTable)
455 CREATE_LWIP_SYNC_NODE(21, ip_RouteTable)
456 #if LWIP_ARP
457 CREATE_LWIP_SYNC_NODE(22, ip_NetToMediaTable)
458 #endif /* LWIP_ARP */
459 CREATE_LWIP_SYNC_NODE(23, ip_RoutingDiscards)
460 
461 static const struct snmp_node* ip_nodes[] = {
462  &SYNC_NODE_NAME(ip_Forwarding).node.node,
463  &SYNC_NODE_NAME(ip_DefaultTTL).node.node,
464  &SYNC_NODE_NAME(ip_InReceives).node.node,
465  &SYNC_NODE_NAME(ip_InHdrErrors).node.node,
466  &SYNC_NODE_NAME(ip_InAddrErrors).node.node,
467  &SYNC_NODE_NAME(ip_ForwDatagrams).node.node,
468  &SYNC_NODE_NAME(ip_InUnknownProtos).node.node,
469  &SYNC_NODE_NAME(ip_InDiscards).node.node,
470  &SYNC_NODE_NAME(ip_InDelivers).node.node,
471  &SYNC_NODE_NAME(ip_OutRequests).node.node,
472  &SYNC_NODE_NAME(ip_OutDiscards).node.node,
473  &SYNC_NODE_NAME(ip_OutNoRoutes).node.node,
474  &SYNC_NODE_NAME(ip_ReasmTimeout).node.node,
475  &SYNC_NODE_NAME(ip_ReasmReqds).node.node,
476  &SYNC_NODE_NAME(ip_ReasmOKs).node.node,
477  &SYNC_NODE_NAME(ip_ReasmFails).node.node,
478  &SYNC_NODE_NAME(ip_FragOKs).node.node,
479  &SYNC_NODE_NAME(ip_FragFails).node.node,
480  &SYNC_NODE_NAME(ip_FragCreates).node.node,
481  &SYNC_NODE_NAME(ip_AddrTable).node.node,
482  &SYNC_NODE_NAME(ip_RouteTable).node.node,
483 #if LWIP_ARP
484  &SYNC_NODE_NAME(ip_NetToMediaTable).node.node,
485 #endif /* LWIP_ARP */
486  &SYNC_NODE_NAME(ip_RoutingDiscards).node.node
487 };
488 
489 static const struct snmp_tree_node ip_root = SNMP_CREATE_TREE_NODE(4, ip_nodes);
490 #endif /* LWIP_IPV4 */
491 
492 /* --- at .1.3.6.1.2.1.3 ----------------------------------------------------- */
493 
494 #if LWIP_ARP && LWIP_IPV4
495 /* at node table is a subset of ip_nettomedia table (same rows but less columns) */
496 static const struct snmp_table_simple_col_def at_Table_columns[] = {
497  { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* atIfIndex */
498  { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* atPhysAddress */
499  { 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 } /* atNetAddress */
500 };
501 
502 static const struct snmp_table_simple_node at_Table = SNMP_TABLE_CREATE_SIMPLE(1, at_Table_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value);
503 
504 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
505 CREATE_LWIP_SYNC_NODE(1, at_Table)
506 
507 static const struct snmp_node* at_nodes[] = {
508  &SYNC_NODE_NAME(at_Table).node.node
509 };
510 
511 static const struct snmp_tree_node at_root = SNMP_CREATE_TREE_NODE(3, at_nodes);
512 #endif /* LWIP_ARP && LWIP_IPV4 */
513 
514 /* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
515 static u16_t interfaces_get_value(struct snmp_node_instance* instance, void* value);
516 static snmp_err_t 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);
517 static snmp_err_t interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance);
518 static u16_t interfaces_Table_get_value(struct snmp_node_instance* instance, void* value);
519 #if !SNMP_SAFE_REQUESTS
520 static snmp_err_t interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value);
521 static snmp_err_t interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value);
522 #endif
523 
524 static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value);
525 
526 static const struct snmp_table_col_def interfaces_Table_columns[] = {
527  { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */
528  { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */
529  { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */
530  { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */
531  { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */
532  { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */
533 #if !SNMP_SAFE_REQUESTS
534  { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */
535 #else
536  { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */
537 #endif
538  { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */
539  { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */
540  { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */
541  { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */
542  { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */
543  { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */
544  { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */
545  { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */
546  { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */
547  { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */
548  { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */
549  { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */
550  { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */
551  { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */
552  { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */
553 };
554 
555 #if !SNMP_SAFE_REQUESTS
556 static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
557  2, interfaces_Table_columns,
558  interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
559  interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value);
560 #else
561 static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE(
562  2, interfaces_Table_columns,
563  interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
564  interfaces_Table_get_value, NULL, NULL);
565 #endif
566 
567 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
568 CREATE_LWIP_SYNC_NODE(1, interfaces_Number)
569 CREATE_LWIP_SYNC_NODE(2, interfaces_Table)
570 
571 static const struct snmp_node* interface_nodes[] = {
572  &SYNC_NODE_NAME(interfaces_Number).node.node,
573  &SYNC_NODE_NAME(interfaces_Table).node.node
574 };
575 
576 static const struct snmp_tree_node interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes);
577 
578 /* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */
579 static u16_t system_get_value(const struct snmp_scalar_array_node_def *node, void *value);
580 static snmp_err_t system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value);
581 static snmp_err_t system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value);
582 
583 static const struct snmp_scalar_array_node_def system_nodes[] = {
584  {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */
585  {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */
586  {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */
587  {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */
588  {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */
589  {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */
590  {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */
591 };
592 
593 static const struct snmp_scalar_array_node system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value);
594 
595 /* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */
596 static const struct snmp_node* mib2_nodes[] = {
597  &system_node.node.node,
598  &interface_root.node,
599 #if LWIP_ARP && LWIP_IPV4
600  &at_root.node,
601 #endif /* LWIP_ARP && LWIP_IPV4 */
602 #if LWIP_IPV4
603  &ip_root.node,
604 #endif /* LWIP_IPV4 */
605 #if LWIP_ICMP
606  &icmp_root.node.node,
607 #endif /* LWIP_ICMP */
608 #if LWIP_TCP && LWIP_IPV4
609  &tcp_root.node,
610 #endif /* LWIP_TCP && LWIP_IPV4 */
611 #if LWIP_UDP && LWIP_IPV4
612  &udp_root.node,
613 #endif /* LWIP_UDP && LWIP_IPV4 */
614  &snmp_root.node.node
615 };
616 
617 static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes);
618 
619 static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 };
620 const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node);
621 
623 static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC;
624 static const u8_t* sysdescr = sysdescr_default;
625 static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */
626 
628 static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT;
629 static const u8_t* syscontact = syscontact_default;
630 static const u16_t* syscontact_len = NULL; /* use strlen for determining len */
631 static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */
632 static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */
633 static u16_t syscontact_bufsize = 0; /* 0=not writable */
634 
636 static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME;
637 static const u8_t* sysname = sysname_default;
638 static const u16_t* sysname_len = NULL; /* use strlen for determining len */
639 static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */
640 static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */
641 static u16_t sysname_bufsize = 0; /* 0=not writable */
642 
644 static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION;
645 static const u8_t* syslocation = syslocation_default;
646 static const u16_t* syslocation_len = NULL; /* use strlen for determining len */
647 static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */
648 static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */
649 static u16_t syslocation_bufsize = 0; /* 0=not writable */
650 
657 void snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len)
658 {
659  if (str != NULL) {
660  sysdescr = str;
661  sysdescr_len = len;
662  }
663 }
664 
678 void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
679 {
680  if (ocstr != NULL) {
681  syscontact = ocstr;
682  syscontact_wr = ocstr;
683  syscontact_len = ocstrlen;
684  syscontact_wr_len = ocstrlen;
685  syscontact_bufsize = bufsize;
686  }
687 }
688 
689 void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
690 {
691  if (ocstr != NULL) {
692  syscontact = ocstr;
693  syscontact_len = ocstrlen;
694  syscontact_wr = NULL;
695  syscontact_wr_len = NULL;
696  syscontact_bufsize = 0;
697  }
698 }
699 
700 
714 void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
715 {
716  if (ocstr != NULL) {
717  sysname = ocstr;
718  sysname_wr = ocstr;
719  sysname_len = ocstrlen;
720  sysname_wr_len = ocstrlen;
721  sysname_bufsize = bufsize;
722  }
723 }
724 
725 void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
726 {
727  if (ocstr != NULL) {
728  sysname = ocstr;
729  sysname_len = ocstrlen;
730  sysname_wr = NULL;
731  sysname_wr_len = NULL;
732  sysname_bufsize = 0;
733  }
734 }
735 
749 void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize)
750 {
751  if (ocstr != NULL) {
752  syslocation = ocstr;
753  syslocation_wr = ocstr;
754  syslocation_len = ocstrlen;
755  syslocation_wr_len = ocstrlen;
756  syslocation_bufsize = bufsize;
757  }
758 }
759 
760 void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen)
761 {
762  if (ocstr != NULL) {
763  syslocation = ocstr;
764  syslocation_len = ocstrlen;
765  syslocation_wr = NULL;
766  syslocation_wr_len = NULL;
767  syslocation_bufsize = 0;
768  }
769 }
770 
771 
772 /* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */
773 
774 static u16_t
775 system_get_value(const struct snmp_scalar_array_node_def *node, void *value)
776 {
777  const u8_t* var = NULL;
778  const u16_t* var_len;
779  u16_t result;
780 
781  switch (node->oid) {
782  case 1: /* sysDescr */
783  var = sysdescr;
784  var_len = sysdescr_len;
785  break;
786  case 2: /* sysObjectID */
787  {
788  const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid();
789  MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t));
790  return dev_enterprise_oid->len * sizeof(u32_t);
791  }
792  case 3: /* sysUpTime */
793  MIB2_COPY_SYSUPTIME_TO((u32_t*)value);
794  return sizeof(u32_t);
795  case 4: /* sysContact */
796  var = syscontact;
797  var_len = syscontact_len;
798  break;
799  case 5: /* sysName */
800  var = sysname;
801  var_len = sysname_len;
802  break;
803  case 6: /* sysLocation */
804  var = syslocation;
805  var_len = syslocation_len;
806  break;
807  case 7: /* sysServices */
808  *(s32_t*)value = SNMP_SYSSERVICES;
809  return sizeof(s32_t);
810  default:
811  LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid));
812  return 0;
813  }
814 
815  /* handle string values (OID 1,4,5 and 6) */
816  LWIP_ASSERT("", (value != NULL));
817  if (var_len == NULL) {
818  result = (u16_t)strlen((const char*)var);
819  } else {
820  result = *var_len;
821  }
822  MEMCPY(value, var, result);
823  return result;
824 }
825 
826 static snmp_err_t
827 system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
828 {
829  snmp_err_t ret = SNMP_ERR_WRONGVALUE;
830  const u16_t* var_bufsize = NULL;
831  const u16_t* var_wr_len;
832 
833  LWIP_UNUSED_ARG(value);
834 
835  switch (node->oid) {
836  case 4: /* sysContact */
837  var_bufsize = &syscontact_bufsize;
838  var_wr_len = syscontact_wr_len;
839  break;
840  case 5: /* sysName */
841  var_bufsize = &sysname_bufsize;
842  var_wr_len = sysname_wr_len;
843  break;
844  case 6: /* sysLocation */
845  var_bufsize = &syslocation_bufsize;
846  var_wr_len = syslocation_wr_len;
847  break;
848  default:
849  LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid));
850  return ret;
851  }
852 
853  /* check if value is writable at all */
854  if (*var_bufsize > 0) {
855  if (var_wr_len == NULL) {
856  /* we have to take the terminating 0 into account */
857  if (len < *var_bufsize) {
858  ret = SNMP_ERR_NOERROR;
859  }
860  } else {
861  if (len <= *var_bufsize) {
862  ret = SNMP_ERR_NOERROR;
863  }
864  }
865  } else {
866  ret = SNMP_ERR_NOTWRITABLE;
867  }
868 
869  return ret;
870 }
871 
872 static snmp_err_t
873 system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
874 {
875  u8_t* var_wr = NULL;
876  u16_t* var_wr_len;
877 
878  switch (node->oid) {
879  case 4: /* sysContact */
880  var_wr = syscontact_wr;
881  var_wr_len = syscontact_wr_len;
882  break;
883  case 5: /* sysName */
884  var_wr = sysname_wr;
885  var_wr_len = sysname_wr_len;
886  break;
887  case 6: /* sysLocation */
888  var_wr = syslocation_wr;
889  var_wr_len = syslocation_wr_len;
890  break;
891  default:
892  LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid));
893  return SNMP_ERR_GENERROR;
894  }
895 
896  /* no need to check size of target buffer, this was already done in set_test method */
897  LWIP_ASSERT("", var_wr != NULL);
898  MEMCPY(var_wr, value, len);
899 
900  if (var_wr_len == NULL) {
901  /* add terminating 0 */
902  var_wr[len] = 0;
903  } else {
904  *var_wr_len = len;
905  }
906 
907  return SNMP_ERR_NOERROR;
908 }
909 
910 /* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */
911 
912 static u16_t
913 interfaces_get_value(struct snmp_node_instance* instance, void* value)
914 {
915  if (instance->node->oid == 1) {
916  s32_t *sint_ptr = (s32_t*)value;
917  s32_t num_netifs = 0;
918 
919  struct netif *netif = netif_list;
920  while (netif != NULL) {
921  num_netifs++;
922  netif = netif->next;
923  }
924 
925  *sint_ptr = num_netifs;
926  return sizeof(*sint_ptr);
927  }
928 
929  return 0;
930 }
931 
932 /* list of allowed value ranges for incoming OID */
933 static const struct snmp_oid_range interfaces_Table_oid_ranges[] = {
934  { 1, 0xff } /* netif->num is u8_t */
935 };
936 
937 static const u8_t iftable_ifOutQLen = 0;
938 
939 static const u8_t iftable_ifOperStatus_up = 1;
940 static const u8_t iftable_ifOperStatus_down = 2;
941 
942 static const u8_t iftable_ifAdminStatus_up = 1;
943 static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7;
944 static const u8_t iftable_ifAdminStatus_down = 2;
945 
946 static snmp_err_t 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)
947 {
948  u32_t ifIndex;
949  struct netif *netif;
950 
951  LWIP_UNUSED_ARG(column);
952 
953  /* check if incoming OID length and if values are in plausible range */
954  if(!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) {
955  return SNMP_ERR_NOSUCHINSTANCE;
956  }
957 
958  /* get netif index from incoming OID */
959  ifIndex = row_oid[0];
960 
961  /* find netif with index */
962  netif = netif_list;
963  while (netif != NULL) {
964  if(netif_to_num(netif) == ifIndex) {
965  /* store netif pointer for subsequent operations (get/test/set) */
966  cell_instance->reference.ptr = netif;
967  return SNMP_ERR_NOERROR;
968  }
969  netif = netif->next;
970  }
971 
972  /* not found */
973  return SNMP_ERR_NOSUCHINSTANCE;
974 }
975 
976 static snmp_err_t interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance)
977 {
978  struct netif *netif;
979  struct snmp_next_oid_state state;
980  u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
981 
982  LWIP_UNUSED_ARG(column);
983 
984  /* init struct to search next oid */
985  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges));
986 
987  /* iterate over all possible OIDs to find the next one */
988  netif = netif_list;
989  while (netif != NULL) {
990  u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)];
991  test_oid[0] = netif_to_num(netif);
992 
993  /* check generated OID: is it a candidate for the next one? */
994  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif);
995 
996  netif = netif->next;
997  }
998 
999  /* did we find a next one? */
1000  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
1001  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
1002  /* store netif pointer for subsequent operations (get/test/set) */
1003  cell_instance->reference.ptr = /* (struct netif*) */state.reference;
1004  return SNMP_ERR_NOERROR;
1005  }
1006 
1007  /* not found */
1008  return SNMP_ERR_NOSUCHINSTANCE;
1009 }
1010 
1011 static u16_t interfaces_Table_get_value(struct snmp_node_instance* instance, void* value)
1012 {
1013  struct netif *netif = (struct netif*)instance->reference.ptr;
1014  u32_t* value_u32 = (u32_t*)value;
1015  s32_t* value_s32 = (s32_t*)value;
1016  u16_t value_len;
1017 
1018  switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id))
1019  {
1020  case 1: /* ifIndex */
1021  *value_s32 = netif_to_num(netif);
1022  value_len = sizeof(*value_s32);
1023  break;
1024  case 2: /* ifDescr */
1025  value_len = sizeof(netif->name);
1026  MEMCPY(value, netif->name, value_len);
1027  break;
1028  case 3: /* ifType */
1029  *value_s32 = netif->link_type;
1030  value_len = sizeof(*value_s32);
1031  break;
1032  case 4: /* ifMtu */
1033  *value_s32 = netif->mtu;
1034  value_len = sizeof(*value_s32);
1035  break;
1036  case 5: /* ifSpeed */
1037  *value_u32 = netif->link_speed;
1038  value_len = sizeof(*value_u32);
1039  break;
1040  case 6: /* ifPhysAddress */
1041  value_len = sizeof(netif->hwaddr);
1042  MEMCPY(value, &netif->hwaddr, value_len);
1043  break;
1044  case 7: /* ifAdminStatus */
1045  if (netif_is_up(netif)) {
1046  *value_s32 = iftable_ifOperStatus_up;
1047  } else {
1048  *value_s32 = iftable_ifOperStatus_down;
1049  }
1050  value_len = sizeof(*value_s32);
1051  break;
1052  case 8: /* ifOperStatus */
1053  if (netif_is_up(netif)) {
1054  if (netif_is_link_up(netif)) {
1055  *value_s32 = iftable_ifAdminStatus_up;
1056  } else {
1057  *value_s32 = iftable_ifAdminStatus_lowerLayerDown;
1058  }
1059  } else {
1060  *value_s32 = iftable_ifAdminStatus_down;
1061  }
1062  value_len = sizeof(*value_s32);
1063  break;
1064  case 9: /* ifLastChange */
1065  *value_u32 = netif->ts;
1066  value_len = sizeof(*value_u32);
1067  break;
1068  case 10: /* ifInOctets */
1069  *value_u32 = netif->mib2_counters.ifinoctets;
1070  value_len = sizeof(*value_u32);
1071  break;
1072  case 11: /* ifInUcastPkts */
1073  *value_u32 = netif->mib2_counters.ifinucastpkts;
1074  value_len = sizeof(*value_u32);
1075  break;
1076  case 12: /* ifInNUcastPkts */
1077  *value_u32 = netif->mib2_counters.ifinnucastpkts;
1078  value_len = sizeof(*value_u32);
1079  break;
1080  case 13: /* ifInDiscards */
1081  *value_u32 = netif->mib2_counters.ifindiscards;
1082  value_len = sizeof(*value_u32);
1083  break;
1084  case 14: /* ifInErrors */
1085  *value_u32 = netif->mib2_counters.ifinerrors;
1086  value_len = sizeof(*value_u32);
1087  break;
1088  case 15: /* ifInUnkownProtos */
1089  *value_u32 = netif->mib2_counters.ifinunknownprotos;
1090  value_len = sizeof(*value_u32);
1091  break;
1092  case 16: /* ifOutOctets */
1093  *value_u32 = netif->mib2_counters.ifoutoctets;
1094  value_len = sizeof(*value_u32);
1095  break;
1096  case 17: /* ifOutUcastPkts */
1097  *value_u32 = netif->mib2_counters.ifoutucastpkts;
1098  value_len = sizeof(*value_u32);
1099  break;
1100  case 18: /* ifOutNUcastPkts */
1101  *value_u32 = netif->mib2_counters.ifoutnucastpkts;
1102  value_len = sizeof(*value_u32);
1103  break;
1104  case 19: /* ifOutDiscarts */
1105  *value_u32 = netif->mib2_counters.ifoutdiscards;
1106  value_len = sizeof(*value_u32);
1107  break;
1108  case 20: /* ifOutErrors */
1109  *value_u32 = netif->mib2_counters.ifouterrors;
1110  value_len = sizeof(*value_u32);
1111  break;
1112  case 21: /* ifOutQLen */
1113  *value_u32 = iftable_ifOutQLen;
1114  value_len = sizeof(*value_u32);
1115  break;
1117  case 22: /* ifSpecific */
1118  value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
1119  MEMCPY(value, snmp_zero_dot_zero.id, value_len);
1120  break;
1121  default:
1122  return 0;
1123  }
1124 
1125  return value_len;
1126 }
1127 
1128 #if !SNMP_SAFE_REQUESTS
1129 
1130 static snmp_err_t interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
1131 {
1132  s32_t *sint_ptr = (s32_t*)value;
1133 
1134  /* stack should never call this method for another column,
1135  because all other columns are set to readonly */
1136  LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
1137  LWIP_UNUSED_ARG(len);
1138 
1139  if (*sint_ptr == 1 || *sint_ptr == 2)
1140  {
1141  return SNMP_ERR_NOERROR;
1142  }
1143 
1144  return SNMP_ERR_WRONGVALUE;
1145 }
1146 
1147 static snmp_err_t interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
1148 {
1149  struct netif *netif = (struct netif*)instance->reference.ptr;
1150  s32_t *sint_ptr = (s32_t*)value;
1151 
1152  /* stack should never call this method for another column,
1153  because all other columns are set to readonly */
1154  LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7));
1155  LWIP_UNUSED_ARG(len);
1156 
1157  if (*sint_ptr == 1) {
1158  netif_set_up(netif);
1159  } else if (*sint_ptr == 2) {
1160  netif_set_down(netif);
1161  }
1162 
1163  return SNMP_ERR_NOERROR;
1164 }
1165 
1166 #endif /* SNMP_SAFE_REQUESTS */
1167 
1168 #if LWIP_IPV4
1169 /* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */
1170 
1171 static u16_t
1172 ip_get_value(struct snmp_node_instance* instance, void* value)
1173 {
1174  s32_t* sint_ptr = (s32_t*)value;
1175  u32_t* uint_ptr = (u32_t*)value;
1176 
1177  switch (instance->node->oid) {
1178  case 1: /* ipForwarding */
1179 #if IP_FORWARD
1180  /* forwarding */
1181  *sint_ptr = 1;
1182 #else
1183  /* not-forwarding */
1184  *sint_ptr = 2;
1185 #endif
1186  return sizeof(*sint_ptr);
1187  case 2: /* ipDefaultTTL */
1188  *sint_ptr = IP_DEFAULT_TTL;
1189  return sizeof(*sint_ptr);
1190  case 3: /* ipInReceives */
1191  *uint_ptr = STATS_GET(mib2.ipinreceives);
1192  return sizeof(*uint_ptr);
1193  case 4: /* ipInHdrErrors */
1194  *uint_ptr = STATS_GET(mib2.ipinhdrerrors);
1195  return sizeof(*uint_ptr);
1196  case 5: /* ipInAddrErrors */
1197  *uint_ptr = STATS_GET(mib2.ipinaddrerrors);
1198  return sizeof(*uint_ptr);
1199  case 6: /* ipForwDatagrams */
1200  *uint_ptr = STATS_GET(mib2.ipforwdatagrams);
1201  return sizeof(*uint_ptr);
1202  case 7: /* ipInUnknownProtos */
1203  *uint_ptr = STATS_GET(mib2.ipinunknownprotos);
1204  return sizeof(*uint_ptr);
1205  case 8: /* ipInDiscards */
1206  *uint_ptr = STATS_GET(mib2.ipindiscards);
1207  return sizeof(*uint_ptr);
1208  case 9: /* ipInDelivers */
1209  *uint_ptr = STATS_GET(mib2.ipindelivers);
1210  return sizeof(*uint_ptr);
1211  case 10: /* ipOutRequests */
1212  *uint_ptr = STATS_GET(mib2.ipoutrequests);
1213  return sizeof(*uint_ptr);
1214  case 11: /* ipOutDiscards */
1215  *uint_ptr = STATS_GET(mib2.ipoutdiscards);
1216  return sizeof(*uint_ptr);
1217  case 12: /* ipOutNoRoutes */
1218  *uint_ptr = STATS_GET(mib2.ipoutnoroutes);
1219  return sizeof(*uint_ptr);
1220  case 13: /* ipReasmTimeout */
1221 #if IP_REASSEMBLY
1222  *sint_ptr = IP_REASS_MAXAGE;
1223 #else
1224  *sint_ptr = 0;
1225 #endif
1226  return sizeof(*sint_ptr);
1227  case 14: /* ipReasmReqds */
1228  *uint_ptr = STATS_GET(mib2.ipreasmreqds);
1229  return sizeof(*uint_ptr);
1230  case 15: /* ipReasmOKs */
1231  *uint_ptr = STATS_GET(mib2.ipreasmoks);
1232  return sizeof(*uint_ptr);
1233  case 16: /* ipReasmFails */
1234  *uint_ptr = STATS_GET(mib2.ipreasmfails);
1235  return sizeof(*uint_ptr);
1236  case 17: /* ipFragOKs */
1237  *uint_ptr = STATS_GET(mib2.ipfragoks);
1238  return sizeof(*uint_ptr);
1239  case 18: /* ipFragFails */
1240  *uint_ptr = STATS_GET(mib2.ipfragfails);
1241  return sizeof(*uint_ptr);
1242  case 19: /* ipFragCreates */
1243  *uint_ptr = STATS_GET(mib2.ipfragcreates);
1244  return sizeof(*uint_ptr);
1245  case 23: /* ipRoutingDiscards: not supported -> always 0 */
1246  *uint_ptr = 0;
1247  return sizeof(*uint_ptr);
1248  default:
1249  LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
1250  break;
1251  }
1252 
1253  return 0;
1254 }
1255 
1266 static snmp_err_t
1267 ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
1268 {
1269  snmp_err_t ret = SNMP_ERR_WRONGVALUE;
1270  s32_t *sint_ptr = (s32_t*)value;
1271 
1272  LWIP_UNUSED_ARG(len);
1273  switch (instance->node->oid) {
1274  case 1: /* ipForwarding */
1275 #if IP_FORWARD
1276  /* forwarding */
1277  if (*sint_ptr == 1)
1278 #else
1279  /* not-forwarding */
1280  if (*sint_ptr == 2)
1281 #endif
1282  {
1283  ret = SNMP_ERR_NOERROR;
1284  }
1285  break;
1286  case 2: /* ipDefaultTTL */
1287  if (*sint_ptr == IP_DEFAULT_TTL) {
1288  ret = SNMP_ERR_NOERROR;
1289  }
1290  break;
1291  default:
1292  LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid));
1293  break;
1294  }
1295 
1296  return ret;
1297 }
1298 
1299 static snmp_err_t
1300 ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
1301 {
1302  LWIP_UNUSED_ARG(instance);
1303  LWIP_UNUSED_ARG(len);
1304  LWIP_UNUSED_ARG(value);
1305  /* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */
1306  return SNMP_ERR_NOERROR;
1307 }
1308 
1309 /* --- ipAddrTable --- */
1310 
1311 /* list of allowed value ranges for incoming OID */
1312 static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = {
1313  { 0, 0xff }, /* IP A */
1314  { 0, 0xff }, /* IP B */
1315  { 0, 0xff }, /* IP C */
1316  { 0, 0xff } /* IP D */
1317 };
1318 
1319 static snmp_err_t
1320 ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
1321 {
1322  LWIP_UNUSED_ARG(value_len);
1323 
1324  switch (*column) {
1325  case 1: /* ipAdEntAddr */
1326  value->u32 = netif_ip4_addr(netif)->addr;
1327  break;
1328  case 2: /* ipAdEntIfIndex */
1329  value->u32 = netif_to_num(netif);
1330  break;
1331  case 3: /* ipAdEntNetMask */
1332  value->u32 = netif_ip4_netmask(netif)->addr;
1333  break;
1334  case 4: /* ipAdEntBcastAddr */
1335  /* lwIP oddity, there's no broadcast
1336  address in the netif we can rely on */
1337  value->u32 = IPADDR_BROADCAST & 1;
1338  break;
1339  case 5: /* ipAdEntReasmMaxSize */
1340 #if IP_REASSEMBLY
1341  /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs,
1342  * but only if receiving one fragmented packet at a time.
1343  * The current solution is to calculate for 2 simultaneous packets...
1344  */
1345  value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) *
1347 #else
1348 
1350  value->u32 = 0;
1351 #endif
1352  break;
1353  default:
1354  return SNMP_ERR_NOSUCHINSTANCE;
1355  }
1356 
1357  return SNMP_ERR_NOERROR;
1358 }
1359 
1360 static snmp_err_t
1361 ip_AddrTable_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)
1362 {
1363  ip4_addr_t ip;
1364  struct netif *netif;
1365 
1366  /* check if incoming OID length and if values are in plausible range */
1367  if(!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) {
1368  return SNMP_ERR_NOSUCHINSTANCE;
1369  }
1370 
1371  /* get IP from incoming OID */
1372  snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
1373 
1374  /* find netif with requested ip */
1375  netif = netif_list;
1376  while (netif != NULL) {
1377  if(ip4_addr_cmp(&ip, netif_ip4_addr(netif))) {
1378  /* fill in object properties */
1379  return ip_AddrTable_get_cell_value_core(netif, column, value, value_len);
1380  }
1381 
1382  netif = netif->next;
1383  }
1384 
1385  /* not found */
1386  return SNMP_ERR_NOSUCHINSTANCE;
1387 }
1388 
1389 static snmp_err_t
1390 ip_AddrTable_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)
1391 {
1392  struct netif *netif;
1393  struct snmp_next_oid_state state;
1394  u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)];
1395 
1396  /* init struct to search next oid */
1397  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges));
1398 
1399  /* iterate over all possible OIDs to find the next one */
1400  netif = netif_list;
1401  while (netif != NULL) {
1402  u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)];
1403  snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]);
1404 
1405  /* check generated OID: is it a candidate for the next one? */
1406  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif);
1407 
1408  netif = netif->next;
1409  }
1410 
1411  /* did we find a next one? */
1412  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
1413  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
1414  /* fill in object properties */
1415  return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len);
1416  }
1417 
1418  /* not found */
1419  return SNMP_ERR_NOSUCHINSTANCE;
1420 }
1421 
1422 /* --- ipRouteTable --- */
1423 
1424 /* list of allowed value ranges for incoming OID */
1425 static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = {
1426  { 0, 0xff }, /* IP A */
1427  { 0, 0xff }, /* IP B */
1428  { 0, 0xff }, /* IP C */
1429  { 0, 0xff }, /* IP D */
1430 };
1431 
1432 static snmp_err_t
1433 ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
1434 {
1435  switch (*column) {
1436  case 1: /* ipRouteDest */
1437  if (default_route) {
1438  /* default rte has 0.0.0.0 dest */
1439  value->u32 = IP4_ADDR_ANY->addr;
1440  } else {
1441  /* netifs have netaddress dest */
1442  ip4_addr_t tmp;
1443  ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif));
1444  value->u32 = tmp.addr;
1445  }
1446  break;
1447  case 2: /* ipRouteIfIndex */
1448  value->u32 = netif_to_num(netif);
1449  break;
1450  case 3: /* ipRouteMetric1 */
1451  if (default_route) {
1452  value->s32 = 1; /* default */
1453  } else {
1454  value->s32 = 0; /* normal */
1455  }
1456  break;
1457  case 4: /* ipRouteMetric2 */
1458  case 5: /* ipRouteMetric3 */
1459  case 6: /* ipRouteMetric4 */
1460  value->s32 = -1; /* none */
1461  break;
1462  case 7: /* ipRouteNextHop */
1463  if (default_route) {
1464  /* default rte: gateway */
1465  value->u32 = netif_ip4_gw(netif)->addr;
1466  } else {
1467  /* other rtes: netif ip_addr */
1468  value->u32 = netif_ip4_addr(netif)->addr;
1469  }
1470  break;
1471  case 8: /* ipRouteType */
1472  if (default_route) {
1473  /* default rte is indirect */
1474  value->u32 = 4; /* indirect */
1475  } else {
1476  /* other rtes are direct */
1477  value->u32 = 3; /* direct */
1478  }
1479  break;
1480  case 9: /* ipRouteProto */
1481  /* locally defined routes */
1482  value->u32 = 2; /* local */
1483  break;
1484  case 10: /* ipRouteAge */
1485  /* @todo (sysuptime - timestamp last change) / 100 */
1486  value->u32 = 0;
1487  break;
1488  case 11: /* ipRouteMask */
1489  if (default_route) {
1490  /* default rte use 0.0.0.0 mask */
1491  value->u32 = IP4_ADDR_ANY->addr;
1492  } else {
1493  /* other rtes use netmask */
1494  value->u32 = netif_ip4_netmask(netif)->addr;
1495  }
1496  break;
1497  case 12: /* ipRouteMetric5 */
1498  value->s32 = -1; /* none */
1499  break;
1500  case 13: /* ipRouteInfo */
1501  value->const_ptr = snmp_zero_dot_zero.id;
1502  *value_len = snmp_zero_dot_zero.len * sizeof(u32_t);
1503  break;
1504  default:
1505  return SNMP_ERR_NOSUCHINSTANCE;
1506  }
1507 
1508  return SNMP_ERR_NOERROR;
1509 }
1510 
1511 static snmp_err_t
1512 ip_RouteTable_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)
1513 {
1514  ip4_addr_t test_ip;
1515  struct netif *netif;
1516 
1517  /* check if incoming OID length and if values are in plausible range */
1518  if(!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) {
1519  return SNMP_ERR_NOSUCHINSTANCE;
1520  }
1521 
1522  /* get IP and port from incoming OID */
1523  snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */
1524 
1525  /* default route is on default netif */
1526  if(ip4_addr_isany_val(test_ip) && (netif_default != NULL)) {
1527  /* fill in object properties */
1528  return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len);
1529  }
1530 
1531  /* find netif with requested route */
1532  netif = netif_list;
1533  while (netif != NULL) {
1534  ip4_addr_t dst;
1535  ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif));
1536 
1537  if(ip4_addr_cmp(&dst, &test_ip)) {
1538  /* fill in object properties */
1539  return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len);
1540  }
1541 
1542  netif = netif->next;
1543  }
1544 
1545  /* not found */
1546  return SNMP_ERR_NOSUCHINSTANCE;
1547 }
1548 
1549 static snmp_err_t
1550 ip_RouteTable_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)
1551 {
1552  struct netif *netif;
1553  struct snmp_next_oid_state state;
1554  u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)];
1555  u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)];
1556 
1557  /* init struct to search next oid */
1558  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges));
1559 
1560  /* check default route */
1561  if(netif_default != NULL) {
1562  snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[0]);
1563  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default);
1564  }
1565 
1566  /* iterate over all possible OIDs to find the next one */
1567  netif = netif_list;
1568  while (netif != NULL) {
1569  ip4_addr_t dst;
1570  ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif));
1571 
1572  /* check generated OID: is it a candidate for the next one? */
1573  if (!ip4_addr_isany_val(dst)) {
1574  snmp_ip4_to_oid(&dst, &test_oid[0]);
1575  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif);
1576  }
1577 
1578  netif = netif->next;
1579  }
1580 
1581  /* did we find a next one? */
1582  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
1583  ip4_addr_t dst;
1584  snmp_oid_to_ip4(&result_temp[0], &dst);
1585  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
1586  /* fill in object properties */
1587  return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len);
1588  } else {
1589  /* not found */
1590  return SNMP_ERR_NOSUCHINSTANCE;
1591  }
1592 }
1593 
1594 /* --- ipNetToMediaTable --- */
1595 
1596 /* list of allowed value ranges for incoming OID */
1597 static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = {
1598  { 1, 0xff }, /* IfIndex */
1599  { 0, 0xff }, /* IP A */
1600  { 0, 0xff }, /* IP B */
1601  { 0, 0xff }, /* IP C */
1602  { 0, 0xff } /* IP D */
1603 };
1604 
1605 static snmp_err_t
1606 ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
1607 {
1608  ip4_addr_t *ip;
1609  struct netif *netif;
1610  struct eth_addr *ethaddr;
1611 
1612  etharp_get_entry(arp_table_index, &ip, &netif, &ethaddr);
1613 
1614  /* value */
1615  switch (*column) {
1616  case 1: /* atIfIndex / ipNetToMediaIfIndex */
1617  value->u32 = netif_to_num(netif);
1618  break;
1619  case 2: /* atPhysAddress / ipNetToMediaPhysAddress */
1620  value->ptr = ethaddr;
1621  *value_len = sizeof(*ethaddr);
1622  break;
1623  case 3: /* atNetAddress / ipNetToMediaNetAddress */
1624  value->u32 = ip->addr;
1625  break;
1626  case 4: /* ipNetToMediaType */
1627  value->u32 = 3; /* dynamic*/
1628  break;
1629  default:
1630  return SNMP_ERR_NOSUCHINSTANCE;
1631  }
1632 
1633  return SNMP_ERR_NOERROR;
1634 }
1635 
1636 static snmp_err_t
1637 ip_NetToMediaTable_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)
1638 {
1639  ip4_addr_t ip_in;
1640  u8_t netif_index;
1641  u8_t i;
1642 
1643  /* check if incoming OID length and if values are in plausible range */
1644  if(!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) {
1645  return SNMP_ERR_NOSUCHINSTANCE;
1646  }
1647 
1648  /* get IP from incoming OID */
1649  netif_index = (u8_t)row_oid[0];
1650  snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */
1651 
1652  /* find requested entry */
1653  for(i=0; i<ARP_TABLE_SIZE; i++) {
1654  ip4_addr_t *ip;
1655  struct netif *netif;
1656  struct eth_addr *ethaddr;
1657 
1658  if(etharp_get_entry(i, &ip, &netif, &ethaddr)) {
1659  if((netif_index == netif_to_num(netif)) && ip4_addr_cmp(&ip_in, ip)) {
1660  /* fill in object properties */
1661  return ip_NetToMediaTable_get_cell_value_core(i, column, value, value_len);
1662  }
1663  }
1664  }
1665 
1666  /* not found */
1667  return SNMP_ERR_NOSUCHINSTANCE;
1668 }
1669 
1670 static snmp_err_t
1671 ip_NetToMediaTable_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)
1672 {
1673  u8_t i;
1674  struct snmp_next_oid_state state;
1675  u32_t result_temp[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)];
1676 
1677  /* init struct to search next oid */
1678  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges));
1679 
1680  /* iterate over all possible OIDs to find the next one */
1681  for(i=0; i<ARP_TABLE_SIZE; i++) {
1682  ip4_addr_t *ip;
1683  struct netif *netif;
1684  struct eth_addr *ethaddr;
1685 
1686  if(etharp_get_entry(i, &ip, &netif, &ethaddr)) {
1687  u32_t test_oid[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)];
1688 
1689  test_oid[0] = netif_to_num(netif);
1690  snmp_ip4_to_oid(ip, &test_oid[1]);
1691 
1692  /* check generated OID: is it a candidate for the next one? */
1693  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i);
1694  }
1695  }
1696 
1697  /* did we find a next one? */
1698  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
1699  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
1700  /* fill in object properties */
1701  return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len);
1702  }
1703 
1704  /* not found */
1705  return SNMP_ERR_NOSUCHINSTANCE;
1706 }
1707 #endif /* LWIP_IPV4 */
1708 
1709 /* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */
1710 
1711 #if LWIP_ICMP
1712 
1713 static u16_t
1714 icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value)
1715 {
1716  u32_t *uint_ptr = (u32_t*)value;
1717 
1718  switch (node->oid) {
1719  case 1: /* icmpInMsgs */
1720  *uint_ptr = STATS_GET(mib2.icmpinmsgs);
1721  return sizeof(*uint_ptr);
1722  case 2: /* icmpInErrors */
1723  *uint_ptr = STATS_GET(mib2.icmpinerrors);
1724  return sizeof(*uint_ptr);
1725  case 3: /* icmpInDestUnreachs */
1726  *uint_ptr = STATS_GET(mib2.icmpindestunreachs);
1727  return sizeof(*uint_ptr);
1728  case 4: /* icmpInTimeExcds */
1729  *uint_ptr = STATS_GET(mib2.icmpintimeexcds);
1730  return sizeof(*uint_ptr);
1731  case 5: /* icmpInParmProbs */
1732  *uint_ptr = STATS_GET(mib2.icmpinparmprobs);
1733  return sizeof(*uint_ptr);
1734  case 6: /* icmpInSrcQuenchs */
1735  *uint_ptr = STATS_GET(mib2.icmpinsrcquenchs);
1736  return sizeof(*uint_ptr);
1737  case 7: /* icmpInRedirects */
1738  *uint_ptr = STATS_GET(mib2.icmpinredirects);
1739  return sizeof(*uint_ptr);
1740  case 8: /* icmpInEchos */
1741  *uint_ptr = STATS_GET(mib2.icmpinechos);
1742  return sizeof(*uint_ptr);
1743  case 9: /* icmpInEchoReps */
1744  *uint_ptr = STATS_GET(mib2.icmpinechoreps);
1745  return sizeof(*uint_ptr);
1746  case 10: /* icmpInTimestamps */
1747  *uint_ptr = STATS_GET(mib2.icmpintimestamps);
1748  return sizeof(*uint_ptr);
1749  case 11: /* icmpInTimestampReps */
1750  *uint_ptr = STATS_GET(mib2.icmpintimestampreps);
1751  return sizeof(*uint_ptr);
1752  case 12: /* icmpInAddrMasks */
1753  *uint_ptr = STATS_GET(mib2.icmpinaddrmasks);
1754  return sizeof(*uint_ptr);
1755  case 13: /* icmpInAddrMaskReps */
1756  *uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps);
1757  return sizeof(*uint_ptr);
1758  case 14: /* icmpOutMsgs */
1759  *uint_ptr = STATS_GET(mib2.icmpoutmsgs);
1760  return sizeof(*uint_ptr);
1761  case 15: /* icmpOutErrors */
1762  *uint_ptr = STATS_GET(mib2.icmpouterrors);
1763  return sizeof(*uint_ptr);
1764  case 16: /* icmpOutDestUnreachs */
1765  *uint_ptr = STATS_GET(mib2.icmpoutdestunreachs);
1766  return sizeof(*uint_ptr);
1767  case 17: /* icmpOutTimeExcds */
1768  *uint_ptr = STATS_GET(mib2.icmpouttimeexcds);
1769  return sizeof(*uint_ptr);
1770  case 18: /* icmpOutParmProbs: not supported -> always 0 */
1771  *uint_ptr = 0;
1772  return sizeof(*uint_ptr);
1773  case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */
1774  *uint_ptr = 0;
1775  return sizeof(*uint_ptr);
1776  case 20: /* icmpOutRedirects: not supported -> always 0 */
1777  *uint_ptr = 0;
1778  return sizeof(*uint_ptr);
1779  case 21: /* icmpOutEchos */
1780  *uint_ptr = STATS_GET(mib2.icmpoutechos);
1781  return sizeof(*uint_ptr);
1782  case 22: /* icmpOutEchoReps */
1783  *uint_ptr = STATS_GET(mib2.icmpoutechoreps);
1784  return sizeof(*uint_ptr);
1785  case 23: /* icmpOutTimestamps: not supported -> always 0 */
1786  *uint_ptr = 0;
1787  return sizeof(*uint_ptr);
1788  case 24: /* icmpOutTimestampReps: not supported -> always 0 */
1789  *uint_ptr = 0;
1790  return sizeof(*uint_ptr);
1791  case 25: /* icmpOutAddrMasks: not supported -> always 0 */
1792  *uint_ptr = 0;
1793  return sizeof(*uint_ptr);
1794  case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */
1795  *uint_ptr = 0;
1796  return sizeof(*uint_ptr);
1797  default:
1798  LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid));
1799  break;
1800  }
1801 
1802  return 0;
1803 }
1804 
1805 #endif /* LWIP_ICMP */
1806 
1807 /* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */
1808 
1809 #if LWIP_TCP
1810 
1811 static u16_t
1812 tcp_get_value(struct snmp_node_instance* instance, void* value)
1813 {
1814  u32_t *uint_ptr = (u32_t*)value;
1815  s32_t *sint_ptr = (s32_t*)value;
1816 
1817  switch (instance->node->oid) {
1818  case 1: /* tcpRtoAlgorithm, vanj(4) */
1819  *sint_ptr = 4;
1820  return sizeof(*sint_ptr);
1821  case 2: /* tcpRtoMin */
1822  /* @todo not the actual value, a guess,
1823  needs to be calculated */
1824  *sint_ptr = 1000;
1825  return sizeof(*sint_ptr);
1826  case 3: /* tcpRtoMax */
1827  /* @todo not the actual value, a guess,
1828  needs to be calculated */
1829  *sint_ptr = 60000;
1830  return sizeof(*sint_ptr);
1831  case 4: /* tcpMaxConn */
1832  *sint_ptr = MEMP_NUM_TCP_PCB;
1833  return sizeof(*sint_ptr);
1834  case 5: /* tcpActiveOpens */
1835  *uint_ptr = STATS_GET(mib2.tcpactiveopens);
1836  return sizeof(*uint_ptr);
1837  case 6: /* tcpPassiveOpens */
1838  *uint_ptr = STATS_GET(mib2.tcppassiveopens);
1839  return sizeof(*uint_ptr);
1840  case 7: /* tcpAttemptFails */
1841  *uint_ptr = STATS_GET(mib2.tcpattemptfails);
1842  return sizeof(*uint_ptr);
1843  case 8: /* tcpEstabResets */
1844  *uint_ptr = STATS_GET(mib2.tcpestabresets);
1845  return sizeof(*uint_ptr);
1846  case 9: /* tcpCurrEstab */
1847  {
1848  u16_t tcpcurrestab = 0;
1849  struct tcp_pcb *pcb = tcp_active_pcbs;
1850  while (pcb != NULL) {
1851  if ((pcb->state == ESTABLISHED) ||
1852  (pcb->state == CLOSE_WAIT)) {
1853  tcpcurrestab++;
1854  }
1855  pcb = pcb->next;
1856  }
1857  *uint_ptr = tcpcurrestab;
1858  }
1859  return sizeof(*uint_ptr);
1860  case 10: /* tcpInSegs */
1861  *uint_ptr = STATS_GET(mib2.tcpinsegs);
1862  return sizeof(*uint_ptr);
1863  case 11: /* tcpOutSegs */
1864  *uint_ptr = STATS_GET(mib2.tcpoutsegs);
1865  return sizeof(*uint_ptr);
1866  case 12: /* tcpRetransSegs */
1867  *uint_ptr = STATS_GET(mib2.tcpretranssegs);
1868  return sizeof(*uint_ptr);
1869  case 14: /* tcpInErrs */
1870  *uint_ptr = STATS_GET(mib2.tcpinerrs);
1871  return sizeof(*uint_ptr);
1872  case 15: /* tcpOutRsts */
1873  *uint_ptr = STATS_GET(mib2.tcpoutrsts);
1874  return sizeof(*uint_ptr);
1875  case 17: /* tcpHCInSegs */
1876  memset(value, 0, 2*sizeof(u32_t)); /* not supported */
1877  return 2*sizeof(u32_t);
1878  case 18: /* tcpHCOutSegs */
1879  memset(value, 0, 2*sizeof(u32_t)); /* not supported */
1880  return 2*sizeof(u32_t);
1881  default:
1882  LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
1883  break;
1884  }
1885 
1886  return 0;
1887 }
1888 
1889 /* --- tcpConnTable --- */
1890 
1891 #if LWIP_IPV4
1892 
1893 /* list of allowed value ranges for incoming OID */
1894 static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = {
1895  { 0, 0xff }, /* IP A */
1896  { 0, 0xff }, /* IP B */
1897  { 0, 0xff }, /* IP C */
1898  { 0, 0xff }, /* IP D */
1899  { 0, 0xffff }, /* Port */
1900  { 0, 0xff }, /* IP A */
1901  { 0, 0xff }, /* IP B */
1902  { 0, 0xff }, /* IP C */
1903  { 0, 0xff }, /* IP D */
1904  { 0, 0xffff } /* Port */
1905 };
1906 
1907 static snmp_err_t
1908 tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
1909 {
1910  LWIP_UNUSED_ARG(value_len);
1911 
1912  /* value */
1913  switch (*column) {
1914  case 1: /* tcpConnState */
1915  value->u32 = pcb->state + 1;
1916  break;
1917  case 2: /* tcpConnLocalAddress */
1918  value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
1919  break;
1920  case 3: /* tcpConnLocalPort */
1921  value->u32 = pcb->local_port;
1922  break;
1923  case 4: /* tcpConnRemAddress */
1924  if(pcb->state == LISTEN) {
1925  value->u32 = IP4_ADDR_ANY->addr;
1926  } else {
1927  value->u32 = ip_2_ip4(&pcb->remote_ip)->addr;
1928  }
1929  break;
1930  case 5: /* tcpConnRemPort */
1931  if(pcb->state == LISTEN) {
1932  value->u32 = 0;
1933  } else {
1934  value->u32 = pcb->remote_port;
1935  }
1936  break;
1937  default:
1938  LWIP_ASSERT("invalid id", 0);
1939  return SNMP_ERR_NOSUCHINSTANCE;
1940  }
1941 
1942  return SNMP_ERR_NOERROR;
1943 }
1944 
1945 static snmp_err_t
1946 tcp_ConnTable_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)
1947 {
1948  u8_t i;
1949  ip4_addr_t local_ip;
1950  ip4_addr_t remote_ip;
1951  u16_t local_port;
1952  u16_t remote_port;
1953  struct tcp_pcb *pcb;
1954 
1955  /* check if incoming OID length and if values are in plausible range */
1956  if(!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) {
1957  return SNMP_ERR_NOSUCHINSTANCE;
1958  }
1959 
1960  /* get IPs and ports from incoming OID */
1961  snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */
1962  local_port = (u16_t)row_oid[4];
1963  snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */
1964  remote_port = (u16_t)row_oid[9];
1965 
1966  /* find tcp_pcb with requested ips and ports */
1967  for(i=0; i<LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
1968  pcb = *tcp_pcb_lists[i];
1969 
1970  while (pcb != NULL) {
1971  /* do local IP and local port match? */
1972  if(!IP_IS_V6_VAL(pcb->local_ip) &&
1973  ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) {
1974 
1975  /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */
1976  if(pcb->state == LISTEN) {
1977  if(ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY) && (remote_port == 0)) {
1978  /* fill in object properties */
1979  return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
1980  }
1981  } else {
1982  if(!IP_IS_V6_VAL(pcb->remote_ip) &&
1983  ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) {
1984  /* fill in object properties */
1985  return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len);
1986  }
1987  }
1988  }
1989 
1990  pcb = pcb->next;
1991  }
1992  }
1993 
1994  /* not found */
1995  return SNMP_ERR_NOSUCHINSTANCE;
1996 }
1997 
1998 static snmp_err_t
1999 tcp_ConnTable_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)
2000 {
2001  u8_t i;
2002  struct tcp_pcb *pcb;
2003  struct snmp_next_oid_state state;
2004  u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)];
2005 
2006  /* init struct to search next oid */
2007  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges));
2008 
2009  /* iterate over all possible OIDs to find the next one */
2010  for(i=0; i<LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
2011  pcb = *tcp_pcb_lists[i];
2012  while (pcb != NULL) {
2013  u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)];
2014 
2015  if(!IP_IS_V6_VAL(pcb->local_ip)) {
2016  snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]);
2017  test_oid[4] = pcb->local_port;
2018 
2019  /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */
2020  if(pcb->state == LISTEN) {
2021  snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[5]);
2022  test_oid[9] = 0;
2023  } else {
2024  if(IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */
2025  continue;
2026  }
2027  snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]);
2028  test_oid[9] = pcb->remote_port;
2029  }
2030 
2031  /* check generated OID: is it a candidate for the next one? */
2032  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb);
2033  }
2034 
2035  pcb = pcb->next;
2036  }
2037  }
2038 
2039  /* did we find a next one? */
2040  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
2041  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
2042  /* fill in object properties */
2043  return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len);
2044  }
2045 
2046  /* not found */
2047  return SNMP_ERR_NOSUCHINSTANCE;
2048 }
2049 
2050 #endif /* LWIP_IPV4 */
2051 
2052 /* --- tcpConnectionTable --- */
2053 
2054 static snmp_err_t
2055 tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value)
2056 {
2057  /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
2058  switch (*column) {
2059  case 7: /* tcpConnectionState */
2060  value->u32 = pcb->state + 1;
2061  break;
2062  case 8: /* tcpConnectionProcess */
2063  value->u32 = 0; /* not supported */
2064  break;
2065  default:
2066  return SNMP_ERR_NOSUCHINSTANCE;
2067  }
2068 
2069  return SNMP_ERR_NOERROR;
2070 }
2071 
2072 static snmp_err_t
2073 tcp_ConnectionTable_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)
2074 {
2075  ip_addr_t local_ip, remote_ip;
2076  u16_t local_port, remote_port;
2077  struct tcp_pcb *pcb;
2078  u8_t idx = 0;
2079  u8_t i;
2080  struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs};
2081 
2082  LWIP_UNUSED_ARG(value_len);
2083 
2084  /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */
2085  idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
2086  if(idx == 0) {
2087  return SNMP_ERR_NOSUCHINSTANCE;
2088  }
2089 
2090  /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */
2091  idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
2092  if(idx == 0) {
2093  return SNMP_ERR_NOSUCHINSTANCE;
2094  }
2095 
2096  /* find tcp_pcb with requested ip and port*/
2097  for(i=0; i<LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) {
2098  pcb = *tcp_pcb_nonlisten_lists[i];
2099 
2100  while (pcb != NULL) {
2101  if(ip_addr_cmp(&local_ip, &pcb->local_ip) &&
2102  (local_port == pcb->local_port) &&
2103  ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
2104  (remote_port == pcb->remote_port)) {
2105  /* fill in object properties */
2106  return tcp_ConnectionTable_get_cell_value_core(column, pcb, value);
2107  }
2108  pcb = pcb->next;
2109  }
2110  }
2111 
2112  /* not found */
2113  return SNMP_ERR_NOSUCHINSTANCE;
2114 }
2115 
2116 static snmp_err_t
2117 tcp_ConnectionTable_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)
2118 {
2119  struct tcp_pcb *pcb;
2120  struct snmp_next_oid_state state;
2121  /* 1x tcpConnectionLocalAddressType + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort
2122  * 1x tcpConnectionRemAddressType + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */
2123  u32_t result_temp[36];
2124  u8_t i;
2125  struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs};
2126 
2127  LWIP_UNUSED_ARG(value_len);
2128 
2129  /* init struct to search next oid */
2130  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
2131 
2132  /* iterate over all possible OIDs to find the next one */
2133  for(i=0; i<LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) {
2134  pcb = *tcp_pcb_nonlisten_lists[i];
2135 
2136  while (pcb != NULL) {
2137  u8_t idx = 0;
2138  u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
2139 
2140  /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */
2141  idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
2142 
2143  /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */
2144  idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
2145 
2146  /* check generated OID: is it a candidate for the next one? */
2147  snmp_next_oid_check(&state, test_oid, idx, pcb);
2148 
2149  pcb = pcb->next;
2150  }
2151  }
2152 
2153  /* did we find a next one? */
2154  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
2155  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
2156  /* fill in object properties */
2157  return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value);
2158  } else {
2159  /* not found */
2160  return SNMP_ERR_NOSUCHINSTANCE;
2161  }
2162 }
2163 
2164 /* --- tcpListenerTable --- */
2165 
2166 static snmp_err_t
2167 tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
2168 {
2169  /* all items except tcpListenerProcess are declared as not-accessible */
2170  switch (*column) {
2171  case 4: /* tcpListenerProcess */
2172  value->u32 = 0; /* not supported */
2173  break;
2174  default:
2175  return SNMP_ERR_NOSUCHINSTANCE;
2176  }
2177 
2178  return SNMP_ERR_NOERROR;
2179 }
2180 
2181 static snmp_err_t
2182 tcp_ListenerTable_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)
2183 {
2184  ip_addr_t local_ip;
2185  u16_t local_port;
2186  struct tcp_pcb_listen *pcb;
2187  u8_t idx = 0;
2188 
2189  LWIP_UNUSED_ARG(value_len);
2190 
2191  /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */
2192  idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
2193  if(idx == 0) {
2194  return SNMP_ERR_NOSUCHINSTANCE;
2195  }
2196 
2197  /* find tcp_pcb with requested ip and port*/
2198  pcb = tcp_listen_pcbs.listen_pcbs;
2199  while (pcb != NULL) {
2200  if(ip_addr_cmp(&local_ip, &pcb->local_ip) &&
2201  (local_port == pcb->local_port)) {
2202  /* fill in object properties */
2203  return tcp_ListenerTable_get_cell_value_core(column, value);
2204  }
2205  pcb = pcb->next;
2206  }
2207 
2208  /* not found */
2209  return SNMP_ERR_NOSUCHINSTANCE;
2210 }
2211 
2212 static snmp_err_t
2213 tcp_ListenerTable_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)
2214 {
2215  struct tcp_pcb_listen *pcb;
2216  struct snmp_next_oid_state state;
2217  /* 1x tcpListenerLocalAddressType + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */
2218  u32_t result_temp[18];
2219 
2220  LWIP_UNUSED_ARG(value_len);
2221 
2222  /* init struct to search next oid */
2223  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
2224 
2225  /* iterate over all possible OIDs to find the next one */
2226  pcb = tcp_listen_pcbs.listen_pcbs;
2227  while (pcb != NULL) {
2228  u8_t idx = 0;
2229  u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
2230 
2231  /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */
2232  idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
2233 
2234  /* check generated OID: is it a candidate for the next one? */
2235  snmp_next_oid_check(&state, test_oid, idx, NULL);
2236 
2237  pcb = pcb->next;
2238  }
2239 
2240  /* did we find a next one? */
2241  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
2242  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
2243  /* fill in object properties */
2244  return tcp_ListenerTable_get_cell_value_core(column, value);
2245  } else {
2246  /* not found */
2247  return SNMP_ERR_NOSUCHINSTANCE;
2248  }
2249 }
2250 
2251 #endif /* LWIP_TCP */
2252 
2253 /* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */
2254 
2255 #if LWIP_UDP
2256 
2257 static u16_t
2258 udp_get_value(struct snmp_node_instance* instance, void* value)
2259 {
2260  u32_t *uint_ptr = (u32_t*)value;
2261 
2262  switch (instance->node->oid) {
2263  case 1: /* udpInDatagrams */
2264  *uint_ptr = STATS_GET(mib2.udpindatagrams);
2265  return sizeof(*uint_ptr);
2266  case 2: /* udpNoPorts */
2267  *uint_ptr = STATS_GET(mib2.udpnoports);
2268  return sizeof(*uint_ptr);
2269  case 3: /* udpInErrors */
2270  *uint_ptr = STATS_GET(mib2.udpinerrors);
2271  return sizeof(*uint_ptr);
2272  case 4: /* udpOutDatagrams */
2273  *uint_ptr = STATS_GET(mib2.udpoutdatagrams);
2274  return sizeof(*uint_ptr);
2275  case 8: /* udpHCInDatagrams */
2276  memset(value, 0, 2*sizeof(u32_t)); /* not supported */
2277  return 2*sizeof(u32_t);
2278  case 9: /* udpHCOutDatagrams */
2279  memset(value, 0, 2*sizeof(u32_t)); /* not supported */
2280  return 2*sizeof(u32_t);
2281  default:
2282  LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid));
2283  break;
2284  }
2285 
2286  return 0;
2287 }
2288 
2289 /* --- udpEndpointTable --- */
2290 
2291 static snmp_err_t
2292 udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value)
2293 {
2294  /* all items except udpEndpointProcess are declared as not-accessible */
2295  switch (*column) {
2296  case 8: /* udpEndpointProcess */
2297  value->u32 = 0; /* not supported */
2298  break;
2299  default:
2300  return SNMP_ERR_NOSUCHINSTANCE;
2301  }
2302 
2303  return SNMP_ERR_NOERROR;
2304 }
2305 
2306 static snmp_err_t
2307 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)
2308 {
2309  ip_addr_t local_ip, remote_ip;
2310  u16_t local_port, remote_port;
2311  struct udp_pcb *pcb;
2312  u8_t idx = 0;
2313 
2314  LWIP_UNUSED_ARG(value_len);
2315 
2316  /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
2317  idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port);
2318  if(idx == 0) {
2319  return SNMP_ERR_NOSUCHINSTANCE;
2320  }
2321 
2322  /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
2323  idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port);
2324  if(idx == 0) {
2325  return SNMP_ERR_NOSUCHINSTANCE;
2326  }
2327 
2328  /* udpEndpointInstance */
2329  if(row_oid_len < (idx+1)) {
2330  return SNMP_ERR_NOSUCHINSTANCE;
2331  }
2332  if(row_oid[idx] != 0) {
2333  return SNMP_ERR_NOSUCHINSTANCE;
2334  }
2335 
2336  /* find udp_pcb with requested ip and port*/
2337  pcb = udp_pcbs;
2338  while (pcb != NULL) {
2339  if(ip_addr_cmp(&local_ip, &pcb->local_ip) &&
2340  (local_port == pcb->local_port) &&
2341  ip_addr_cmp(&remote_ip, &pcb->remote_ip) &&
2342  (remote_port == pcb->remote_port)) {
2343  /* fill in object properties */
2344  return udp_endpointTable_get_cell_value_core(column, value);
2345  }
2346  pcb = pcb->next;
2347  }
2348 
2349  /* not found */
2350  return SNMP_ERR_NOSUCHINSTANCE;
2351 }
2352 
2353 static snmp_err_t
2354 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)
2355 {
2356  struct udp_pcb *pcb;
2357  struct snmp_next_oid_state state;
2358  /* 1x udpEndpointLocalAddressType + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort +
2359  * 1x udpEndpointRemoteAddressType + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort +
2360  * 1x udpEndpointInstance = 37
2361  */
2362  u32_t result_temp[37];
2363 
2364  LWIP_UNUSED_ARG(value_len);
2365 
2366  /* init struct to search next oid */
2367  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp));
2368 
2369  /* iterate over all possible OIDs to find the next one */
2370  pcb = udp_pcbs;
2371  while (pcb != NULL) {
2372  u32_t test_oid[LWIP_ARRAYSIZE(result_temp)];
2373  u8_t idx = 0;
2374 
2375  /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */
2376  idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]);
2377 
2378  /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */
2379  idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]);
2380 
2381  test_oid[idx] = 0; /* udpEndpointInstance */
2382  idx++;
2383 
2384  /* check generated OID: is it a candidate for the next one? */
2385  snmp_next_oid_check(&state, test_oid, idx, NULL);
2386 
2387  pcb = pcb->next;
2388  }
2389 
2390  /* did we find a next one? */
2391  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
2392  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
2393  /* fill in object properties */
2394  return udp_endpointTable_get_cell_value_core(column, value);
2395  } else {
2396  /* not found */
2397  return SNMP_ERR_NOSUCHINSTANCE;
2398  }
2399 }
2400 
2401 #endif /* LWIP_UDP */
2402 
2403 /* --- udpTable --- */
2404 
2405 #if LWIP_UDP && LWIP_IPV4
2406 
2407 /* list of allowed value ranges for incoming OID */
2408 static const struct snmp_oid_range udp_Table_oid_ranges[] = {
2409  { 0, 0xff }, /* IP A */
2410  { 0, 0xff }, /* IP B */
2411  { 0, 0xff }, /* IP C */
2412  { 0, 0xff }, /* IP D */
2413  { 1, 0xffff } /* Port */
2414 };
2415 
2416 static snmp_err_t
2417 udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len)
2418 {
2419  LWIP_UNUSED_ARG(value_len);
2420 
2421  switch (*column) {
2422  case 1: /* udpLocalAddress */
2423  /* set reference to PCB local IP and return a generic node that copies IP4 addresses */
2424  value->u32 = ip_2_ip4(&pcb->local_ip)->addr;
2425  break;
2426  case 2: /* udpLocalPort */
2427  /* set reference to PCB local port and return a generic node that copies u16_t values */
2428  value->u32 = pcb->local_port;
2429  break;
2430  default:
2431  return SNMP_ERR_NOSUCHINSTANCE;
2432  }
2433 
2434  return SNMP_ERR_NOERROR;
2435 }
2436 
2437 static snmp_err_t
2438 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)
2439 {
2440  ip4_addr_t ip;
2441  u16_t port;
2442  struct udp_pcb *pcb;
2443 
2444  /* check if incoming OID length and if values are in plausible range */
2445  if(!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) {
2446  return SNMP_ERR_NOSUCHINSTANCE;
2447  }
2448 
2449  /* get IP and port from incoming OID */
2450  snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */
2451  port = (u16_t)row_oid[4];
2452 
2453  /* find udp_pcb with requested ip and port*/
2454  pcb = udp_pcbs;
2455  while (pcb != NULL) {
2456  if(!IP_IS_V6_VAL(pcb->local_ip)) {
2457  if(ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) {
2458  /* fill in object properties */
2459  return udp_Table_get_cell_value_core(pcb, column, value, value_len);
2460  }
2461  }
2462  pcb = pcb->next;
2463  }
2464 
2465  /* not found */
2466  return SNMP_ERR_NOSUCHINSTANCE;
2467 }
2468 
2469 static snmp_err_t
2470 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)
2471 {
2472  struct udp_pcb *pcb;
2473  struct snmp_next_oid_state state;
2474  u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
2475 
2476  /* init struct to search next oid */
2477  snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges));
2478 
2479  /* iterate over all possible OIDs to find the next one */
2480  pcb = udp_pcbs;
2481  while (pcb != NULL) {
2482  u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)];
2483 
2484  if(!IP_IS_V6_VAL(pcb->local_ip)) {
2485  snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]);
2486  test_oid[4] = pcb->local_port;
2487 
2488  /* check generated OID: is it a candidate for the next one? */
2489  snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb);
2490  }
2491 
2492  pcb = pcb->next;
2493  }
2494 
2495  /* did we find a next one? */
2496  if(state.status == SNMP_NEXT_OID_STATUS_SUCCESS) {
2497  snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len);
2498  /* fill in object properties */
2499  return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len);
2500  } else {
2501  /* not found */
2502  return SNMP_ERR_NOSUCHINSTANCE;
2503  }
2504 }
2505 
2506 #endif /* LWIP_UDP && LWIP_IPV4 */
2507 
2508 /* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */
2509 
2510 static u16_t
2511 snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value)
2512 {
2513  u32_t *uint_ptr = (u32_t*)value;
2514  switch (node->oid) {
2515  case 1: /* snmpInPkts */
2516  *uint_ptr = snmp_stats.inpkts;
2517  break;
2518  case 2: /* snmpOutPkts */
2519  *uint_ptr = snmp_stats.outpkts;
2520  break;
2521  case 3: /* snmpInBadVersions */
2522  *uint_ptr = snmp_stats.inbadversions;
2523  break;
2524  case 4: /* snmpInBadCommunityNames */
2525  *uint_ptr = snmp_stats.inbadcommunitynames;
2526  break;
2527  case 5: /* snmpInBadCommunityUses */
2528  *uint_ptr = snmp_stats.inbadcommunityuses;
2529  break;
2530  case 6: /* snmpInASNParseErrs */
2531  *uint_ptr = snmp_stats.inasnparseerrs;
2532  break;
2533  case 8: /* snmpInTooBigs */
2534  *uint_ptr = snmp_stats.intoobigs;
2535  break;
2536  case 9: /* snmpInNoSuchNames */
2537  *uint_ptr = snmp_stats.innosuchnames;
2538  break;
2539  case 10: /* snmpInBadValues */
2540  *uint_ptr = snmp_stats.inbadvalues;
2541  break;
2542  case 11: /* snmpInReadOnlys */
2543  *uint_ptr = snmp_stats.inreadonlys;
2544  break;
2545  case 12: /* snmpInGenErrs */
2546  *uint_ptr = snmp_stats.ingenerrs;
2547  break;
2548  case 13: /* snmpInTotalReqVars */
2549  *uint_ptr = snmp_stats.intotalreqvars;
2550  break;
2551  case 14: /* snmpInTotalSetVars */
2552  *uint_ptr = snmp_stats.intotalsetvars;
2553  break;
2554  case 15: /* snmpInGetRequests */
2555  *uint_ptr = snmp_stats.ingetrequests;
2556  break;
2557  case 16: /* snmpInGetNexts */
2558  *uint_ptr = snmp_stats.ingetnexts;
2559  break;
2560  case 17: /* snmpInSetRequests */
2561  *uint_ptr = snmp_stats.insetrequests;
2562  break;
2563  case 18: /* snmpInGetResponses */
2564  *uint_ptr = snmp_stats.ingetresponses;
2565  break;
2566  case 19: /* snmpInTraps */
2567  *uint_ptr = snmp_stats.intraps;
2568  break;
2569  case 20: /* snmpOutTooBigs */
2570  *uint_ptr = snmp_stats.outtoobigs;
2571  break;
2572  case 21: /* snmpOutNoSuchNames */
2573  *uint_ptr = snmp_stats.outnosuchnames;
2574  break;
2575  case 22: /* snmpOutBadValues */
2576  *uint_ptr = snmp_stats.outbadvalues;
2577  break;
2578  case 24: /* snmpOutGenErrs */
2579  *uint_ptr = snmp_stats.outgenerrs;
2580  break;
2581  case 25: /* snmpOutGetRequests */
2582  *uint_ptr = snmp_stats.outgetrequests;
2583  break;
2584  case 26: /* snmpOutGetNexts */
2585  *uint_ptr = snmp_stats.outgetnexts;
2586  break;
2587  case 27: /* snmpOutSetRequests */
2588  *uint_ptr = snmp_stats.outsetrequests;
2589  break;
2590  case 28: /* snmpOutGetResponses */
2591  *uint_ptr = snmp_stats.outgetresponses;
2592  break;
2593  case 29: /* snmpOutTraps */
2594  *uint_ptr = snmp_stats.outtraps;
2595  break;
2596  case 30: /* snmpEnableAuthenTraps */
2597  if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) {
2598  *uint_ptr = MIB2_AUTH_TRAPS_DISABLED;
2599  } else {
2600  *uint_ptr = MIB2_AUTH_TRAPS_ENABLED;
2601  }
2602  break;
2603  case 31: /* snmpSilentDrops */
2604  *uint_ptr = 0; /* not supported */
2605  break;
2606  case 32: /* snmpProxyDrops */
2607  *uint_ptr = 0; /* not supported */
2608  break;
2609  default:
2610  LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid));
2611  return 0;
2612  }
2613 
2614  return sizeof(*uint_ptr);
2615 }
2616 
2617 static snmp_err_t
2618 snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
2619 {
2620  snmp_err_t ret = SNMP_ERR_WRONGVALUE;
2621  LWIP_UNUSED_ARG(len);
2622 
2623  if (node->oid == 30) {
2624  /* snmpEnableAuthenTraps */
2625  s32_t *sint_ptr = (s32_t*)value;
2626 
2627  /* we should have writable non-volatile mem here */
2628  if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) {
2629  ret = SNMP_ERR_NOERROR;
2630  }
2631  }
2632  return ret;
2633 }
2634 
2635 static snmp_err_t
2636 snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value)
2637 {
2638  LWIP_UNUSED_ARG(len);
2639 
2640  if (node->oid == 30) {
2641  /* snmpEnableAuthenTraps */
2642  s32_t *sint_ptr = (s32_t*)value;
2643  if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) {
2644  snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED);
2645  } else {
2646  snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED);
2647  }
2648  }
2649 
2650  return SNMP_ERR_NOERROR;
2651 }
2652 
2653 #endif /* SNMP_LWIP_MIB2 */
2654 #endif /* LWIP_SNMP */
struct netif * netif_list
Definition: netif.c:84
#define IP_DEFAULT_TTL
Definition: opt.h:640
#define SNMP_MIB_DEBUG
Definition: snmp_opts.h:196
struct netif * netif_default
Definition: netif.c:85
uint32_t idx
Definition: lcd_log.c:247
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:267
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:276
#define netif_is_link_up(netif)
Definition: netif.h:368
struct netif * next
Definition: netif.h:184
u16_t mtu
Definition: netif.h:263
#define MEMCPY(dst, src, len)
Definition: opt.h:84
#define S32_F
Definition: cc.h:52
#define PBUF_POOL_BUFSIZE
Definition: lwipopts.h:105
void netif_set_up(struct netif *netif)
Definition: netif.c:530
char name[2]
Definition: netif.h:271
#define IP_REASS_MAX_PBUFS
Definition: opt.h:614
#define SNMP_LWIP_MIB2_SYSNAME
Definition: snmp_opts.h:218
#define NULL
Definition: usbd_def.h:53
#define SNMP_LWIP_MIB2_SYSLOCATION
Definition: snmp_opts.h:234
unsigned long u32_t
Definition: cc.h:42
#define MIB2_COPY_SYSUPTIME_TO(ptrToVal)
Definition: snmp.h:118
#define ARP_TABLE_SIZE
Definition: opt.h:451
#define PBUF_LINK_ENCAPSULATION_HLEN
Definition: opt.h:1193
#define IP_IS_V6_VAL(ipaddr)
Definition: ip_addr.h:196
#define IP_REASS_MAXAGE
Definition: opt.h:604
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:214
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:70
Definition: netif.h:182
#define LWIP_ARRAYSIZE(x)
Definition: def.h:53
#define SNMP_LWIP_MIB2_SYSDESC
Definition: snmp_opts.h:210
void netif_set_down(struct netif *netif)
Definition: netif.c:587
unsigned char u8_t
Definition: cc.h:38
ip6_addr_t ip_addr_t
Definition: ip_addr.h:194
#define SNMP_LWIP_MIB2_SYSCONTACT
Definition: snmp_opts.h:226
signed long s32_t
Definition: cc.h:43
#define netif_is_up(netif)
Definition: netif.h:356
#define PBUF_LINK_HLEN
Definition: opt.h:1184
#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
#define MEMP_NUM_TCP_PCB
Definition: lwipopts.h:88