]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ankh/lib/lwip/lib/contrib/src/core/snmp/mib2.c
update
[l4.git] / l4 / pkg / ankh / lib / lwip / lib / contrib / src / core / snmp / mib2.c
1 /**
2  * @file
3  * Management Information Base II (RFC1213) objects and functions.
4  *
5  * @note the object identifiers for this MIB-2 and private MIB tree
6  * must be kept in sorted ascending order. This to ensure correct getnext operation.
7  */
8
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: Christiaan Simons <christiaan.simons@axon.tv>
36  */
37
38 #include "lwip/opt.h"
39
40 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
41
42 #include "lwip/snmp.h"
43 #include "lwip/netif.h"
44 #include "lwip/ip.h"
45 #include "lwip/ip_frag.h"
46 #include "lwip/tcp_impl.h"
47 #include "lwip/udp.h"
48 #include "lwip/snmp_asn1.h"
49 #include "lwip/snmp_structs.h"
50 #include "netif/etharp.h"
51
52 /**
53  * IANA assigned enterprise ID for lwIP is 26381
54  * @see http://www.iana.org/assignments/enterprise-numbers
55  *
56  * @note this enterprise ID is assigned to the lwIP project,
57  * all object identifiers living under this ID are assigned
58  * by the lwIP maintainers (contact Christiaan Simons)!
59  * @note don't change this define, use snmp_set_sysobjid()
60  *
61  * If you need to create your own private MIB you'll need
62  * to apply for your own enterprise ID with IANA:
63  * http://www.iana.org/numbers.html
64  */
65 #define SNMP_ENTERPRISE_ID 26381
66 #define SNMP_SYSOBJID_LEN 7
67 #define SNMP_SYSOBJID {1, 3, 6, 1, 4, 1, SNMP_ENTERPRISE_ID}
68
69 #ifndef SNMP_SYSSERVICES
70 #define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2))
71 #endif
72
73 #ifndef SNMP_GET_SYSUPTIME
74 #define SNMP_GET_SYSUPTIME(sysuptime)
75 #endif
76
77 static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
78 static void system_get_value(struct obj_def *od, u16_t len, void *value);
79 static u8_t system_set_test(struct obj_def *od, u16_t len, void *value);
80 static void system_set_value(struct obj_def *od, u16_t len, void *value);
81 static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
82 static void interfaces_get_value(struct obj_def *od, u16_t len, void *value);
83 static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
84 static void ifentry_get_value(struct obj_def *od, u16_t len, void *value);
85 #if !SNMP_SAFE_REQUESTS
86 static u8_t ifentry_set_test (struct obj_def *od, u16_t len, void *value);
87 static void ifentry_set_value (struct obj_def *od, u16_t len, void *value);
88 #endif /* SNMP_SAFE_REQUESTS */
89 static void atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
90 static void atentry_get_value(struct obj_def *od, u16_t len, void *value);
91 static void ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
92 static void ip_get_value(struct obj_def *od, u16_t len, void *value);
93 static u8_t ip_set_test(struct obj_def *od, u16_t len, void *value);
94 static void ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
95 static void ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value);
96 static void ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
97 static void ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value);
98 static void ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
99 static void ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value);
100 static void icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
101 static void icmp_get_value(struct obj_def *od, u16_t len, void *value);
102 #if LWIP_TCP
103 static void tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
104 static void tcp_get_value(struct obj_def *od, u16_t len, void *value);
105 #ifdef THIS_SEEMS_UNUSED
106 static void tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
107 static void tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value);
108 #endif
109 #endif
110 static void udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
111 static void udp_get_value(struct obj_def *od, u16_t len, void *value);
112 static void udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
113 static void udpentry_get_value(struct obj_def *od, u16_t len, void *value);
114 static void snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
115 static void snmp_get_value(struct obj_def *od, u16_t len, void *value);
116 static u8_t snmp_set_test(struct obj_def *od, u16_t len, void *value);
117 static void snmp_set_value(struct obj_def *od, u16_t len, void *value);
118
119
120 /* snmp .1.3.6.1.2.1.11 */
121 const mib_scalar_node snmp_scalar = {
122   &snmp_get_object_def,
123   &snmp_get_value,
124   &snmp_set_test,
125   &snmp_set_value,
126   MIB_NODE_SC,
127   0
128 };
129 const s32_t snmp_ids[28] = {
130   1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16,
131   17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30
132 };
133 struct mib_node* const snmp_nodes[28] = {
134   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
135   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
136   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
137   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
138   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
139   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
140   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
141   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
142   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
143   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
144   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
145   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
146   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar,
147   (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar
148 };
149 const struct mib_array_node snmp = {
150   &noleafs_get_object_def,
151   &noleafs_get_value,
152   &noleafs_set_test,
153   &noleafs_set_value,
154   MIB_NODE_AR,
155   28,
156   snmp_ids,
157   snmp_nodes
158 };
159
160 /* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */
161 /* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */
162 /* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */
163
164 /* udp .1.3.6.1.2.1.7 */
165 /** index root node for udpTable */
166 struct mib_list_rootnode udp_root = {
167   &noleafs_get_object_def,
168   &noleafs_get_value,
169   &noleafs_set_test,
170   &noleafs_set_value,
171   MIB_NODE_LR,
172   0,
173   NULL,
174   NULL,
175   0
176 };
177 const s32_t udpentry_ids[2] = { 1, 2 };
178 struct mib_node* const udpentry_nodes[2] = {
179   (struct mib_node*)&udp_root, (struct mib_node*)&udp_root,
180 };
181 const struct mib_array_node udpentry = {
182   &noleafs_get_object_def,
183   &noleafs_get_value,
184   &noleafs_set_test,
185   &noleafs_set_value,
186   MIB_NODE_AR,
187   2,
188   udpentry_ids,
189   udpentry_nodes
190 };
191
192 s32_t udptable_id = 1;
193 struct mib_node* udptable_node = (struct mib_node*)&udpentry;
194 struct mib_ram_array_node udptable = {
195   &noleafs_get_object_def,
196   &noleafs_get_value,
197   &noleafs_set_test,
198   &noleafs_set_value,
199   MIB_NODE_RA,
200   0,
201   &udptable_id,
202   &udptable_node
203 };
204
205 const mib_scalar_node udp_scalar = {
206   &udp_get_object_def,
207   &udp_get_value,
208   &noleafs_set_test,
209   &noleafs_set_value,
210   MIB_NODE_SC,
211   0
212 };
213 const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 };
214 struct mib_node* const udp_nodes[5] = {
215   (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar,
216   (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar,
217   (struct mib_node*)&udptable
218 };
219 const struct mib_array_node udp = {
220   &noleafs_get_object_def,
221   &noleafs_get_value,
222   &noleafs_set_test,
223   &noleafs_set_value,
224   MIB_NODE_AR,
225   5,
226   udp_ids,
227   udp_nodes
228 };
229
230 /* tcp .1.3.6.1.2.1.6 */
231 #if LWIP_TCP
232 /* only if the TCP protocol is available may implement this group */
233 /** index root node for tcpConnTable */
234 struct mib_list_rootnode tcpconntree_root = {
235   &noleafs_get_object_def,
236   &noleafs_get_value,
237   &noleafs_set_test,
238   &noleafs_set_value,
239   MIB_NODE_LR,
240   0,
241   NULL,
242   NULL,
243   0
244 };
245 const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 };
246 struct mib_node* const tcpconnentry_nodes[5] = {
247   (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root,
248   (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root,
249   (struct mib_node*)&tcpconntree_root
250 };
251 const struct mib_array_node tcpconnentry = {
252   &noleafs_get_object_def,
253   &noleafs_get_value,
254   &noleafs_set_test,
255   &noleafs_set_value,
256   MIB_NODE_AR,
257   5,
258   tcpconnentry_ids,
259   tcpconnentry_nodes
260 };
261
262 s32_t tcpconntable_id = 1;
263 struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry;
264 struct mib_ram_array_node tcpconntable = {
265   &noleafs_get_object_def,
266   &noleafs_get_value,
267   &noleafs_set_test,
268   &noleafs_set_value,
269   MIB_NODE_RA,
270 /** @todo update maxlength when inserting / deleting from table
271    0 when table is empty, 1 when more than one entry */
272   0,
273   &tcpconntable_id,
274   &tcpconntable_node
275 };
276
277 const mib_scalar_node tcp_scalar = {
278   &tcp_get_object_def,
279   &tcp_get_value,
280   &noleafs_set_test,
281   &noleafs_set_value,
282   MIB_NODE_SC,
283   0
284 };
285 const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
286 struct mib_node* const tcp_nodes[15] = {
287   (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
288   (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
289   (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
290   (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
291   (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
292   (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar,
293   (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar,
294   (struct mib_node*)&tcp_scalar
295 };
296 const struct mib_array_node tcp = {
297   &noleafs_get_object_def,
298   &noleafs_get_value,
299   &noleafs_set_test,
300   &noleafs_set_value,
301   MIB_NODE_AR,
302   15,
303   tcp_ids,
304   tcp_nodes
305 };
306 #endif
307
308 /* icmp .1.3.6.1.2.1.5 */
309 const mib_scalar_node icmp_scalar = {
310   &icmp_get_object_def,
311   &icmp_get_value,
312   &noleafs_set_test,
313   &noleafs_set_value,
314   MIB_NODE_SC,
315   0
316 };
317 const s32_t icmp_ids[26] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
318 struct mib_node* const icmp_nodes[26] = {
319   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
320   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
321   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
322   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
323   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
324   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
325   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
326   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
327   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
328   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
329   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
330   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar,
331   (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar
332 };
333 const struct mib_array_node icmp = {
334   &noleafs_get_object_def,
335   &noleafs_get_value,
336   &noleafs_set_test,
337   &noleafs_set_value,
338   MIB_NODE_AR,
339   26,
340   icmp_ids,
341   icmp_nodes
342 };
343
344 /** index root node for ipNetToMediaTable */
345 struct mib_list_rootnode ipntomtree_root = {
346   &noleafs_get_object_def,
347   &noleafs_get_value,
348   &noleafs_set_test,
349   &noleafs_set_value,
350   MIB_NODE_LR,
351   0,
352   NULL,
353   NULL,
354   0
355 };
356 const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 };
357 struct mib_node* const ipntomentry_nodes[4] = {
358   (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root,
359   (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root
360 };
361 const struct mib_array_node ipntomentry = {
362   &noleafs_get_object_def,
363   &noleafs_get_value,
364   &noleafs_set_test,
365   &noleafs_set_value,
366   MIB_NODE_AR,
367   4,
368   ipntomentry_ids,
369   ipntomentry_nodes
370 };
371
372 s32_t ipntomtable_id = 1;
373 struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry;
374 struct mib_ram_array_node ipntomtable = {
375   &noleafs_get_object_def,
376   &noleafs_get_value,
377   &noleafs_set_test,
378   &noleafs_set_value,
379   MIB_NODE_RA,
380   0,
381   &ipntomtable_id,
382   &ipntomtable_node
383 };
384
385 /** index root node for ipRouteTable */
386 struct mib_list_rootnode iprtetree_root = {
387   &noleafs_get_object_def,
388   &noleafs_get_value,
389   &noleafs_set_test,
390   &noleafs_set_value,
391   MIB_NODE_LR,
392   0,
393   NULL,
394   NULL,
395   0
396 };
397 const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
398 struct mib_node* const iprteentry_nodes[13] = {
399   (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
400   (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
401   (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
402   (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
403   (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
404   (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root,
405   (struct mib_node*)&iprtetree_root
406 };
407 const struct mib_array_node iprteentry = {
408   &noleafs_get_object_def,
409   &noleafs_get_value,
410   &noleafs_set_test,
411   &noleafs_set_value,
412   MIB_NODE_AR,
413   13,
414   iprteentry_ids,
415   iprteentry_nodes
416 };
417
418 s32_t iprtetable_id = 1;
419 struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry;
420 struct mib_ram_array_node iprtetable = {
421   &noleafs_get_object_def,
422   &noleafs_get_value,
423   &noleafs_set_test,
424   &noleafs_set_value,
425   MIB_NODE_RA,
426   0,
427   &iprtetable_id,
428   &iprtetable_node
429 };
430
431 /** index root node for ipAddrTable */
432 struct mib_list_rootnode ipaddrtree_root = {
433   &noleafs_get_object_def,
434   &noleafs_get_value,
435   &noleafs_set_test,
436   &noleafs_set_value,
437   MIB_NODE_LR,
438   0,
439   NULL,
440   NULL,
441   0
442 };
443 const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 };
444 struct mib_node* const ipaddrentry_nodes[5] = {
445   (struct mib_node*)&ipaddrtree_root,
446   (struct mib_node*)&ipaddrtree_root,
447   (struct mib_node*)&ipaddrtree_root,
448   (struct mib_node*)&ipaddrtree_root,
449   (struct mib_node*)&ipaddrtree_root
450 };
451 const struct mib_array_node ipaddrentry = {
452   &noleafs_get_object_def,
453   &noleafs_get_value,
454   &noleafs_set_test,
455   &noleafs_set_value,
456   MIB_NODE_AR,
457   5,
458   ipaddrentry_ids,
459   ipaddrentry_nodes
460 };
461
462 s32_t ipaddrtable_id = 1;
463 struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry;
464 struct mib_ram_array_node ipaddrtable = {
465   &noleafs_get_object_def,
466   &noleafs_get_value,
467   &noleafs_set_test,
468   &noleafs_set_value,
469   MIB_NODE_RA,
470   0,
471   &ipaddrtable_id,
472   &ipaddrtable_node
473 };
474
475 /* ip .1.3.6.1.2.1.4 */
476 const mib_scalar_node ip_scalar = {
477   &ip_get_object_def,
478   &ip_get_value,
479   &ip_set_test,
480   &noleafs_set_value,
481   MIB_NODE_SC,
482   0
483 };
484 const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
485 struct mib_node* const ip_nodes[23] = {
486   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
487   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
488   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
489   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
490   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
491   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
492   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
493   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
494   (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar,
495   (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable,
496   (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable,
497   (struct mib_node*)&ip_scalar
498 };
499 const struct mib_array_node mib2_ip = {
500   &noleafs_get_object_def,
501   &noleafs_get_value,
502   &noleafs_set_test,
503   &noleafs_set_value,
504   MIB_NODE_AR,
505   23,
506   ip_ids,
507   ip_nodes
508 };
509
510 /** index root node for atTable */
511 struct mib_list_rootnode arptree_root = {
512   &noleafs_get_object_def,
513   &noleafs_get_value,
514   &noleafs_set_test,
515   &noleafs_set_value,
516   MIB_NODE_LR,
517   0,
518   NULL,
519   NULL,
520   0
521 };
522 const s32_t atentry_ids[3] = { 1, 2, 3 };
523 struct mib_node* const atentry_nodes[3] = {
524   (struct mib_node*)&arptree_root,
525   (struct mib_node*)&arptree_root,
526   (struct mib_node*)&arptree_root
527 };
528 const struct mib_array_node atentry = {
529   &noleafs_get_object_def,
530   &noleafs_get_value,
531   &noleafs_set_test,
532   &noleafs_set_value,
533   MIB_NODE_AR,
534   3,
535   atentry_ids,
536   atentry_nodes
537 };
538
539 const s32_t attable_id = 1;
540 struct mib_node* const attable_node = (struct mib_node*)&atentry;
541 const struct mib_array_node attable = {
542   &noleafs_get_object_def,
543   &noleafs_get_value,
544   &noleafs_set_test,
545   &noleafs_set_value,
546   MIB_NODE_AR,
547   1,
548   &attable_id,
549   &attable_node
550 };
551
552 /* at .1.3.6.1.2.1.3 */
553 s32_t at_id = 1;
554 struct mib_node* mib2_at_node = (struct mib_node*)&attable;
555 struct mib_ram_array_node at = {
556   &noleafs_get_object_def,
557   &noleafs_get_value,
558   &noleafs_set_test,
559   &noleafs_set_value,
560   MIB_NODE_RA,
561   0,
562   &at_id,
563   &mib2_at_node
564 };
565
566 /** index root node for ifTable */
567 struct mib_list_rootnode iflist_root = {
568   &ifentry_get_object_def,
569   &ifentry_get_value,
570 #if SNMP_SAFE_REQUESTS
571   &noleafs_set_test,
572   &noleafs_set_value,
573 #else /* SNMP_SAFE_REQUESTS */
574   &ifentry_set_test,
575   &ifentry_set_value,
576 #endif /* SNMP_SAFE_REQUESTS */
577   MIB_NODE_LR,
578   0,
579   NULL,
580   NULL,
581   0
582 };
583 const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
584 struct mib_node* const ifentry_nodes[22] = {
585   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
586   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
587   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
588   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
589   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
590   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
591   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
592   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
593   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
594   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root,
595   (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root
596 };
597 const struct mib_array_node ifentry = {
598   &noleafs_get_object_def,
599   &noleafs_get_value,
600   &noleafs_set_test,
601   &noleafs_set_value,
602   MIB_NODE_AR,
603   22,
604   ifentry_ids,
605   ifentry_nodes
606 };
607
608 s32_t iftable_id = 1;
609 struct mib_node* iftable_node = (struct mib_node*)&ifentry;
610 struct mib_ram_array_node iftable = {
611   &noleafs_get_object_def,
612   &noleafs_get_value,
613   &noleafs_set_test,
614   &noleafs_set_value,
615   MIB_NODE_RA,
616   0,
617   &iftable_id,
618   &iftable_node
619 };
620
621 /* interfaces .1.3.6.1.2.1.2 */
622 const mib_scalar_node interfaces_scalar = {
623   &interfaces_get_object_def,
624   &interfaces_get_value,
625   &noleafs_set_test,
626   &noleafs_set_value,
627   MIB_NODE_SC,
628   0
629 };
630 const s32_t interfaces_ids[2] = { 1, 2 };
631 struct mib_node* const interfaces_nodes[2] = {
632   (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable
633 };
634 const struct mib_array_node interfaces = {
635   &noleafs_get_object_def,
636   &noleafs_get_value,
637   &noleafs_set_test,
638   &noleafs_set_value,
639   MIB_NODE_AR,
640   2,
641   interfaces_ids,
642   interfaces_nodes
643 };
644
645
646 /*             0 1 2 3 4 5 6 */
647 /* system .1.3.6.1.2.1.1 */
648 const mib_scalar_node sys_tem_scalar = {
649   &system_get_object_def,
650   &system_get_value,
651   &system_set_test,
652   &system_set_value,
653   MIB_NODE_SC,
654   0
655 };
656 const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 };
657 struct mib_node* const sys_tem_nodes[7] = {
658   (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
659   (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
660   (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar,
661   (struct mib_node*)&sys_tem_scalar
662 };
663 /* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */
664 const struct mib_array_node sys_tem = {
665   &noleafs_get_object_def,
666   &noleafs_get_value,
667   &noleafs_set_test,
668   &noleafs_set_value,
669   MIB_NODE_AR,
670   7,
671   sys_tem_ids,
672   sys_tem_nodes
673 };
674
675 /* mib-2 .1.3.6.1.2.1 */
676 #if LWIP_TCP
677 #define MIB2_GROUPS 8
678 #else
679 #define MIB2_GROUPS 7
680 #endif
681 const s32_t mib2_ids[MIB2_GROUPS] =
682 {
683   1,
684   2,
685   3,
686   4,
687   5,
688 #if LWIP_TCP
689   6,
690 #endif
691   7,
692   11
693 };
694 struct mib_node* const mib2_nodes[MIB2_GROUPS] = {
695   (struct mib_node*)&sys_tem,
696   (struct mib_node*)&interfaces,
697   (struct mib_node*)&at,
698   (struct mib_node*)&mib2_ip,
699   (struct mib_node*)&icmp,
700 #if LWIP_TCP
701   (struct mib_node*)&tcp,
702 #endif
703   (struct mib_node*)&udp,
704   (struct mib_node*)&snmp
705 };
706
707 const struct mib_array_node mib2 = {
708   &noleafs_get_object_def,
709   &noleafs_get_value,
710   &noleafs_set_test,
711   &noleafs_set_value,
712   MIB_NODE_AR,
713   MIB2_GROUPS,
714   mib2_ids,
715   mib2_nodes
716 };
717
718 /* mgmt .1.3.6.1.2 */
719 const s32_t mgmt_ids[1] = { 1 };
720 struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 };
721 const struct mib_array_node mgmt = {
722   &noleafs_get_object_def,
723   &noleafs_get_value,
724   &noleafs_set_test,
725   &noleafs_set_value,
726   MIB_NODE_AR,
727   1,
728   mgmt_ids,
729   mgmt_nodes
730 };
731
732 /* internet .1.3.6.1 */
733 #if SNMP_PRIVATE_MIB
734 /* When using a private MIB, you have to create a file 'private_mib.h' that contains
735  * a 'struct mib_array_node mib_private' which contains your MIB. */
736 s32_t internet_ids[2] = { 2, 4 };
737 struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private };
738 const struct mib_array_node internet = {
739   &noleafs_get_object_def,
740   &noleafs_get_value,
741   &noleafs_set_test,
742   &noleafs_set_value,
743   MIB_NODE_AR,
744   2,
745   internet_ids,
746   internet_nodes
747 };
748 #else
749 const s32_t internet_ids[1] = { 2 };
750 struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt };
751 const struct mib_array_node internet = {
752   &noleafs_get_object_def,
753   &noleafs_get_value,
754   &noleafs_set_test,
755   &noleafs_set_value,
756   MIB_NODE_AR,
757   1,
758   internet_ids,
759   internet_nodes
760 };
761 #endif
762
763 /** mib-2.system.sysObjectID  */
764 static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID};
765 /** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */
766 static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}};
767 /** mib-2.system.sysServices */
768 static const s32_t sysservices = SNMP_SYSSERVICES;
769
770 /** mib-2.system.sysDescr */
771 static const u8_t sysdescr_len_default = 4;
772 static const u8_t sysdescr_default[] = "lwIP";
773 static u8_t* sysdescr_len_ptr = (u8_t*)&sysdescr_len_default;
774 static u8_t* sysdescr_ptr = (u8_t*)&sysdescr_default[0];
775 /** mib-2.system.sysContact */
776 static const u8_t syscontact_len_default = 0;
777 static const u8_t syscontact_default[] = "";
778 static u8_t* syscontact_len_ptr = (u8_t*)&syscontact_len_default;
779 static u8_t* syscontact_ptr = (u8_t*)&syscontact_default[0];
780 /** mib-2.system.sysName */
781 static const u8_t sysname_len_default = 8;
782 static const u8_t sysname_default[] = "FQDN-unk";
783 static u8_t* sysname_len_ptr = (u8_t*)&sysname_len_default;
784 static u8_t* sysname_ptr = (u8_t*)&sysname_default[0];
785 /** mib-2.system.sysLocation */
786 static const u8_t syslocation_len_default = 0;
787 static const u8_t syslocation_default[] = "";
788 static u8_t* syslocation_len_ptr = (u8_t*)&syslocation_len_default;
789 static u8_t* syslocation_ptr = (u8_t*)&syslocation_default[0];
790 /** mib-2.snmp.snmpEnableAuthenTraps */
791 static const u8_t snmpenableauthentraps_default = 2; /* disabled */
792 static u8_t* snmpenableauthentraps_ptr = (u8_t*)&snmpenableauthentraps_default;
793
794 /** mib-2.interfaces.ifTable.ifEntry.ifSpecific (zeroDotZero) */
795 static const struct snmp_obj_id ifspecific = {2, {0, 0}};
796 /** mib-2.ip.ipRouteTable.ipRouteEntry.ipRouteInfo (zeroDotZero) */
797 static const struct snmp_obj_id iprouteinfo = {2, {0, 0}};
798
799
800
801 /* mib-2.system counter(s) */
802 static u32_t sysuptime = 0;
803
804 /* mib-2.ip counter(s) */
805 static u32_t ipinreceives = 0,
806              ipinhdrerrors = 0,
807              ipinaddrerrors = 0,
808              ipforwdatagrams = 0,
809              ipinunknownprotos = 0,
810              ipindiscards = 0,
811              ipindelivers = 0,
812              ipoutrequests = 0,
813              ipoutdiscards = 0,
814              ipoutnoroutes = 0,
815              ipreasmreqds = 0,
816              ipreasmoks = 0,
817              ipreasmfails = 0,
818              ipfragoks = 0,
819              ipfragfails = 0,
820              ipfragcreates = 0,
821              iproutingdiscards = 0;
822 /* mib-2.icmp counter(s) */
823 static u32_t icmpinmsgs = 0,
824              icmpinerrors = 0,
825              icmpindestunreachs = 0,
826              icmpintimeexcds = 0,
827              icmpinparmprobs = 0,
828              icmpinsrcquenchs = 0,
829              icmpinredirects = 0,
830              icmpinechos = 0,
831              icmpinechoreps = 0,
832              icmpintimestamps = 0,
833              icmpintimestampreps = 0,
834              icmpinaddrmasks = 0,
835              icmpinaddrmaskreps = 0,
836              icmpoutmsgs = 0,
837              icmpouterrors = 0,
838              icmpoutdestunreachs = 0,
839              icmpouttimeexcds = 0,
840              icmpoutparmprobs = 0,
841              icmpoutsrcquenchs = 0,
842              icmpoutredirects = 0,
843              icmpoutechos = 0,
844              icmpoutechoreps = 0,
845              icmpouttimestamps = 0,
846              icmpouttimestampreps = 0,
847              icmpoutaddrmasks = 0,
848              icmpoutaddrmaskreps = 0;
849 /* mib-2.tcp counter(s) */
850 static u32_t tcpactiveopens = 0,
851              tcppassiveopens = 0,
852              tcpattemptfails = 0,
853              tcpestabresets = 0,
854              tcpinsegs = 0,
855              tcpoutsegs = 0,
856              tcpretranssegs = 0,
857              tcpinerrs = 0,
858              tcpoutrsts = 0;
859 /* mib-2.udp counter(s) */
860 static u32_t udpindatagrams = 0,
861              udpnoports = 0,
862              udpinerrors = 0,
863              udpoutdatagrams = 0;
864 /* mib-2.snmp counter(s) */
865 static u32_t snmpinpkts = 0,
866              snmpoutpkts = 0,
867              snmpinbadversions = 0,
868              snmpinbadcommunitynames = 0,
869              snmpinbadcommunityuses = 0,
870              snmpinasnparseerrs = 0,
871              snmpintoobigs = 0,
872              snmpinnosuchnames = 0,
873              snmpinbadvalues = 0,
874              snmpinreadonlys = 0,
875              snmpingenerrs = 0,
876              snmpintotalreqvars = 0,
877              snmpintotalsetvars = 0,
878              snmpingetrequests = 0,
879              snmpingetnexts = 0,
880              snmpinsetrequests = 0,
881              snmpingetresponses = 0,
882              snmpintraps = 0,
883              snmpouttoobigs = 0,
884              snmpoutnosuchnames = 0,
885              snmpoutbadvalues = 0,
886              snmpoutgenerrs = 0,
887              snmpoutgetrequests = 0,
888              snmpoutgetnexts = 0,
889              snmpoutsetrequests = 0,
890              snmpoutgetresponses = 0,
891              snmpouttraps = 0;
892
893
894
895 /* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */
896 /**
897  * Copy octet string.
898  *
899  * @param dst points to destination
900  * @param src points to source
901  * @param n number of octets to copy.
902  */
903 static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n)
904 {
905   u16_t i = n;
906   while (i > 0) {
907     i--;
908     *dst++ = *src++;
909   }
910 }
911
912 /**
913  * Copy object identifier (s32_t) array.
914  *
915  * @param dst points to destination
916  * @param src points to source
917  * @param n number of sub identifiers to copy.
918  */
919 void objectidncpy(s32_t *dst, s32_t *src, u8_t n)
920 {
921   u8_t i = n;
922   while(i > 0) {
923     i--;
924     *dst++ = *src++;
925   }
926 }
927
928 /**
929  * Initializes sysDescr pointers.
930  *
931  * @param str if non-NULL then copy str pointer
932  * @param len points to string length, excluding zero terminator
933  */
934 void snmp_set_sysdesr(u8_t *str, u8_t *len)
935 {
936   if (str != NULL)
937   {
938     sysdescr_ptr = str;
939     sysdescr_len_ptr = len;
940   }
941 }
942
943 void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid)
944 {
945   *oid = &sysobjid;
946 }
947
948 /**
949  * Initializes sysObjectID value.
950  *
951  * @param oid points to stuct snmp_obj_id to copy
952  */
953 void snmp_set_sysobjid(struct snmp_obj_id *oid)
954 {
955   sysobjid = *oid;
956 }
957
958 /**
959  * Must be called at regular 10 msec interval from a timer interrupt
960  * or signal handler depending on your runtime environment.
961  */
962 void snmp_inc_sysuptime(void)
963 {
964   sysuptime++;
965 }
966
967 void snmp_add_sysuptime(u32_t value)
968 {
969   sysuptime+=value;
970 }
971
972 void snmp_get_sysuptime(u32_t *value)
973 {
974   SNMP_GET_SYSUPTIME(sysuptime);
975   *value = sysuptime;
976 }
977
978 /**
979  * Initializes sysContact pointers,
980  * e.g. ptrs to non-volatile memory external to lwIP.
981  *
982  * @param ocstr if non-NULL then copy str pointer
983  * @param ocstrlen points to string length, excluding zero terminator
984  */
985 void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen)
986 {
987   if (ocstr != NULL)
988   {
989     syscontact_ptr = ocstr;
990     syscontact_len_ptr = ocstrlen;
991   }
992 }
993
994 /**
995  * Initializes sysName pointers,
996  * e.g. ptrs to non-volatile memory external to lwIP.
997  *
998  * @param ocstr if non-NULL then copy str pointer
999  * @param ocstrlen points to string length, excluding zero terminator
1000  */
1001 void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen)
1002 {
1003   if (ocstr != NULL)
1004   {
1005     sysname_ptr = ocstr;
1006     sysname_len_ptr = ocstrlen;
1007   }
1008 }
1009
1010 /**
1011  * Initializes sysLocation pointers,
1012  * e.g. ptrs to non-volatile memory external to lwIP.
1013  *
1014  * @param ocstr if non-NULL then copy str pointer
1015  * @param ocstrlen points to string length, excluding zero terminator
1016  */
1017 void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen)
1018 {
1019   if (ocstr != NULL)
1020   {
1021     syslocation_ptr = ocstr;
1022     syslocation_len_ptr = ocstrlen;
1023   }
1024 }
1025
1026
1027 void snmp_add_ifinoctets(struct netif *ni, u32_t value)
1028 {
1029   ni->ifinoctets += value;
1030 }
1031
1032 void snmp_inc_ifinucastpkts(struct netif *ni)
1033 {
1034   (ni->ifinucastpkts)++;
1035 }
1036
1037 void snmp_inc_ifinnucastpkts(struct netif *ni)
1038 {
1039   (ni->ifinnucastpkts)++;
1040 }
1041
1042 void snmp_inc_ifindiscards(struct netif *ni)
1043 {
1044   (ni->ifindiscards)++;
1045 }
1046
1047 void snmp_add_ifoutoctets(struct netif *ni, u32_t value)
1048 {
1049   ni->ifoutoctets += value;
1050 }
1051
1052 void snmp_inc_ifoutucastpkts(struct netif *ni)
1053 {
1054   (ni->ifoutucastpkts)++;
1055 }
1056
1057 void snmp_inc_ifoutnucastpkts(struct netif *ni)
1058 {
1059   (ni->ifoutnucastpkts)++;
1060 }
1061
1062 void snmp_inc_ifoutdiscards(struct netif *ni)
1063 {
1064   (ni->ifoutdiscards)++;
1065 }
1066
1067 void snmp_inc_iflist(void)
1068 {
1069   struct mib_list_node *if_node = NULL;
1070
1071   snmp_mib_node_insert(&iflist_root, iflist_root.count + 1, &if_node);
1072   /* enable getnext traversal on filled table */
1073   iftable.maxlength = 1;
1074 }
1075
1076 void snmp_dec_iflist(void)
1077 {
1078   snmp_mib_node_delete(&iflist_root, iflist_root.tail);
1079   /* disable getnext traversal on empty table */
1080   if(iflist_root.count == 0) iftable.maxlength = 0;
1081 }
1082
1083 /**
1084  * Inserts ARP table indexes (.xIfIndex.xNetAddress)
1085  * into arp table index trees (both atTable and ipNetToMediaTable).
1086  */
1087 void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip)
1088 {
1089   struct mib_list_rootnode *at_rn;
1090   struct mib_list_node *at_node;
1091   s32_t arpidx[5];
1092   u8_t level, tree;
1093
1094   LWIP_ASSERT("ni != NULL", ni != NULL);
1095   snmp_netiftoifindex(ni, &arpidx[0]);
1096   snmp_iptooid(ip, &arpidx[1]);
1097
1098   for (tree = 0; tree < 2; tree++)
1099   {
1100     if (tree == 0)
1101     {
1102       at_rn = &arptree_root;
1103     }
1104     else
1105     {
1106       at_rn = &ipntomtree_root;
1107     }
1108     for (level = 0; level < 5; level++)
1109     {
1110       at_node = NULL;
1111       snmp_mib_node_insert(at_rn, arpidx[level], &at_node);
1112       if ((level != 4) && (at_node != NULL))
1113       {
1114         if (at_node->nptr == NULL)
1115         {
1116           at_rn = snmp_mib_lrn_alloc();
1117           at_node->nptr = (struct mib_node*)at_rn;
1118           if (at_rn != NULL)
1119           {
1120             if (level == 3)
1121             {
1122               if (tree == 0)
1123               {
1124                 at_rn->get_object_def = atentry_get_object_def;
1125                 at_rn->get_value = atentry_get_value;
1126               }
1127               else
1128               {
1129                 at_rn->get_object_def = ip_ntomentry_get_object_def;
1130                 at_rn->get_value = ip_ntomentry_get_value;
1131               }
1132               at_rn->set_test = noleafs_set_test;
1133               at_rn->set_value = noleafs_set_value;
1134             }
1135           }
1136           else
1137           {
1138             /* at_rn == NULL, malloc failure */
1139             LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_arpidx_tree() insert failed, mem full"));
1140             break;
1141           }
1142         }
1143         else
1144         {
1145           at_rn = (struct mib_list_rootnode*)at_node->nptr;
1146         }
1147       }
1148     }
1149   }
1150   /* enable getnext traversal on filled tables */
1151   at.maxlength = 1;
1152   ipntomtable.maxlength = 1;
1153 }
1154
1155 /**
1156  * Removes ARP table indexes (.xIfIndex.xNetAddress)
1157  * from arp table index trees.
1158  */
1159 void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip)
1160 {
1161   struct mib_list_rootnode *at_rn, *next, *del_rn[5];
1162   struct mib_list_node *at_n, *del_n[5];
1163   s32_t arpidx[5];
1164   u8_t fc, tree, level, del_cnt;
1165
1166   snmp_netiftoifindex(ni, &arpidx[0]);
1167   snmp_iptooid(ip, &arpidx[1]);
1168
1169   for (tree = 0; tree < 2; tree++)
1170   {
1171     /* mark nodes for deletion */
1172     if (tree == 0)
1173     {
1174       at_rn = &arptree_root;
1175     }
1176     else
1177     {
1178       at_rn = &ipntomtree_root;
1179     }
1180     level = 0;
1181     del_cnt = 0;
1182     while ((level < 5) && (at_rn != NULL))
1183     {
1184       fc = snmp_mib_node_find(at_rn, arpidx[level], &at_n);
1185       if (fc == 0)
1186       {
1187         /* arpidx[level] does not exist */
1188         del_cnt = 0;
1189         at_rn = NULL;
1190       }
1191       else if (fc == 1)
1192       {
1193         del_rn[del_cnt] = at_rn;
1194         del_n[del_cnt] = at_n;
1195         del_cnt++;
1196         at_rn = (struct mib_list_rootnode*)(at_n->nptr);
1197       }
1198       else if (fc == 2)
1199       {
1200         /* reset delete (2 or more childs) */
1201         del_cnt = 0;
1202         at_rn = (struct mib_list_rootnode*)(at_n->nptr);
1203       }
1204       level++;
1205     }
1206     /* delete marked index nodes */
1207     while (del_cnt > 0)
1208     {
1209       del_cnt--;
1210
1211       at_rn = del_rn[del_cnt];
1212       at_n = del_n[del_cnt];
1213
1214       next = snmp_mib_node_delete(at_rn, at_n);
1215       if (next != NULL)
1216       {
1217         LWIP_ASSERT("next_count == 0",next->count == 0);
1218         snmp_mib_lrn_free(next);
1219       }
1220     }
1221   }
1222   /* disable getnext traversal on empty tables */
1223   if(arptree_root.count == 0) at.maxlength = 0;
1224   if(ipntomtree_root.count == 0) ipntomtable.maxlength = 0;
1225 }
1226
1227 void snmp_inc_ipinreceives(void)
1228 {
1229   ipinreceives++;
1230 }
1231
1232 void snmp_inc_ipinhdrerrors(void)
1233 {
1234   ipinhdrerrors++;
1235 }
1236
1237 void snmp_inc_ipinaddrerrors(void)
1238 {
1239   ipinaddrerrors++;
1240 }
1241
1242 void snmp_inc_ipforwdatagrams(void)
1243 {
1244   ipforwdatagrams++;
1245 }
1246
1247 void snmp_inc_ipinunknownprotos(void)
1248 {
1249   ipinunknownprotos++;
1250 }
1251
1252 void snmp_inc_ipindiscards(void)
1253 {
1254   ipindiscards++;
1255 }
1256
1257 void snmp_inc_ipindelivers(void)
1258 {
1259   ipindelivers++;
1260 }
1261
1262 void snmp_inc_ipoutrequests(void)
1263 {
1264   ipoutrequests++;
1265 }
1266
1267 void snmp_inc_ipoutdiscards(void)
1268 {
1269   ipoutdiscards++;
1270 }
1271
1272 void snmp_inc_ipoutnoroutes(void)
1273 {
1274   ipoutnoroutes++;
1275 }
1276
1277 void snmp_inc_ipreasmreqds(void)
1278 {
1279   ipreasmreqds++;
1280 }
1281
1282 void snmp_inc_ipreasmoks(void)
1283 {
1284   ipreasmoks++;
1285 }
1286
1287 void snmp_inc_ipreasmfails(void)
1288 {
1289   ipreasmfails++;
1290 }
1291
1292 void snmp_inc_ipfragoks(void)
1293 {
1294   ipfragoks++;
1295 }
1296
1297 void snmp_inc_ipfragfails(void)
1298 {
1299   ipfragfails++;
1300 }
1301
1302 void snmp_inc_ipfragcreates(void)
1303 {
1304   ipfragcreates++;
1305 }
1306
1307 void snmp_inc_iproutingdiscards(void)
1308 {
1309   iproutingdiscards++;
1310 }
1311
1312 /**
1313  * Inserts ipAddrTable indexes (.ipAdEntAddr)
1314  * into index tree.
1315  */
1316 void snmp_insert_ipaddridx_tree(struct netif *ni)
1317 {
1318   struct mib_list_rootnode *ipa_rn;
1319   struct mib_list_node *ipa_node;
1320   s32_t ipaddridx[4];
1321   u8_t level;
1322
1323   LWIP_ASSERT("ni != NULL", ni != NULL);
1324   snmp_iptooid(&ni->ip_addr, &ipaddridx[0]);
1325
1326   level = 0;
1327   ipa_rn = &ipaddrtree_root;
1328   while (level < 4)
1329   {
1330     ipa_node = NULL;
1331     snmp_mib_node_insert(ipa_rn, ipaddridx[level], &ipa_node);
1332     if ((level != 3) && (ipa_node != NULL))
1333     {
1334       if (ipa_node->nptr == NULL)
1335       {
1336         ipa_rn = snmp_mib_lrn_alloc();
1337         ipa_node->nptr = (struct mib_node*)ipa_rn;
1338         if (ipa_rn != NULL)
1339         {
1340           if (level == 2)
1341           {
1342             ipa_rn->get_object_def = ip_addrentry_get_object_def;
1343             ipa_rn->get_value = ip_addrentry_get_value;
1344             ipa_rn->set_test = noleafs_set_test;
1345             ipa_rn->set_value = noleafs_set_value;
1346           }
1347         }
1348         else
1349         {
1350           /* ipa_rn == NULL, malloc failure */
1351           LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_ipaddridx_tree() insert failed, mem full"));
1352           break;
1353         }
1354       }
1355       else
1356       {
1357         ipa_rn = (struct mib_list_rootnode*)ipa_node->nptr;
1358       }
1359     }
1360     level++;
1361   }
1362   /* enable getnext traversal on filled table */
1363   ipaddrtable.maxlength = 1;
1364 }
1365
1366 /**
1367  * Removes ipAddrTable indexes (.ipAdEntAddr)
1368  * from index tree.
1369  */
1370 void snmp_delete_ipaddridx_tree(struct netif *ni)
1371 {
1372   struct mib_list_rootnode *ipa_rn, *next, *del_rn[4];
1373   struct mib_list_node *ipa_n, *del_n[4];
1374   s32_t ipaddridx[4];
1375   u8_t fc, level, del_cnt;
1376
1377   LWIP_ASSERT("ni != NULL", ni != NULL);
1378   snmp_iptooid(&ni->ip_addr, &ipaddridx[0]);
1379
1380   /* mark nodes for deletion */
1381   level = 0;
1382   del_cnt = 0;
1383   ipa_rn = &ipaddrtree_root;
1384   while ((level < 4) && (ipa_rn != NULL))
1385   {
1386     fc = snmp_mib_node_find(ipa_rn, ipaddridx[level], &ipa_n);
1387     if (fc == 0)
1388     {
1389       /* ipaddridx[level] does not exist */
1390       del_cnt = 0;
1391       ipa_rn = NULL;
1392     }
1393     else if (fc == 1)
1394     {
1395       del_rn[del_cnt] = ipa_rn;
1396       del_n[del_cnt] = ipa_n;
1397       del_cnt++;
1398       ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr);
1399     }
1400     else if (fc == 2)
1401     {
1402       /* reset delete (2 or more childs) */
1403       del_cnt = 0;
1404       ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr);
1405     }
1406     level++;
1407   }
1408   /* delete marked index nodes */
1409   while (del_cnt > 0)
1410   {
1411     del_cnt--;
1412
1413     ipa_rn = del_rn[del_cnt];
1414     ipa_n = del_n[del_cnt];
1415
1416     next = snmp_mib_node_delete(ipa_rn, ipa_n);
1417     if (next != NULL)
1418     {
1419       LWIP_ASSERT("next_count == 0",next->count == 0);
1420       snmp_mib_lrn_free(next);
1421     }
1422   }
1423   /* disable getnext traversal on empty table */
1424   if (ipaddrtree_root.count == 0) ipaddrtable.maxlength = 0;
1425 }
1426
1427 /**
1428  * Inserts ipRouteTable indexes (.ipRouteDest)
1429  * into index tree.
1430  *
1431  * @param dflt non-zero for the default rte, zero for network rte
1432  * @param ni points to network interface for this rte
1433  *
1434  * @todo record sysuptime for _this_ route when it is installed
1435  *   (needed for ipRouteAge) in the netif.
1436  */
1437 void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni)
1438 {
1439   u8_t insert = 0;
1440   ip_addr_t dst;
1441
1442   if (dflt != 0)
1443   {
1444     /* the default route 0.0.0.0 */
1445     ip_addr_set_any(&dst);
1446     insert = 1;
1447   }
1448   else
1449   {
1450     /* route to the network address */
1451     ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask);
1452     /* exclude 0.0.0.0 network (reserved for default rte) */
1453     if (!ip_addr_isany(&dst)) {
1454       insert = 1;
1455     }
1456   }
1457   if (insert)
1458   {
1459     struct mib_list_rootnode *iprte_rn;
1460     struct mib_list_node *iprte_node;
1461     s32_t iprteidx[4];
1462     u8_t level;
1463
1464     snmp_iptooid(&dst, &iprteidx[0]);
1465     level = 0;
1466     iprte_rn = &iprtetree_root;
1467     while (level < 4)
1468     {
1469       iprte_node = NULL;
1470       snmp_mib_node_insert(iprte_rn, iprteidx[level], &iprte_node);
1471       if ((level != 3) && (iprte_node != NULL))
1472       {
1473         if (iprte_node->nptr == NULL)
1474         {
1475           iprte_rn = snmp_mib_lrn_alloc();
1476           iprte_node->nptr = (struct mib_node*)iprte_rn;
1477           if (iprte_rn != NULL)
1478           {
1479             if (level == 2)
1480             {
1481               iprte_rn->get_object_def = ip_rteentry_get_object_def;
1482               iprte_rn->get_value = ip_rteentry_get_value;
1483               iprte_rn->set_test = noleafs_set_test;
1484               iprte_rn->set_value = noleafs_set_value;
1485             }
1486           }
1487           else
1488           {
1489             /* iprte_rn == NULL, malloc failure */
1490             LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_iprteidx_tree() insert failed, mem full"));
1491             break;
1492           }
1493         }
1494         else
1495         {
1496           iprte_rn = (struct mib_list_rootnode*)iprte_node->nptr;
1497         }
1498       }
1499       level++;
1500     }
1501   }
1502   /* enable getnext traversal on filled table */
1503   iprtetable.maxlength = 1;
1504 }
1505
1506 /**
1507  * Removes ipRouteTable indexes (.ipRouteDest)
1508  * from index tree.
1509  *
1510  * @param dflt non-zero for the default rte, zero for network rte
1511  * @param ni points to network interface for this rte or NULL
1512  *   for default route to be removed.
1513  */
1514 void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni)
1515 {
1516   u8_t del = 0;
1517   ip_addr_t dst;
1518
1519   if (dflt != 0)
1520   {
1521     /* the default route 0.0.0.0 */
1522     ip_addr_set_any(&dst);
1523     del = 1;
1524   }
1525   else
1526   {
1527     /* route to the network address */
1528     ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask);
1529     /* exclude 0.0.0.0 network (reserved for default rte) */
1530     if (!ip_addr_isany(&dst)) {
1531       del = 1;
1532     }
1533   }
1534   if (del)
1535   {
1536     struct mib_list_rootnode *iprte_rn, *next, *del_rn[4];
1537     struct mib_list_node *iprte_n, *del_n[4];
1538     s32_t iprteidx[4];
1539     u8_t fc, level, del_cnt;
1540
1541     snmp_iptooid(&dst, &iprteidx[0]);
1542     /* mark nodes for deletion */
1543     level = 0;
1544     del_cnt = 0;
1545     iprte_rn = &iprtetree_root;
1546     while ((level < 4) && (iprte_rn != NULL))
1547     {
1548       fc = snmp_mib_node_find(iprte_rn, iprteidx[level], &iprte_n);
1549       if (fc == 0)
1550       {
1551         /* iprteidx[level] does not exist */
1552         del_cnt = 0;
1553         iprte_rn = NULL;
1554       }
1555       else if (fc == 1)
1556       {
1557         del_rn[del_cnt] = iprte_rn;
1558         del_n[del_cnt] = iprte_n;
1559         del_cnt++;
1560         iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr);
1561       }
1562       else if (fc == 2)
1563       {
1564         /* reset delete (2 or more childs) */
1565         del_cnt = 0;
1566         iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr);
1567       }
1568       level++;
1569     }
1570     /* delete marked index nodes */
1571     while (del_cnt > 0)
1572     {
1573       del_cnt--;
1574
1575       iprte_rn = del_rn[del_cnt];
1576       iprte_n = del_n[del_cnt];
1577
1578       next = snmp_mib_node_delete(iprte_rn, iprte_n);
1579       if (next != NULL)
1580       {
1581         LWIP_ASSERT("next_count == 0",next->count == 0);
1582         snmp_mib_lrn_free(next);
1583       }
1584     }
1585   }
1586   /* disable getnext traversal on empty table */
1587   if (iprtetree_root.count == 0) iprtetable.maxlength = 0;
1588 }
1589
1590
1591 void snmp_inc_icmpinmsgs(void)
1592 {
1593   icmpinmsgs++;
1594 }
1595
1596 void snmp_inc_icmpinerrors(void)
1597 {
1598   icmpinerrors++;
1599 }
1600
1601 void snmp_inc_icmpindestunreachs(void)
1602 {
1603   icmpindestunreachs++;
1604 }
1605
1606 void snmp_inc_icmpintimeexcds(void)
1607 {
1608   icmpintimeexcds++;
1609 }
1610
1611 void snmp_inc_icmpinparmprobs(void)
1612 {
1613   icmpinparmprobs++;
1614 }
1615
1616 void snmp_inc_icmpinsrcquenchs(void)
1617 {
1618   icmpinsrcquenchs++;
1619 }
1620
1621 void snmp_inc_icmpinredirects(void)
1622 {
1623   icmpinredirects++;
1624 }
1625
1626 void snmp_inc_icmpinechos(void)
1627 {
1628   icmpinechos++;
1629 }
1630
1631 void snmp_inc_icmpinechoreps(void)
1632 {
1633   icmpinechoreps++;
1634 }
1635
1636 void snmp_inc_icmpintimestamps(void)
1637 {
1638   icmpintimestamps++;
1639 }
1640
1641 void snmp_inc_icmpintimestampreps(void)
1642 {
1643   icmpintimestampreps++;
1644 }
1645
1646 void snmp_inc_icmpinaddrmasks(void)
1647 {
1648   icmpinaddrmasks++;
1649 }
1650
1651 void snmp_inc_icmpinaddrmaskreps(void)
1652 {
1653   icmpinaddrmaskreps++;
1654 }
1655
1656 void snmp_inc_icmpoutmsgs(void)
1657 {
1658   icmpoutmsgs++;
1659 }
1660
1661 void snmp_inc_icmpouterrors(void)
1662 {
1663   icmpouterrors++;
1664 }
1665
1666 void snmp_inc_icmpoutdestunreachs(void)
1667 {
1668   icmpoutdestunreachs++;
1669 }
1670
1671 void snmp_inc_icmpouttimeexcds(void)
1672 {
1673   icmpouttimeexcds++;
1674 }
1675
1676 void snmp_inc_icmpoutparmprobs(void)
1677 {
1678   icmpoutparmprobs++;
1679 }
1680
1681 void snmp_inc_icmpoutsrcquenchs(void)
1682 {
1683   icmpoutsrcquenchs++;
1684 }
1685
1686 void snmp_inc_icmpoutredirects(void)
1687 {
1688   icmpoutredirects++;
1689 }
1690
1691 void snmp_inc_icmpoutechos(void)
1692 {
1693   icmpoutechos++;
1694 }
1695
1696 void snmp_inc_icmpoutechoreps(void)
1697 {
1698   icmpoutechoreps++;
1699 }
1700
1701 void snmp_inc_icmpouttimestamps(void)
1702 {
1703   icmpouttimestamps++;
1704 }
1705
1706 void snmp_inc_icmpouttimestampreps(void)
1707 {
1708   icmpouttimestampreps++;
1709 }
1710
1711 void snmp_inc_icmpoutaddrmasks(void)
1712 {
1713   icmpoutaddrmasks++;
1714 }
1715
1716 void snmp_inc_icmpoutaddrmaskreps(void)
1717 {
1718   icmpoutaddrmaskreps++;
1719 }
1720
1721 void snmp_inc_tcpactiveopens(void)
1722 {
1723   tcpactiveopens++;
1724 }
1725
1726 void snmp_inc_tcppassiveopens(void)
1727 {
1728   tcppassiveopens++;
1729 }
1730
1731 void snmp_inc_tcpattemptfails(void)
1732 {
1733   tcpattemptfails++;
1734 }
1735
1736 void snmp_inc_tcpestabresets(void)
1737 {
1738   tcpestabresets++;
1739 }
1740
1741 void snmp_inc_tcpinsegs(void)
1742 {
1743   tcpinsegs++;
1744 }
1745
1746 void snmp_inc_tcpoutsegs(void)
1747 {
1748   tcpoutsegs++;
1749 }
1750
1751 void snmp_inc_tcpretranssegs(void)
1752 {
1753   tcpretranssegs++;
1754 }
1755
1756 void snmp_inc_tcpinerrs(void)
1757 {
1758   tcpinerrs++;
1759 }
1760
1761 void snmp_inc_tcpoutrsts(void)
1762 {
1763   tcpoutrsts++;
1764 }
1765
1766 void snmp_inc_udpindatagrams(void)
1767 {
1768   udpindatagrams++;
1769 }
1770
1771 void snmp_inc_udpnoports(void)
1772 {
1773   udpnoports++;
1774 }
1775
1776 void snmp_inc_udpinerrors(void)
1777 {
1778   udpinerrors++;
1779 }
1780
1781 void snmp_inc_udpoutdatagrams(void)
1782 {
1783   udpoutdatagrams++;
1784 }
1785
1786 /**
1787  * Inserts udpTable indexes (.udpLocalAddress.udpLocalPort)
1788  * into index tree.
1789  */
1790 void snmp_insert_udpidx_tree(struct udp_pcb *pcb)
1791 {
1792   struct mib_list_rootnode *udp_rn;
1793   struct mib_list_node *udp_node;
1794   s32_t udpidx[5];
1795   u8_t level;
1796
1797   LWIP_ASSERT("pcb != NULL", pcb != NULL);
1798   snmp_iptooid(&pcb->local_ip, &udpidx[0]);
1799   udpidx[4] = pcb->local_port;
1800
1801   udp_rn = &udp_root;
1802   for (level = 0; level < 5; level++)
1803   {
1804     udp_node = NULL;
1805     snmp_mib_node_insert(udp_rn, udpidx[level], &udp_node);
1806     if ((level != 4) && (udp_node != NULL))
1807     {
1808       if (udp_node->nptr == NULL)
1809       {
1810         udp_rn = snmp_mib_lrn_alloc();
1811         udp_node->nptr = (struct mib_node*)udp_rn;
1812         if (udp_rn != NULL)
1813         {
1814           if (level == 3)
1815           {
1816             udp_rn->get_object_def = udpentry_get_object_def;
1817             udp_rn->get_value = udpentry_get_value;
1818             udp_rn->set_test = noleafs_set_test;
1819             udp_rn->set_value = noleafs_set_value;
1820           }
1821         }
1822         else
1823         {
1824           /* udp_rn == NULL, malloc failure */
1825           LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_udpidx_tree() insert failed, mem full"));
1826           break;
1827         }
1828       }
1829       else
1830       {
1831         udp_rn = (struct mib_list_rootnode*)udp_node->nptr;
1832       }
1833     }
1834   }
1835   udptable.maxlength = 1;
1836 }
1837
1838 /**
1839  * Removes udpTable indexes (.udpLocalAddress.udpLocalPort)
1840  * from index tree.
1841  */
1842 void snmp_delete_udpidx_tree(struct udp_pcb *pcb)
1843 {
1844   struct udp_pcb *npcb;
1845   struct mib_list_rootnode *udp_rn, *next, *del_rn[5];
1846   struct mib_list_node *udp_n, *del_n[5];
1847   s32_t udpidx[5];
1848   u8_t bindings, fc, level, del_cnt;
1849
1850   LWIP_ASSERT("pcb != NULL", pcb != NULL);
1851   snmp_iptooid(&pcb->local_ip, &udpidx[0]);
1852   udpidx[4] = pcb->local_port;
1853
1854   /* count PCBs for a given binding
1855      (e.g. when reusing ports or for temp output PCBs) */
1856   bindings = 0;
1857   npcb = udp_pcbs;
1858   while ((npcb != NULL))
1859   {
1860     if (ip_addr_cmp(&npcb->local_ip, &pcb->local_ip) &&
1861         (npcb->local_port == udpidx[4]))
1862     {
1863       bindings++;
1864     }
1865     npcb = npcb->next;
1866   }
1867   if (bindings == 1)
1868   {
1869     /* selectively remove */
1870     /* mark nodes for deletion */
1871     level = 0;
1872     del_cnt = 0;
1873     udp_rn = &udp_root;
1874     while ((level < 5) && (udp_rn != NULL))
1875     {
1876       fc = snmp_mib_node_find(udp_rn, udpidx[level], &udp_n);
1877       if (fc == 0)
1878       {
1879         /* udpidx[level] does not exist */
1880         del_cnt = 0;
1881         udp_rn = NULL;
1882       }
1883       else if (fc == 1)
1884       {
1885         del_rn[del_cnt] = udp_rn;
1886         del_n[del_cnt] = udp_n;
1887         del_cnt++;
1888         udp_rn = (struct mib_list_rootnode*)(udp_n->nptr);
1889       }
1890       else if (fc == 2)
1891       {
1892         /* reset delete (2 or more childs) */
1893         del_cnt = 0;
1894         udp_rn = (struct mib_list_rootnode*)(udp_n->nptr);
1895       }
1896       level++;
1897     }
1898     /* delete marked index nodes */
1899     while (del_cnt > 0)
1900     {
1901       del_cnt--;
1902
1903       udp_rn = del_rn[del_cnt];
1904       udp_n = del_n[del_cnt];
1905
1906       next = snmp_mib_node_delete(udp_rn, udp_n);
1907       if (next != NULL)
1908       {
1909         LWIP_ASSERT("next_count == 0",next->count == 0);
1910         snmp_mib_lrn_free(next);
1911       }
1912     }
1913   }
1914   /* disable getnext traversal on empty table */
1915   if (udp_root.count == 0) udptable.maxlength = 0;
1916 }
1917
1918
1919 void snmp_inc_snmpinpkts(void)
1920 {
1921   snmpinpkts++;
1922 }
1923
1924 void snmp_inc_snmpoutpkts(void)
1925 {
1926   snmpoutpkts++;
1927 }
1928
1929 void snmp_inc_snmpinbadversions(void)
1930 {
1931   snmpinbadversions++;
1932 }
1933
1934 void snmp_inc_snmpinbadcommunitynames(void)
1935 {
1936   snmpinbadcommunitynames++;
1937 }
1938
1939 void snmp_inc_snmpinbadcommunityuses(void)
1940 {
1941   snmpinbadcommunityuses++;
1942 }
1943
1944 void snmp_inc_snmpinasnparseerrs(void)
1945 {
1946   snmpinasnparseerrs++;
1947 }
1948
1949 void snmp_inc_snmpintoobigs(void)
1950 {
1951   snmpintoobigs++;
1952 }
1953
1954 void snmp_inc_snmpinnosuchnames(void)
1955 {
1956   snmpinnosuchnames++;
1957 }
1958
1959 void snmp_inc_snmpinbadvalues(void)
1960 {
1961   snmpinbadvalues++;
1962 }
1963
1964 void snmp_inc_snmpinreadonlys(void)
1965 {
1966   snmpinreadonlys++;
1967 }
1968
1969 void snmp_inc_snmpingenerrs(void)
1970 {
1971   snmpingenerrs++;
1972 }
1973
1974 void snmp_add_snmpintotalreqvars(u8_t value)
1975 {
1976   snmpintotalreqvars += value;
1977 }
1978
1979 void snmp_add_snmpintotalsetvars(u8_t value)
1980 {
1981   snmpintotalsetvars += value;
1982 }
1983
1984 void snmp_inc_snmpingetrequests(void)
1985 {
1986   snmpingetrequests++;
1987 }
1988
1989 void snmp_inc_snmpingetnexts(void)
1990 {
1991   snmpingetnexts++;
1992 }
1993
1994 void snmp_inc_snmpinsetrequests(void)
1995 {
1996   snmpinsetrequests++;
1997 }
1998
1999 void snmp_inc_snmpingetresponses(void)
2000 {
2001   snmpingetresponses++;
2002 }
2003
2004 void snmp_inc_snmpintraps(void)
2005 {
2006   snmpintraps++;
2007 }
2008
2009 void snmp_inc_snmpouttoobigs(void)
2010 {
2011   snmpouttoobigs++;
2012 }
2013
2014 void snmp_inc_snmpoutnosuchnames(void)
2015 {
2016   snmpoutnosuchnames++;
2017 }
2018
2019 void snmp_inc_snmpoutbadvalues(void)
2020 {
2021   snmpoutbadvalues++;
2022 }
2023
2024 void snmp_inc_snmpoutgenerrs(void)
2025 {
2026   snmpoutgenerrs++;
2027 }
2028
2029 void snmp_inc_snmpoutgetrequests(void)
2030 {
2031   snmpoutgetrequests++;
2032 }
2033
2034 void snmp_inc_snmpoutgetnexts(void)
2035 {
2036   snmpoutgetnexts++;
2037 }
2038
2039 void snmp_inc_snmpoutsetrequests(void)
2040 {
2041   snmpoutsetrequests++;
2042 }
2043
2044 void snmp_inc_snmpoutgetresponses(void)
2045 {
2046   snmpoutgetresponses++;
2047 }
2048
2049 void snmp_inc_snmpouttraps(void)
2050 {
2051   snmpouttraps++;
2052 }
2053
2054 void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid)
2055 {
2056   *oid = &snmpgrp_id;
2057 }
2058
2059 void snmp_set_snmpenableauthentraps(u8_t *value)
2060 {
2061   if (value != NULL)
2062   {
2063     snmpenableauthentraps_ptr = value;
2064   }
2065 }
2066
2067 void snmp_get_snmpenableauthentraps(u8_t *value)
2068 {
2069   *value = *snmpenableauthentraps_ptr;
2070 }
2071
2072 void
2073 noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
2074 {
2075   LWIP_UNUSED_ARG(ident_len);
2076   LWIP_UNUSED_ARG(ident);
2077   od->instance = MIB_OBJECT_NONE;
2078 }
2079
2080 void
2081 noleafs_get_value(struct obj_def *od, u16_t len, void *value)
2082 {
2083   LWIP_UNUSED_ARG(od);
2084   LWIP_UNUSED_ARG(len);
2085   LWIP_UNUSED_ARG(value);
2086 }
2087
2088 u8_t
2089 noleafs_set_test(struct obj_def *od, u16_t len, void *value)
2090 {
2091   LWIP_UNUSED_ARG(od);
2092   LWIP_UNUSED_ARG(len);
2093   LWIP_UNUSED_ARG(value);
2094   /* can't set */
2095   return 0;
2096 }
2097
2098 void
2099 noleafs_set_value(struct obj_def *od, u16_t len, void *value)
2100 {
2101   LWIP_UNUSED_ARG(od);
2102   LWIP_UNUSED_ARG(len);
2103   LWIP_UNUSED_ARG(value);
2104 }
2105
2106
2107 /**
2108  * Returns systems object definitions.
2109  *
2110  * @param ident_len the address length (2)
2111  * @param ident points to objectname.0 (object id trailer)
2112  * @param od points to object definition.
2113  */
2114 static void
2115 system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
2116 {
2117   u8_t id;
2118
2119   /* return to object name, adding index depth (1) */
2120   ident_len += 1;
2121   ident -= 1;
2122   if (ident_len == 2)
2123   {
2124     od->id_inst_len = ident_len;
2125     od->id_inst_ptr = ident;
2126
2127     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
2128     id = (u8_t)ident[0];
2129     LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id));
2130     switch (id)
2131     {
2132       case 1: /* sysDescr */
2133         od->instance = MIB_OBJECT_SCALAR;
2134         od->access = MIB_OBJECT_READ_ONLY;
2135         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2136         od->v_len = *sysdescr_len_ptr;
2137         break;
2138       case 2: /* sysObjectID */
2139         od->instance = MIB_OBJECT_SCALAR;
2140         od->access = MIB_OBJECT_READ_ONLY;
2141         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID);
2142         od->v_len = sysobjid.len * sizeof(s32_t);
2143         break;
2144       case 3: /* sysUpTime */
2145         od->instance = MIB_OBJECT_SCALAR;
2146         od->access = MIB_OBJECT_READ_ONLY;
2147         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS);
2148         od->v_len = sizeof(u32_t);
2149         break;
2150       case 4: /* sysContact */
2151         od->instance = MIB_OBJECT_SCALAR;
2152         od->access = MIB_OBJECT_READ_WRITE;
2153         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2154         od->v_len = *syscontact_len_ptr;
2155         break;
2156       case 5: /* sysName */
2157         od->instance = MIB_OBJECT_SCALAR;
2158         od->access = MIB_OBJECT_READ_WRITE;
2159         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2160         od->v_len = *sysname_len_ptr;
2161         break;
2162       case 6: /* sysLocation */
2163         od->instance = MIB_OBJECT_SCALAR;
2164         od->access = MIB_OBJECT_READ_WRITE;
2165         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2166         od->v_len = *syslocation_len_ptr;
2167         break;
2168       case 7: /* sysServices */
2169         od->instance = MIB_OBJECT_SCALAR;
2170         od->access = MIB_OBJECT_READ_ONLY;
2171         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2172         od->v_len = sizeof(s32_t);
2173         break;
2174       default:
2175         LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no such object\n"));
2176         od->instance = MIB_OBJECT_NONE;
2177         break;
2178     };
2179   }
2180   else
2181   {
2182     LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar\n"));
2183     od->instance = MIB_OBJECT_NONE;
2184   }
2185 }
2186
2187 /**
2188  * Returns system object value.
2189  *
2190  * @param ident_len the address length (2)
2191  * @param ident points to objectname.0 (object id trailer)
2192  * @param len return value space (in bytes)
2193  * @param value points to (varbind) space to copy value into.
2194  */
2195 static void
2196 system_get_value(struct obj_def *od, u16_t len, void *value)
2197 {
2198   u8_t id;
2199
2200   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2201   id = (u8_t)od->id_inst_ptr[0];
2202   switch (id)
2203   {
2204     case 1: /* sysDescr */
2205       ocstrncpy((u8_t*)value, sysdescr_ptr, len);
2206       break;
2207     case 2: /* sysObjectID */
2208       objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t)));
2209       break;
2210     case 3: /* sysUpTime */
2211       {
2212         snmp_get_sysuptime((u32_t*)value);
2213       }
2214       break;
2215     case 4: /* sysContact */
2216       ocstrncpy((u8_t*)value, syscontact_ptr, len);
2217       break;
2218     case 5: /* sysName */
2219       ocstrncpy((u8_t*)value, sysname_ptr, len);
2220       break;
2221     case 6: /* sysLocation */
2222       ocstrncpy((u8_t*)value, syslocation_ptr, len);
2223       break;
2224     case 7: /* sysServices */
2225       {
2226         s32_t *sint_ptr = (s32_t*)value;
2227         *sint_ptr = sysservices;
2228       }
2229       break;
2230   };
2231 }
2232
2233 static u8_t
2234 system_set_test(struct obj_def *od, u16_t len, void *value)
2235 {
2236   u8_t id, set_ok;
2237
2238   LWIP_UNUSED_ARG(value);
2239   set_ok = 0;
2240   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2241   id = (u8_t)od->id_inst_ptr[0];
2242   switch (id)
2243   {
2244     case 4: /* sysContact */
2245       if ((syscontact_ptr != syscontact_default) &&
2246           (len <= 255))
2247       {
2248         set_ok = 1;
2249       }
2250       break;
2251     case 5: /* sysName */
2252       if ((sysname_ptr != sysname_default) &&
2253           (len <= 255))
2254       {
2255         set_ok = 1;
2256       }
2257       break;
2258     case 6: /* sysLocation */
2259       if ((syslocation_ptr != syslocation_default) &&
2260           (len <= 255))
2261       {
2262         set_ok = 1;
2263       }
2264       break;
2265   };
2266   return set_ok;
2267 }
2268
2269 static void
2270 system_set_value(struct obj_def *od, u16_t len, void *value)
2271 {
2272   u8_t id;
2273
2274   LWIP_ASSERT("invalid len", len <= 0xff);
2275   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2276   id = (u8_t)od->id_inst_ptr[0];
2277   switch (id)
2278   {
2279     case 4: /* sysContact */
2280       ocstrncpy(syscontact_ptr, (u8_t*)value, len);
2281       *syscontact_len_ptr = (u8_t)len;
2282       break;
2283     case 5: /* sysName */
2284       ocstrncpy(sysname_ptr, (u8_t*)value, len);
2285       *sysname_len_ptr = (u8_t)len;
2286       break;
2287     case 6: /* sysLocation */
2288       ocstrncpy(syslocation_ptr, (u8_t*)value, len);
2289       *syslocation_len_ptr = (u8_t)len;
2290       break;
2291   };
2292 }
2293
2294 /**
2295  * Returns interfaces.ifnumber object definition.
2296  *
2297  * @param ident_len the address length (2)
2298  * @param ident points to objectname.index
2299  * @param od points to object definition.
2300  */
2301 static void
2302 interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
2303 {
2304   /* return to object name, adding index depth (1) */
2305   ident_len += 1;
2306   ident -= 1;
2307   if (ident_len == 2)
2308   {
2309     od->id_inst_len = ident_len;
2310     od->id_inst_ptr = ident;
2311
2312     od->instance = MIB_OBJECT_SCALAR;
2313     od->access = MIB_OBJECT_READ_ONLY;
2314     od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2315     od->v_len = sizeof(s32_t);
2316   }
2317   else
2318   {
2319     LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar\n"));
2320     od->instance = MIB_OBJECT_NONE;
2321   }
2322 }
2323
2324 /**
2325  * Returns interfaces.ifnumber object value.
2326  *
2327  * @param ident_len the address length (2)
2328  * @param ident points to objectname.0 (object id trailer)
2329  * @param len return value space (in bytes)
2330  * @param value points to (varbind) space to copy value into.
2331  */
2332 static void
2333 interfaces_get_value(struct obj_def *od, u16_t len, void *value)
2334 {
2335   LWIP_UNUSED_ARG(len);
2336   if (od->id_inst_ptr[0] == 1)
2337   {
2338     s32_t *sint_ptr = (s32_t*)value;
2339     *sint_ptr = iflist_root.count;
2340   }
2341 }
2342
2343 /**
2344  * Returns ifentry object definitions.
2345  *
2346  * @param ident_len the address length (2)
2347  * @param ident points to objectname.index
2348  * @param od points to object definition.
2349  */
2350 static void
2351 ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
2352 {
2353   u8_t id;
2354
2355   /* return to object name, adding index depth (1) */
2356   ident_len += 1;
2357   ident -= 1;
2358   if (ident_len == 2)
2359   {
2360     od->id_inst_len = ident_len;
2361     od->id_inst_ptr = ident;
2362
2363     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
2364     id = (u8_t)ident[0];
2365     LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id));
2366     switch (id)
2367     {
2368       case 1: /* ifIndex */
2369       case 3: /* ifType */
2370       case 4: /* ifMtu */
2371       case 8: /* ifOperStatus */
2372         od->instance = MIB_OBJECT_TAB;
2373         od->access = MIB_OBJECT_READ_ONLY;
2374         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2375         od->v_len = sizeof(s32_t);
2376         break;
2377       case 2: /* ifDescr */
2378         od->instance = MIB_OBJECT_TAB;
2379         od->access = MIB_OBJECT_READ_ONLY;
2380         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2381         /** @todo this should be some sort of sizeof(struct netif.name) */
2382         od->v_len = 2;
2383         break;
2384       case 5: /* ifSpeed */
2385       case 21: /* ifOutQLen */
2386         od->instance = MIB_OBJECT_TAB;
2387         od->access = MIB_OBJECT_READ_ONLY;
2388         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE);
2389         od->v_len = sizeof(u32_t);
2390         break;
2391       case 6: /* ifPhysAddress */
2392         {
2393           struct netif *netif;
2394
2395           snmp_ifindextonetif(ident[1], &netif);
2396           od->instance = MIB_OBJECT_TAB;
2397           od->access = MIB_OBJECT_READ_ONLY;
2398           od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2399           od->v_len = netif->hwaddr_len;
2400         }
2401         break;
2402       case 7: /* ifAdminStatus */
2403         od->instance = MIB_OBJECT_TAB;
2404         od->access = MIB_OBJECT_READ_WRITE;
2405         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2406         od->v_len = sizeof(s32_t);
2407         break;
2408       case 9: /* ifLastChange */
2409         od->instance = MIB_OBJECT_TAB;
2410         od->access = MIB_OBJECT_READ_ONLY;
2411         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS);
2412         od->v_len = sizeof(u32_t);
2413         break;
2414       case 10: /* ifInOctets */
2415       case 11: /* ifInUcastPkts */
2416       case 12: /* ifInNUcastPkts */
2417       case 13: /* ifInDiscarts */
2418       case 14: /* ifInErrors */
2419       case 15: /* ifInUnkownProtos */
2420       case 16: /* ifOutOctets */
2421       case 17: /* ifOutUcastPkts */
2422       case 18: /* ifOutNUcastPkts */
2423       case 19: /* ifOutDiscarts */
2424       case 20: /* ifOutErrors */
2425         od->instance = MIB_OBJECT_TAB;
2426         od->access = MIB_OBJECT_READ_ONLY;
2427         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER);
2428         od->v_len = sizeof(u32_t);
2429         break;
2430       case 22: /* ifSpecific */
2431         /** @note returning zeroDotZero (0.0) no media specific MIB support */
2432         od->instance = MIB_OBJECT_TAB;
2433         od->access = MIB_OBJECT_READ_ONLY;
2434         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID);
2435         od->v_len = ifspecific.len * sizeof(s32_t);
2436         break;
2437       default:
2438         LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no such object\n"));
2439         od->instance = MIB_OBJECT_NONE;
2440         break;
2441     };
2442   }
2443   else
2444   {
2445     LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar\n"));
2446     od->instance = MIB_OBJECT_NONE;
2447   }
2448 }
2449
2450 /**
2451  * Returns ifentry object value.
2452  *
2453  * @param ident_len the address length (2)
2454  * @param ident points to objectname.0 (object id trailer)
2455  * @param len return value space (in bytes)
2456  * @param value points to (varbind) space to copy value into.
2457  */
2458 static void
2459 ifentry_get_value(struct obj_def *od, u16_t len, void *value)
2460 {
2461   struct netif *netif;
2462   u8_t id;
2463
2464   snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
2465   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2466   id = (u8_t)od->id_inst_ptr[0];
2467   switch (id)
2468   {
2469     case 1: /* ifIndex */
2470       {
2471         s32_t *sint_ptr = (s32_t*)value;
2472         *sint_ptr = od->id_inst_ptr[1];
2473       }
2474       break;
2475     case 2: /* ifDescr */
2476       ocstrncpy((u8_t*)value, (u8_t*)netif->name, len);
2477       break;
2478     case 3: /* ifType */
2479       {
2480         s32_t *sint_ptr = (s32_t*)value;
2481         *sint_ptr = netif->link_type;
2482       }
2483       break;
2484     case 4: /* ifMtu */
2485       {
2486         s32_t *sint_ptr = (s32_t*)value;
2487         *sint_ptr = netif->mtu;
2488       }
2489       break;
2490     case 5: /* ifSpeed */
2491       {
2492         u32_t *uint_ptr = (u32_t*)value;
2493         *uint_ptr = netif->link_speed;
2494       }
2495       break;
2496     case 6: /* ifPhysAddress */
2497       ocstrncpy((u8_t*)value, netif->hwaddr, len);
2498       break;
2499     case 7: /* ifAdminStatus */
2500       {
2501         s32_t *sint_ptr = (s32_t*)value;
2502         if (netif_is_up(netif))
2503         {
2504           if (netif_is_link_up(netif))
2505           {
2506             *sint_ptr = 1; /* up */
2507           }
2508           else
2509           {
2510             *sint_ptr = 7; /* lowerLayerDown */
2511           }
2512         }
2513         else
2514         {
2515           *sint_ptr = 2; /* down */
2516         }
2517       }
2518       break;
2519     case 8: /* ifOperStatus */
2520       {
2521         s32_t *sint_ptr = (s32_t*)value;
2522         if (netif_is_up(netif))
2523         {
2524           *sint_ptr = 1;
2525         }
2526         else
2527         {
2528           *sint_ptr = 2;
2529         }
2530       }
2531       break;
2532     case 9: /* ifLastChange */
2533       {
2534         u32_t *uint_ptr = (u32_t*)value;
2535         *uint_ptr = netif->ts;
2536       }
2537       break;
2538     case 10: /* ifInOctets */
2539       {
2540         u32_t *uint_ptr = (u32_t*)value;
2541         *uint_ptr = netif->ifinoctets;
2542       }
2543       break;
2544     case 11: /* ifInUcastPkts */
2545       {
2546         u32_t *uint_ptr = (u32_t*)value;
2547         *uint_ptr = netif->ifinucastpkts;
2548       }
2549       break;
2550     case 12: /* ifInNUcastPkts */
2551       {
2552         u32_t *uint_ptr = (u32_t*)value;
2553         *uint_ptr = netif->ifinnucastpkts;
2554       }
2555       break;
2556     case 13: /* ifInDiscarts */
2557       {
2558         u32_t *uint_ptr = (u32_t*)value;
2559         *uint_ptr = netif->ifindiscards;
2560       }
2561       break;
2562     case 14: /* ifInErrors */
2563     case 15: /* ifInUnkownProtos */
2564       /** @todo add these counters! */
2565       {
2566         u32_t *uint_ptr = (u32_t*)value;
2567         *uint_ptr = 0;
2568       }
2569       break;
2570     case 16: /* ifOutOctets */
2571       {
2572         u32_t *uint_ptr = (u32_t*)value;
2573         *uint_ptr = netif->ifoutoctets;
2574       }
2575       break;
2576     case 17: /* ifOutUcastPkts */
2577       {
2578         u32_t *uint_ptr = (u32_t*)value;
2579         *uint_ptr = netif->ifoutucastpkts;
2580       }
2581       break;
2582     case 18: /* ifOutNUcastPkts */
2583       {
2584         u32_t *uint_ptr = (u32_t*)value;
2585         *uint_ptr = netif->ifoutnucastpkts;
2586       }
2587       break;
2588     case 19: /* ifOutDiscarts */
2589       {
2590         u32_t *uint_ptr = (u32_t*)value;
2591         *uint_ptr = netif->ifoutdiscards;
2592       }
2593       break;
2594     case 20: /* ifOutErrors */
2595        /** @todo add this counter! */
2596       {
2597         u32_t *uint_ptr = (u32_t*)value;
2598         *uint_ptr = 0;
2599       }
2600       break;
2601     case 21: /* ifOutQLen */
2602       /** @todo figure out if this must be 0 (no queue) or 1? */
2603       {
2604         u32_t *uint_ptr = (u32_t*)value;
2605         *uint_ptr = 0;
2606       }
2607       break;
2608     case 22: /* ifSpecific */
2609       objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t)));
2610       break;
2611   };
2612 }
2613
2614 #if !SNMP_SAFE_REQUESTS
2615 static u8_t
2616 ifentry_set_test(struct obj_def *od, u16_t len, void *value)
2617 {
2618   struct netif *netif;
2619   u8_t id, set_ok;
2620   LWIP_UNUSED_ARG(len);
2621
2622   set_ok = 0;
2623   snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
2624   id = (u8_t)od->id_inst_ptr[0];
2625   switch (id)
2626   {
2627     case 7: /* ifAdminStatus */
2628       {
2629         s32_t *sint_ptr = (s32_t*)value;
2630         if (*sint_ptr == 1 || *sint_ptr == 2)
2631           set_ok = 1;
2632       }
2633       break;
2634   }
2635   return set_ok;
2636 }
2637
2638 static void
2639 ifentry_set_value(struct obj_def *od, u16_t len, void *value)
2640 {
2641   struct netif *netif;
2642   u8_t id;
2643   LWIP_UNUSED_ARG(len);
2644
2645   snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
2646   id = (u8_t)od->id_inst_ptr[0];
2647   switch (id)
2648   {
2649     case 7: /* ifAdminStatus */
2650       {
2651         s32_t *sint_ptr = (s32_t*)value;
2652         if (*sint_ptr == 1)
2653         {
2654           netif_set_up(netif);
2655         }
2656         else if (*sint_ptr == 2)
2657         {
2658           netif_set_down(netif);
2659          }
2660       }
2661       break;
2662   }
2663 }
2664 #endif /* SNMP_SAFE_REQUESTS */
2665
2666 /**
2667  * Returns atentry object definitions.
2668  *
2669  * @param ident_len the address length (6)
2670  * @param ident points to objectname.atifindex.atnetaddress
2671  * @param od points to object definition.
2672  */
2673 static void
2674 atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
2675 {
2676   /* return to object name, adding index depth (5) */
2677   ident_len += 5;
2678   ident -= 5;
2679
2680   if (ident_len == 6)
2681   {
2682     od->id_inst_len = ident_len;
2683     od->id_inst_ptr = ident;
2684
2685     switch (ident[0])
2686     {
2687       case 1: /* atIfIndex */
2688         od->instance = MIB_OBJECT_TAB;
2689         od->access = MIB_OBJECT_READ_WRITE;
2690         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2691         od->v_len = sizeof(s32_t);
2692         break;
2693       case 2: /* atPhysAddress */
2694         od->instance = MIB_OBJECT_TAB;
2695         od->access = MIB_OBJECT_READ_WRITE;
2696         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
2697         od->v_len = 6; /** @todo try to use netif::hwaddr_len */
2698         break;
2699       case 3: /* atNetAddress */
2700         od->instance = MIB_OBJECT_TAB;
2701         od->access = MIB_OBJECT_READ_WRITE;
2702         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR);
2703         od->v_len = 4;
2704         break;
2705       default:
2706         LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no such object\n"));
2707         od->instance = MIB_OBJECT_NONE;
2708         break;
2709     }
2710   }
2711   else
2712   {
2713     LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no scalar\n"));
2714     od->instance = MIB_OBJECT_NONE;
2715   }
2716 }
2717
2718 static void
2719 atentry_get_value(struct obj_def *od, u16_t len, void *value)
2720 {
2721 #if LWIP_ARP
2722   u8_t id;
2723   struct eth_addr* ethaddr_ret;
2724   ip_addr_t* ipaddr_ret;
2725 #endif /* LWIP_ARP */
2726   ip_addr_t ip;
2727   struct netif *netif;
2728
2729   LWIP_UNUSED_ARG(len);
2730   LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */
2731
2732   snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
2733   snmp_oidtoip(&od->id_inst_ptr[2], &ip);
2734
2735 #if LWIP_ARP /** @todo implement a netif_find_addr */
2736   if (etharp_find_addr(netif, &ip, &ethaddr_ret, &ipaddr_ret) > -1)
2737   {
2738     LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2739     id = (u8_t)od->id_inst_ptr[0];
2740     switch (id)
2741     {
2742       case 1: /* atIfIndex */
2743         {
2744           s32_t *sint_ptr = (s32_t*)value;
2745           *sint_ptr = od->id_inst_ptr[1];
2746         }
2747         break;
2748       case 2: /* atPhysAddress */
2749         {
2750           struct eth_addr *dst = (struct eth_addr*)value;
2751
2752           *dst = *ethaddr_ret;
2753         }
2754         break;
2755       case 3: /* atNetAddress */
2756         {
2757           ip_addr_t *dst = (ip_addr_t*)value;
2758
2759           *dst = *ipaddr_ret;
2760         }
2761         break;
2762     }
2763   }
2764 #endif /* LWIP_ARP */
2765 }
2766
2767 static void
2768 ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
2769 {
2770   u8_t id;
2771
2772   /* return to object name, adding index depth (1) */
2773   ident_len += 1;
2774   ident -= 1;
2775   if (ident_len == 2)
2776   {
2777     od->id_inst_len = ident_len;
2778     od->id_inst_ptr = ident;
2779
2780     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
2781     id = (u8_t)ident[0];
2782     LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id));
2783     switch (id)
2784     {
2785       case 1: /* ipForwarding */
2786       case 2: /* ipDefaultTTL */
2787         od->instance = MIB_OBJECT_SCALAR;
2788         od->access = MIB_OBJECT_READ_WRITE;
2789         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2790         od->v_len = sizeof(s32_t);
2791         break;
2792       case 3: /* ipInReceives */
2793       case 4: /* ipInHdrErrors */
2794       case 5: /* ipInAddrErrors */
2795       case 6: /* ipForwDatagrams */
2796       case 7: /* ipInUnknownProtos */
2797       case 8: /* ipInDiscards */
2798       case 9: /* ipInDelivers */
2799       case 10: /* ipOutRequests */
2800       case 11: /* ipOutDiscards */
2801       case 12: /* ipOutNoRoutes */
2802       case 14: /* ipReasmReqds */
2803       case 15: /* ipReasmOKs */
2804       case 16: /* ipReasmFails */
2805       case 17: /* ipFragOKs */
2806       case 18: /* ipFragFails */
2807       case 19: /* ipFragCreates */
2808       case 23: /* ipRoutingDiscards */
2809         od->instance = MIB_OBJECT_SCALAR;
2810         od->access = MIB_OBJECT_READ_ONLY;
2811         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER);
2812         od->v_len = sizeof(u32_t);
2813         break;
2814       case 13: /* ipReasmTimeout */
2815         od->instance = MIB_OBJECT_SCALAR;
2816         od->access = MIB_OBJECT_READ_ONLY;
2817         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
2818         od->v_len = sizeof(s32_t);
2819         break;
2820       default:
2821         LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no such object\n"));
2822         od->instance = MIB_OBJECT_NONE;
2823         break;
2824     };
2825   }
2826   else
2827   {
2828     LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no scalar\n"));
2829     od->instance = MIB_OBJECT_NONE;
2830   }
2831 }
2832
2833 static void
2834 ip_get_value(struct obj_def *od, u16_t len, void *value)
2835 {
2836   u8_t id;
2837
2838   LWIP_UNUSED_ARG(len);
2839   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2840   id = (u8_t)od->id_inst_ptr[0];
2841   switch (id)
2842   {
2843     case 1: /* ipForwarding */
2844       {
2845         s32_t *sint_ptr = (s32_t*)value;
2846 #if IP_FORWARD
2847         /* forwarding */
2848         *sint_ptr = 1;
2849 #else
2850         /* not-forwarding */
2851         *sint_ptr = 2;
2852 #endif
2853       }
2854       break;
2855     case 2: /* ipDefaultTTL */
2856       {
2857         s32_t *sint_ptr = (s32_t*)value;
2858         *sint_ptr = IP_DEFAULT_TTL;
2859       }
2860       break;
2861     case 3: /* ipInReceives */
2862       {
2863         u32_t *uint_ptr = (u32_t*)value;
2864         *uint_ptr = ipinreceives;
2865       }
2866       break;
2867     case 4: /* ipInHdrErrors */
2868       {
2869         u32_t *uint_ptr = (u32_t*)value;
2870         *uint_ptr = ipinhdrerrors;
2871       }
2872       break;
2873     case 5: /* ipInAddrErrors */
2874       {
2875         u32_t *uint_ptr = (u32_t*)value;
2876         *uint_ptr = ipinaddrerrors;
2877       }
2878       break;
2879     case 6: /* ipForwDatagrams */
2880       {
2881         u32_t *uint_ptr = (u32_t*)value;
2882         *uint_ptr = ipforwdatagrams;
2883       }
2884       break;
2885     case 7: /* ipInUnknownProtos */
2886       {
2887         u32_t *uint_ptr = (u32_t*)value;
2888         *uint_ptr = ipinunknownprotos;
2889       }
2890       break;
2891     case 8: /* ipInDiscards */
2892       {
2893         u32_t *uint_ptr = (u32_t*)value;
2894         *uint_ptr = ipindiscards;
2895       }
2896       break;
2897     case 9: /* ipInDelivers */
2898       {
2899         u32_t *uint_ptr = (u32_t*)value;
2900         *uint_ptr = ipindelivers;
2901       }
2902       break;
2903     case 10: /* ipOutRequests */
2904       {
2905         u32_t *uint_ptr = (u32_t*)value;
2906         *uint_ptr = ipoutrequests;
2907       }
2908       break;
2909     case 11: /* ipOutDiscards */
2910       {
2911         u32_t *uint_ptr = (u32_t*)value;
2912         *uint_ptr = ipoutdiscards;
2913       }
2914       break;
2915     case 12: /* ipOutNoRoutes */
2916       {
2917         u32_t *uint_ptr = (u32_t*)value;
2918         *uint_ptr = ipoutnoroutes;
2919       }
2920       break;
2921     case 13: /* ipReasmTimeout */
2922       {
2923         s32_t *sint_ptr = (s32_t*)value;
2924 #if IP_REASSEMBLY
2925         *sint_ptr = IP_REASS_MAXAGE;
2926 #else
2927         *sint_ptr = 0;
2928 #endif
2929       }
2930       break;
2931     case 14: /* ipReasmReqds */
2932       {
2933         u32_t *uint_ptr = (u32_t*)value;
2934         *uint_ptr = ipreasmreqds;
2935       }
2936       break;
2937     case 15: /* ipReasmOKs */
2938       {
2939         u32_t *uint_ptr = (u32_t*)value;
2940         *uint_ptr = ipreasmoks;
2941       }
2942       break;
2943     case 16: /* ipReasmFails */
2944       {
2945         u32_t *uint_ptr = (u32_t*)value;
2946         *uint_ptr = ipreasmfails;
2947       }
2948       break;
2949     case 17: /* ipFragOKs */
2950       {
2951         u32_t *uint_ptr = (u32_t*)value;
2952         *uint_ptr = ipfragoks;
2953       }
2954       break;
2955     case 18: /* ipFragFails */
2956       {
2957         u32_t *uint_ptr = (u32_t*)value;
2958         *uint_ptr = ipfragfails;
2959       }
2960       break;
2961     case 19: /* ipFragCreates */
2962       {
2963         u32_t *uint_ptr = (u32_t*)value;
2964         *uint_ptr = ipfragcreates;
2965       }
2966       break;
2967     case 23: /* ipRoutingDiscards */
2968       /** @todo can lwIP discard routes at all?? hardwire this to 0?? */
2969       {
2970         u32_t *uint_ptr = (u32_t*)value;
2971         *uint_ptr = iproutingdiscards;
2972       }
2973       break;
2974   };
2975 }
2976
2977 /**
2978  * Test ip object value before setting.
2979  *
2980  * @param od is the object definition
2981  * @param len return value space (in bytes)
2982  * @param value points to (varbind) space to copy value from.
2983  *
2984  * @note we allow set if the value matches the hardwired value,
2985  *   otherwise return badvalue.
2986  */
2987 static u8_t
2988 ip_set_test(struct obj_def *od, u16_t len, void *value)
2989 {
2990   u8_t id, set_ok;
2991   s32_t *sint_ptr = (s32_t*)value;
2992
2993   LWIP_UNUSED_ARG(len);
2994   set_ok = 0;
2995   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
2996   id = (u8_t)od->id_inst_ptr[0];
2997   switch (id)
2998   {
2999     case 1: /* ipForwarding */
3000 #if IP_FORWARD
3001       /* forwarding */
3002       if (*sint_ptr == 1)
3003 #else
3004       /* not-forwarding */
3005       if (*sint_ptr == 2)
3006 #endif
3007       {
3008         set_ok = 1;
3009       }
3010       break;
3011     case 2: /* ipDefaultTTL */
3012       if (*sint_ptr == IP_DEFAULT_TTL)
3013       {
3014         set_ok = 1;
3015       }
3016       break;
3017   };
3018   return set_ok;
3019 }
3020
3021 static void
3022 ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3023 {
3024   /* return to object name, adding index depth (4) */
3025   ident_len += 4;
3026   ident -= 4;
3027
3028   if (ident_len == 5)
3029   {
3030     u8_t id;
3031
3032     od->id_inst_len = ident_len;
3033     od->id_inst_ptr = ident;
3034
3035     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
3036     id = (u8_t)ident[0];
3037     switch (id)
3038     {
3039       case 1: /* ipAdEntAddr */
3040       case 3: /* ipAdEntNetMask */
3041         od->instance = MIB_OBJECT_TAB;
3042         od->access = MIB_OBJECT_READ_ONLY;
3043         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR);
3044         od->v_len = 4;
3045         break;
3046       case 2: /* ipAdEntIfIndex */
3047       case 4: /* ipAdEntBcastAddr */
3048       case 5: /* ipAdEntReasmMaxSize */
3049         od->instance = MIB_OBJECT_TAB;
3050         od->access = MIB_OBJECT_READ_ONLY;
3051         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3052         od->v_len = sizeof(s32_t);
3053         break;
3054       default:
3055         LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no such object\n"));
3056         od->instance = MIB_OBJECT_NONE;
3057         break;
3058     }
3059   }
3060   else
3061   {
3062     LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no scalar\n"));
3063     od->instance = MIB_OBJECT_NONE;
3064   }
3065 }
3066
3067 static void
3068 ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value)
3069 {
3070   u8_t id;
3071   u16_t ifidx;
3072   ip_addr_t ip;
3073   struct netif *netif = netif_list;
3074
3075   LWIP_UNUSED_ARG(len);
3076   snmp_oidtoip(&od->id_inst_ptr[1], &ip);
3077   ifidx = 0;
3078   while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr))
3079   {
3080     netif = netif->next;
3081     ifidx++;
3082   }
3083
3084   if (netif != NULL)
3085   {
3086     LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3087     id = (u8_t)od->id_inst_ptr[0];
3088     switch (id)
3089     {
3090       case 1: /* ipAdEntAddr */
3091         {
3092           ip_addr_t *dst = (ip_addr_t*)value;
3093           *dst = netif->ip_addr;
3094         }
3095         break;
3096       case 2: /* ipAdEntIfIndex */
3097         {
3098           s32_t *sint_ptr = (s32_t*)value;
3099           *sint_ptr = ifidx + 1;
3100         }
3101         break;
3102       case 3: /* ipAdEntNetMask */
3103         {
3104           ip_addr_t *dst = (ip_addr_t*)value;
3105           *dst = netif->netmask;
3106         }
3107         break;
3108       case 4: /* ipAdEntBcastAddr */
3109         {
3110           s32_t *sint_ptr = (s32_t*)value;
3111
3112           /* lwIP oddity, there's no broadcast
3113             address in the netif we can rely on */
3114           *sint_ptr = IPADDR_BROADCAST & 1;
3115         }
3116         break;
3117       case 5: /* ipAdEntReasmMaxSize */
3118         {
3119           s32_t *sint_ptr = (s32_t*)value;
3120 #if IP_REASSEMBLY
3121           /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs,
3122            * but only if receiving one fragmented packet at a time.
3123            * The current solution is to calculate for 2 simultaneous packets...
3124            */
3125           *sint_ptr = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) *
3126             (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IP_HLEN)));
3127 #else
3128           /** @todo returning MTU would be a bad thing and
3129              returning a wild guess like '576' isn't good either */
3130           *sint_ptr = 0;
3131 #endif
3132         }
3133         break;
3134     }
3135   }
3136 }
3137
3138 /**
3139  * @note
3140  * lwIP IP routing is currently using the network addresses in netif_list.
3141  * if no suitable network IP is found in netif_list, the default_netif is used.
3142  */
3143 static void
3144 ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3145 {
3146   u8_t id;
3147
3148   /* return to object name, adding index depth (4) */
3149   ident_len += 4;
3150   ident -= 4;
3151
3152   if (ident_len == 5)
3153   {
3154     od->id_inst_len = ident_len;
3155     od->id_inst_ptr = ident;
3156
3157     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
3158     id = (u8_t)ident[0];
3159     switch (id)
3160     {
3161       case 1: /* ipRouteDest */
3162       case 7: /* ipRouteNextHop */
3163       case 11: /* ipRouteMask */
3164         od->instance = MIB_OBJECT_TAB;
3165         od->access = MIB_OBJECT_READ_WRITE;
3166         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR);
3167         od->v_len = 4;
3168         break;
3169       case 2: /* ipRouteIfIndex */
3170       case 3: /* ipRouteMetric1 */
3171       case 4: /* ipRouteMetric2 */
3172       case 5: /* ipRouteMetric3 */
3173       case 6: /* ipRouteMetric4 */
3174       case 8: /* ipRouteType */
3175       case 10: /* ipRouteAge */
3176       case 12: /* ipRouteMetric5 */
3177         od->instance = MIB_OBJECT_TAB;
3178         od->access = MIB_OBJECT_READ_WRITE;
3179         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3180         od->v_len = sizeof(s32_t);
3181         break;
3182       case 9: /* ipRouteProto */
3183         od->instance = MIB_OBJECT_TAB;
3184         od->access = MIB_OBJECT_READ_ONLY;
3185         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3186         od->v_len = sizeof(s32_t);
3187         break;
3188       case 13: /* ipRouteInfo */
3189         /** @note returning zeroDotZero (0.0) no routing protocol specific MIB */
3190         od->instance = MIB_OBJECT_TAB;
3191         od->access = MIB_OBJECT_READ_ONLY;
3192         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID);
3193         od->v_len = iprouteinfo.len * sizeof(s32_t);
3194         break;
3195       default:
3196         LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no such object\n"));
3197         od->instance = MIB_OBJECT_NONE;
3198         break;
3199     }
3200   }
3201   else
3202   {
3203     LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no scalar\n"));
3204     od->instance = MIB_OBJECT_NONE;
3205   }
3206 }
3207
3208 static void
3209 ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value)
3210 {
3211   struct netif *netif;
3212   ip_addr_t dest;
3213   s32_t *ident;
3214   u8_t id;
3215
3216   ident = od->id_inst_ptr;
3217   snmp_oidtoip(&ident[1], &dest);
3218
3219   if (ip_addr_isany(&dest))
3220   {
3221     /* ip_route() uses default netif for default route */
3222     netif = netif_default;
3223   }
3224   else
3225   {
3226     /* not using ip_route(), need exact match! */
3227     netif = netif_list;
3228     while ((netif != NULL) &&
3229             !ip_addr_netcmp(&dest, &(netif->ip_addr), &(netif->netmask)) )
3230     {
3231       netif = netif->next;
3232     }
3233   }
3234   if (netif != NULL)
3235   {
3236     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
3237     id = (u8_t)ident[0];
3238     switch (id)
3239     {
3240       case 1: /* ipRouteDest */
3241         {
3242           ip_addr_t *dst = (ip_addr_t*)value;
3243
3244           if (ip_addr_isany(&dest))
3245           {
3246             /* default rte has 0.0.0.0 dest */
3247             ip_addr_set_zero(dst);
3248           }
3249           else
3250           {
3251             /* netifs have netaddress dest */
3252             ip_addr_get_network(dst, &netif->ip_addr, &netif->netmask);
3253           }
3254         }
3255         break;
3256       case 2: /* ipRouteIfIndex */
3257         {
3258           s32_t *sint_ptr = (s32_t*)value;
3259
3260           snmp_netiftoifindex(netif, sint_ptr);
3261         }
3262         break;
3263       case 3: /* ipRouteMetric1 */
3264         {
3265           s32_t *sint_ptr = (s32_t*)value;
3266
3267           if (ip_addr_isany(&dest))
3268           {
3269             /* default rte has metric 1 */
3270             *sint_ptr = 1;
3271           }
3272           else
3273           {
3274             /* other rtes have metric 0 */
3275             *sint_ptr = 0;
3276           }
3277         }
3278         break;
3279       case 4: /* ipRouteMetric2 */
3280       case 5: /* ipRouteMetric3 */
3281       case 6: /* ipRouteMetric4 */
3282       case 12: /* ipRouteMetric5 */
3283         {
3284           s32_t *sint_ptr = (s32_t*)value;
3285           /* not used */
3286           *sint_ptr = -1;
3287         }
3288         break;
3289       case 7: /* ipRouteNextHop */
3290         {
3291           ip_addr_t *dst = (ip_addr_t*)value;
3292
3293           if (ip_addr_isany(&dest))
3294           {
3295             /* default rte: gateway */
3296             *dst = netif->gw;
3297           }
3298           else
3299           {
3300             /* other rtes: netif ip_addr  */
3301             *dst = netif->ip_addr;
3302           }
3303         }
3304         break;
3305       case 8: /* ipRouteType */
3306         {
3307           s32_t *sint_ptr = (s32_t*)value;
3308
3309           if (ip_addr_isany(&dest))
3310           {
3311             /* default rte is indirect */
3312             *sint_ptr = 4;
3313           }
3314           else
3315           {
3316             /* other rtes are direct */
3317             *sint_ptr = 3;
3318           }
3319         }
3320         break;
3321       case 9: /* ipRouteProto */
3322         {
3323           s32_t *sint_ptr = (s32_t*)value;
3324           /* locally defined routes */
3325           *sint_ptr = 2;
3326         }
3327         break;
3328       case 10: /* ipRouteAge */
3329         {
3330           s32_t *sint_ptr = (s32_t*)value;
3331           /** @todo (sysuptime - timestamp last change) / 100
3332               @see snmp_insert_iprteidx_tree() */
3333           *sint_ptr = 0;
3334         }
3335         break;
3336       case 11: /* ipRouteMask */
3337         {
3338           ip_addr_t *dst = (ip_addr_t*)value;
3339
3340           if (ip_addr_isany(&dest))
3341           {
3342             /* default rte use 0.0.0.0 mask */
3343             ip_addr_set_zero(dst);
3344           }
3345           else
3346           {
3347             /* other rtes use netmask */
3348             *dst = netif->netmask;
3349           }
3350         }
3351         break;
3352       case 13: /* ipRouteInfo */
3353         objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t)));
3354         break;
3355     }
3356   }
3357 }
3358
3359 static void
3360 ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3361 {
3362   /* return to object name, adding index depth (5) */
3363   ident_len += 5;
3364   ident -= 5;
3365
3366   if (ident_len == 6)
3367   {
3368     u8_t id;
3369
3370     od->id_inst_len = ident_len;
3371     od->id_inst_ptr = ident;
3372
3373     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
3374     id = (u8_t)ident[0];
3375     switch (id)
3376     {
3377       case 1: /* ipNetToMediaIfIndex */
3378       case 4: /* ipNetToMediaType */
3379         od->instance = MIB_OBJECT_TAB;
3380         od->access = MIB_OBJECT_READ_WRITE;
3381         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3382         od->v_len = sizeof(s32_t);
3383         break;
3384       case 2: /* ipNetToMediaPhysAddress */
3385         od->instance = MIB_OBJECT_TAB;
3386         od->access = MIB_OBJECT_READ_WRITE;
3387         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
3388         od->v_len = 6; /** @todo try to use netif::hwaddr_len */
3389         break;
3390       case 3: /* ipNetToMediaNetAddress */
3391         od->instance = MIB_OBJECT_TAB;
3392         od->access = MIB_OBJECT_READ_WRITE;
3393         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR);
3394         od->v_len = 4;
3395         break;
3396       default:
3397         LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no such object\n"));
3398         od->instance = MIB_OBJECT_NONE;
3399         break;
3400     }
3401   }
3402   else
3403   {
3404     LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no scalar\n"));
3405     od->instance = MIB_OBJECT_NONE;
3406   }
3407 }
3408
3409 static void
3410 ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value)
3411 {
3412 #if LWIP_ARP
3413   u8_t id;
3414   struct eth_addr* ethaddr_ret;
3415   ip_addr_t* ipaddr_ret;
3416 #endif /* LWIP_ARP */
3417   ip_addr_t ip;
3418   struct netif *netif;
3419
3420   LWIP_UNUSED_ARG(len);
3421   LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */
3422
3423   snmp_ifindextonetif(od->id_inst_ptr[1], &netif);
3424   snmp_oidtoip(&od->id_inst_ptr[2], &ip);
3425
3426 #if LWIP_ARP /** @todo implement a netif_find_addr */
3427   if (etharp_find_addr(netif, &ip, &ethaddr_ret, &ipaddr_ret) > -1)
3428   {
3429     LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3430     id = (u8_t)od->id_inst_ptr[0];
3431     switch (id)
3432     {
3433       case 1: /* ipNetToMediaIfIndex */
3434         {
3435           s32_t *sint_ptr = (s32_t*)value;
3436           *sint_ptr = od->id_inst_ptr[1];
3437         }
3438         break;
3439       case 2: /* ipNetToMediaPhysAddress */
3440         {
3441           struct eth_addr *dst = (struct eth_addr*)value;
3442
3443           *dst = *ethaddr_ret;
3444         }
3445         break;
3446       case 3: /* ipNetToMediaNetAddress */
3447         {
3448           ip_addr_t *dst = (ip_addr_t*)value;
3449
3450           *dst = *ipaddr_ret;
3451         }
3452         break;
3453       case 4: /* ipNetToMediaType */
3454         {
3455           s32_t *sint_ptr = (s32_t*)value;
3456           /* dynamic (?) */
3457           *sint_ptr = 3;
3458         }
3459         break;
3460     }
3461   }
3462 #endif /* LWIP_ARP */
3463 }
3464
3465 static void
3466 icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3467 {
3468   /* return to object name, adding index depth (1) */
3469   ident_len += 1;
3470   ident -= 1;
3471   if ((ident_len == 2) &&
3472       (ident[0] > 0) && (ident[0] < 27))
3473   {
3474     od->id_inst_len = ident_len;
3475     od->id_inst_ptr = ident;
3476
3477     od->instance = MIB_OBJECT_SCALAR;
3478     od->access = MIB_OBJECT_READ_ONLY;
3479     od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER);
3480     od->v_len = sizeof(u32_t);
3481   }
3482   else
3483   {
3484     LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_object_def: no scalar\n"));
3485     od->instance = MIB_OBJECT_NONE;
3486   }
3487 }
3488
3489 static void
3490 icmp_get_value(struct obj_def *od, u16_t len, void *value)
3491 {
3492   u32_t *uint_ptr = (u32_t*)value;
3493   u8_t id;
3494
3495   LWIP_UNUSED_ARG(len);
3496   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3497   id = (u8_t)od->id_inst_ptr[0];
3498   switch (id)
3499   {
3500     case 1: /* icmpInMsgs */
3501       *uint_ptr = icmpinmsgs;
3502       break;
3503     case 2: /* icmpInErrors */
3504       *uint_ptr = icmpinerrors;
3505       break;
3506     case 3: /* icmpInDestUnreachs */
3507       *uint_ptr = icmpindestunreachs;
3508       break;
3509     case 4: /* icmpInTimeExcds */
3510       *uint_ptr = icmpintimeexcds;
3511       break;
3512     case 5: /* icmpInParmProbs */
3513       *uint_ptr = icmpinparmprobs;
3514       break;
3515     case 6: /* icmpInSrcQuenchs */
3516       *uint_ptr = icmpinsrcquenchs;
3517       break;
3518     case 7: /* icmpInRedirects */
3519       *uint_ptr = icmpinredirects;
3520       break;
3521     case 8: /* icmpInEchos */
3522       *uint_ptr = icmpinechos;
3523       break;
3524     case 9: /* icmpInEchoReps */
3525       *uint_ptr = icmpinechoreps;
3526       break;
3527     case 10: /* icmpInTimestamps */
3528       *uint_ptr = icmpintimestamps;
3529       break;
3530     case 11: /* icmpInTimestampReps */
3531       *uint_ptr = icmpintimestampreps;
3532       break;
3533     case 12: /* icmpInAddrMasks */
3534       *uint_ptr = icmpinaddrmasks;
3535       break;
3536     case 13: /* icmpInAddrMaskReps */
3537       *uint_ptr = icmpinaddrmaskreps;
3538       break;
3539     case 14: /* icmpOutMsgs */
3540       *uint_ptr = icmpoutmsgs;
3541       break;
3542     case 15: /* icmpOutErrors */
3543       *uint_ptr = icmpouterrors;
3544       break;
3545     case 16: /* icmpOutDestUnreachs */
3546       *uint_ptr = icmpoutdestunreachs;
3547       break;
3548     case 17: /* icmpOutTimeExcds */
3549       *uint_ptr = icmpouttimeexcds;
3550       break;
3551     case 18: /* icmpOutParmProbs */
3552       *uint_ptr = icmpoutparmprobs;
3553       break;
3554     case 19: /* icmpOutSrcQuenchs */
3555       *uint_ptr = icmpoutsrcquenchs;
3556       break;
3557     case 20: /* icmpOutRedirects */
3558       *uint_ptr = icmpoutredirects;
3559       break;
3560     case 21: /* icmpOutEchos */
3561       *uint_ptr = icmpoutechos;
3562       break;
3563     case 22: /* icmpOutEchoReps */
3564       *uint_ptr = icmpoutechoreps;
3565       break;
3566     case 23: /* icmpOutTimestamps */
3567       *uint_ptr = icmpouttimestamps;
3568       break;
3569     case 24: /* icmpOutTimestampReps */
3570       *uint_ptr = icmpouttimestampreps;
3571       break;
3572     case 25: /* icmpOutAddrMasks */
3573       *uint_ptr = icmpoutaddrmasks;
3574       break;
3575     case 26: /* icmpOutAddrMaskReps */
3576       *uint_ptr = icmpoutaddrmaskreps;
3577       break;
3578   }
3579 }
3580
3581 #if LWIP_TCP
3582 /** @todo tcp grp */
3583 static void
3584 tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3585 {
3586   u8_t id;
3587
3588   /* return to object name, adding index depth (1) */
3589   ident_len += 1;
3590   ident -= 1;
3591   if (ident_len == 2)
3592   {
3593     od->id_inst_len = ident_len;
3594     od->id_inst_ptr = ident;
3595
3596     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
3597     id = (u8_t)ident[0];
3598     LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id));
3599
3600     switch (id)
3601     {
3602       case 1: /* tcpRtoAlgorithm */
3603       case 2: /* tcpRtoMin */
3604       case 3: /* tcpRtoMax */
3605       case 4: /* tcpMaxConn */
3606         od->instance = MIB_OBJECT_SCALAR;
3607         od->access = MIB_OBJECT_READ_ONLY;
3608         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3609         od->v_len = sizeof(s32_t);
3610         break;
3611       case 5: /* tcpActiveOpens */
3612       case 6: /* tcpPassiveOpens */
3613       case 7: /* tcpAttemptFails */
3614       case 8: /* tcpEstabResets */
3615       case 10: /* tcpInSegs */
3616       case 11: /* tcpOutSegs */
3617       case 12: /* tcpRetransSegs */
3618       case 14: /* tcpInErrs */
3619       case 15: /* tcpOutRsts */
3620         od->instance = MIB_OBJECT_SCALAR;
3621         od->access = MIB_OBJECT_READ_ONLY;
3622         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER);
3623         od->v_len = sizeof(u32_t);
3624         break;
3625       case 9: /* tcpCurrEstab */
3626         od->instance = MIB_OBJECT_TAB;
3627         od->access = MIB_OBJECT_READ_ONLY;
3628         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE);
3629         od->v_len = sizeof(u32_t);
3630         break;
3631       default:
3632         LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no such object\n"));
3633         od->instance = MIB_OBJECT_NONE;
3634         break;
3635     };
3636   }
3637   else
3638   {
3639     LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no scalar\n"));
3640     od->instance = MIB_OBJECT_NONE;
3641   }
3642 }
3643
3644 static void
3645 tcp_get_value(struct obj_def *od, u16_t len, void *value)
3646 {
3647   u32_t *uint_ptr = (u32_t*)value;
3648   s32_t *sint_ptr = (s32_t*)value;
3649   u8_t id;
3650
3651   LWIP_UNUSED_ARG(len);
3652   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3653   id = (u8_t)od->id_inst_ptr[0];
3654   switch (id)
3655   {
3656     case 1: /* tcpRtoAlgorithm, vanj(4) */
3657       *sint_ptr = 4;
3658       break;
3659     case 2: /* tcpRtoMin */
3660       /* @todo not the actual value, a guess,
3661           needs to be calculated */
3662       *sint_ptr = 1000;
3663       break;
3664     case 3: /* tcpRtoMax */
3665       /* @todo not the actual value, a guess,
3666          needs to be calculated */
3667       *sint_ptr = 60000;
3668       break;
3669     case 4: /* tcpMaxConn */
3670       *sint_ptr = MEMP_NUM_TCP_PCB;
3671       break;
3672     case 5: /* tcpActiveOpens */
3673       *uint_ptr = tcpactiveopens;
3674       break;
3675     case 6: /* tcpPassiveOpens */
3676       *uint_ptr = tcppassiveopens;
3677       break;
3678     case 7: /* tcpAttemptFails */
3679       *uint_ptr = tcpattemptfails;
3680       break;
3681     case 8: /* tcpEstabResets */
3682       *uint_ptr = tcpestabresets;
3683       break;
3684     case 9: /* tcpCurrEstab */
3685       {
3686         u16_t tcpcurrestab = 0;
3687         struct tcp_pcb *pcb = tcp_active_pcbs;
3688         while (pcb != NULL)
3689         {
3690           if ((pcb->state == ESTABLISHED) ||
3691               (pcb->state == CLOSE_WAIT))
3692           {
3693             tcpcurrestab++;
3694           }
3695           pcb = pcb->next;
3696         }
3697         *uint_ptr = tcpcurrestab;
3698       }
3699       break;
3700     case 10: /* tcpInSegs */
3701       *uint_ptr = tcpinsegs;
3702       break;
3703     case 11: /* tcpOutSegs */
3704       *uint_ptr = tcpoutsegs;
3705       break;
3706     case 12: /* tcpRetransSegs */
3707       *uint_ptr = tcpretranssegs;
3708       break;
3709     case 14: /* tcpInErrs */
3710       *uint_ptr = tcpinerrs;
3711       break;
3712     case 15: /* tcpOutRsts */
3713       *uint_ptr = tcpoutrsts;
3714       break;
3715   }
3716 }
3717 #ifdef THIS_SEEMS_UNUSED
3718 static void
3719 tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3720 {
3721   /* return to object name, adding index depth (10) */
3722   ident_len += 10;
3723   ident -= 10;
3724
3725   if (ident_len == 11)
3726   {
3727     u8_t id;
3728
3729     od->id_inst_len = ident_len;
3730     od->id_inst_ptr = ident;
3731
3732     id = ident[0];
3733     LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id));
3734
3735     switch (id)
3736     {
3737       case 1: /* tcpConnState */
3738         od->instance = MIB_OBJECT_TAB;
3739         od->access = MIB_OBJECT_READ_WRITE;
3740         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3741         od->v_len = sizeof(s32_t);
3742         break;
3743       case 2: /* tcpConnLocalAddress */
3744       case 4: /* tcpConnRemAddress */
3745         od->instance = MIB_OBJECT_TAB;
3746         od->access = MIB_OBJECT_READ_ONLY;
3747         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR);
3748         od->v_len = 4;
3749         break;
3750       case 3: /* tcpConnLocalPort */
3751       case 5: /* tcpConnRemPort */
3752         od->instance = MIB_OBJECT_TAB;
3753         od->access = MIB_OBJECT_READ_ONLY;
3754         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3755         od->v_len = sizeof(s32_t);
3756         break;
3757       default:
3758         LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n"));
3759         od->instance = MIB_OBJECT_NONE;
3760         break;
3761     };
3762   }
3763   else
3764   {
3765     LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n"));
3766     od->instance = MIB_OBJECT_NONE;
3767   }
3768 }
3769
3770 static void
3771 tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value)
3772 {
3773   ip_addr_t lip, rip;
3774   u16_t lport, rport;
3775   s32_t *ident;
3776
3777   ident = od->id_inst_ptr;
3778   snmp_oidtoip(&ident[1], &lip);
3779   lport = ident[5];
3780   snmp_oidtoip(&ident[6], &rip);
3781   rport = ident[10];
3782
3783   /** @todo find matching PCB */
3784 }
3785 #endif /* if 0 */
3786 #endif
3787
3788 static void
3789 udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3790 {
3791   /* return to object name, adding index depth (1) */
3792   ident_len += 1;
3793   ident -= 1;
3794   if ((ident_len == 2) &&
3795       (ident[0] > 0) && (ident[0] < 6))
3796   {
3797     od->id_inst_len = ident_len;
3798     od->id_inst_ptr = ident;
3799
3800     od->instance = MIB_OBJECT_SCALAR;
3801     od->access = MIB_OBJECT_READ_ONLY;
3802     od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER);
3803     od->v_len = sizeof(u32_t);
3804   }
3805   else
3806   {
3807     LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_object_def: no scalar\n"));
3808     od->instance = MIB_OBJECT_NONE;
3809   }
3810 }
3811
3812 static void
3813 udp_get_value(struct obj_def *od, u16_t len, void *value)
3814 {
3815   u32_t *uint_ptr = (u32_t*)value;
3816   u8_t id;
3817
3818   LWIP_UNUSED_ARG(len);
3819   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3820   id = (u8_t)od->id_inst_ptr[0];
3821   switch (id)
3822   {
3823     case 1: /* udpInDatagrams */
3824       *uint_ptr = udpindatagrams;
3825       break;
3826     case 2: /* udpNoPorts */
3827       *uint_ptr = udpnoports;
3828       break;
3829     case 3: /* udpInErrors */
3830       *uint_ptr = udpinerrors;
3831       break;
3832     case 4: /* udpOutDatagrams */
3833       *uint_ptr = udpoutdatagrams;
3834       break;
3835   }
3836 }
3837
3838 static void
3839 udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3840 {
3841   /* return to object name, adding index depth (5) */
3842   ident_len += 5;
3843   ident -= 5;
3844
3845   if (ident_len == 6)
3846   {
3847     od->id_inst_len = ident_len;
3848     od->id_inst_ptr = ident;
3849
3850     switch (ident[0])
3851     {
3852       case 1: /* udpLocalAddress */
3853         od->instance = MIB_OBJECT_TAB;
3854         od->access = MIB_OBJECT_READ_ONLY;
3855         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR);
3856         od->v_len = 4;
3857         break;
3858       case 2: /* udpLocalPort */
3859         od->instance = MIB_OBJECT_TAB;
3860         od->access = MIB_OBJECT_READ_ONLY;
3861         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3862         od->v_len = sizeof(s32_t);
3863         break;
3864       default:
3865         LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no such object\n"));
3866         od->instance = MIB_OBJECT_NONE;
3867         break;
3868     }
3869   }
3870   else
3871   {
3872     LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no scalar\n"));
3873     od->instance = MIB_OBJECT_NONE;
3874   }
3875 }
3876
3877 static void
3878 udpentry_get_value(struct obj_def *od, u16_t len, void *value)
3879 {
3880   u8_t id;
3881   struct udp_pcb *pcb;
3882   ip_addr_t ip;
3883   u16_t port;
3884
3885   LWIP_UNUSED_ARG(len);
3886   snmp_oidtoip(&od->id_inst_ptr[1], &ip);
3887   LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff));
3888   port = (u16_t)od->id_inst_ptr[5];
3889
3890   pcb = udp_pcbs;
3891   while ((pcb != NULL) &&
3892          !(ip_addr_cmp(&pcb->local_ip, &ip) &&
3893            (pcb->local_port == port)))
3894   {
3895     pcb = pcb->next;
3896   }
3897
3898   if (pcb != NULL)
3899   {
3900     LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3901     id = (u8_t)od->id_inst_ptr[0];
3902     switch (id)
3903     {
3904       case 1: /* udpLocalAddress */
3905         {
3906           ip_addr_t *dst = (ip_addr_t*)value;
3907           *dst = pcb->local_ip;
3908         }
3909         break;
3910       case 2: /* udpLocalPort */
3911         {
3912           s32_t *sint_ptr = (s32_t*)value;
3913           *sint_ptr = pcb->local_port;
3914         }
3915         break;
3916     }
3917   }
3918 }
3919
3920 static void
3921 snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
3922 {
3923   /* return to object name, adding index depth (1) */
3924   ident_len += 1;
3925   ident -= 1;
3926   if (ident_len == 2)
3927   {
3928     u8_t id;
3929
3930     od->id_inst_len = ident_len;
3931     od->id_inst_ptr = ident;
3932
3933     LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
3934     id = (u8_t)ident[0];
3935     switch (id)
3936     {
3937       case 1: /* snmpInPkts */
3938       case 2: /* snmpOutPkts */
3939       case 3: /* snmpInBadVersions */
3940       case 4: /* snmpInBadCommunityNames */
3941       case 5: /* snmpInBadCommunityUses */
3942       case 6: /* snmpInASNParseErrs */
3943       case 8: /* snmpInTooBigs */
3944       case 9: /* snmpInNoSuchNames */
3945       case 10: /* snmpInBadValues */
3946       case 11: /* snmpInReadOnlys */
3947       case 12: /* snmpInGenErrs */
3948       case 13: /* snmpInTotalReqVars */
3949       case 14: /* snmpInTotalSetVars */
3950       case 15: /* snmpInGetRequests */
3951       case 16: /* snmpInGetNexts */
3952       case 17: /* snmpInSetRequests */
3953       case 18: /* snmpInGetResponses */
3954       case 19: /* snmpInTraps */
3955       case 20: /* snmpOutTooBigs */
3956       case 21: /* snmpOutNoSuchNames */
3957       case 22: /* snmpOutBadValues */
3958       case 24: /* snmpOutGenErrs */
3959       case 25: /* snmpOutGetRequests */
3960       case 26: /* snmpOutGetNexts */
3961       case 27: /* snmpOutSetRequests */
3962       case 28: /* snmpOutGetResponses */
3963       case 29: /* snmpOutTraps */
3964         od->instance = MIB_OBJECT_SCALAR;
3965         od->access = MIB_OBJECT_READ_ONLY;
3966         od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER);
3967         od->v_len = sizeof(u32_t);
3968         break;
3969       case 30: /* snmpEnableAuthenTraps */
3970         od->instance = MIB_OBJECT_SCALAR;
3971         od->access = MIB_OBJECT_READ_WRITE;
3972         od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
3973         od->v_len = sizeof(s32_t);
3974         break;
3975       default:
3976         LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no such object\n"));
3977         od->instance = MIB_OBJECT_NONE;
3978         break;
3979     };
3980   }
3981   else
3982   {
3983     LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no scalar\n"));
3984     od->instance = MIB_OBJECT_NONE;
3985   }
3986 }
3987
3988 static void
3989 snmp_get_value(struct obj_def *od, u16_t len, void *value)
3990 {
3991   u32_t *uint_ptr = (u32_t*)value;
3992   u8_t id;
3993
3994   LWIP_UNUSED_ARG(len);
3995   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
3996   id = (u8_t)od->id_inst_ptr[0];
3997   switch (id)
3998   {
3999       case 1: /* snmpInPkts */
4000         *uint_ptr = snmpinpkts;
4001         break;
4002       case 2: /* snmpOutPkts */
4003         *uint_ptr = snmpoutpkts;
4004         break;
4005       case 3: /* snmpInBadVersions */
4006         *uint_ptr = snmpinbadversions;
4007         break;
4008       case 4: /* snmpInBadCommunityNames */
4009         *uint_ptr = snmpinbadcommunitynames;
4010         break;
4011       case 5: /* snmpInBadCommunityUses */
4012         *uint_ptr = snmpinbadcommunityuses;
4013         break;
4014       case 6: /* snmpInASNParseErrs */
4015         *uint_ptr = snmpinasnparseerrs;
4016         break;
4017       case 8: /* snmpInTooBigs */
4018         *uint_ptr = snmpintoobigs;
4019         break;
4020       case 9: /* snmpInNoSuchNames */
4021         *uint_ptr = snmpinnosuchnames;
4022         break;
4023       case 10: /* snmpInBadValues */
4024         *uint_ptr = snmpinbadvalues;
4025         break;
4026       case 11: /* snmpInReadOnlys */
4027         *uint_ptr = snmpinreadonlys;
4028         break;
4029       case 12: /* snmpInGenErrs */
4030         *uint_ptr = snmpingenerrs;
4031         break;
4032       case 13: /* snmpInTotalReqVars */
4033         *uint_ptr = snmpintotalreqvars;
4034         break;
4035       case 14: /* snmpInTotalSetVars */
4036         *uint_ptr = snmpintotalsetvars;
4037         break;
4038       case 15: /* snmpInGetRequests */
4039         *uint_ptr = snmpingetrequests;
4040         break;
4041       case 16: /* snmpInGetNexts */
4042         *uint_ptr = snmpingetnexts;
4043         break;
4044       case 17: /* snmpInSetRequests */
4045         *uint_ptr = snmpinsetrequests;
4046         break;
4047       case 18: /* snmpInGetResponses */
4048         *uint_ptr = snmpingetresponses;
4049         break;
4050       case 19: /* snmpInTraps */
4051         *uint_ptr = snmpintraps;
4052         break;
4053       case 20: /* snmpOutTooBigs */
4054         *uint_ptr = snmpouttoobigs;
4055         break;
4056       case 21: /* snmpOutNoSuchNames */
4057         *uint_ptr = snmpoutnosuchnames;
4058         break;
4059       case 22: /* snmpOutBadValues */
4060         *uint_ptr = snmpoutbadvalues;
4061         break;
4062       case 24: /* snmpOutGenErrs */
4063         *uint_ptr = snmpoutgenerrs;
4064         break;
4065       case 25: /* snmpOutGetRequests */
4066         *uint_ptr = snmpoutgetrequests;
4067         break;
4068       case 26: /* snmpOutGetNexts */
4069         *uint_ptr = snmpoutgetnexts;
4070         break;
4071       case 27: /* snmpOutSetRequests */
4072         *uint_ptr = snmpoutsetrequests;
4073         break;
4074       case 28: /* snmpOutGetResponses */
4075         *uint_ptr = snmpoutgetresponses;
4076         break;
4077       case 29: /* snmpOutTraps */
4078         *uint_ptr = snmpouttraps;
4079         break;
4080       case 30: /* snmpEnableAuthenTraps */
4081         *uint_ptr = *snmpenableauthentraps_ptr;
4082         break;
4083   };
4084 }
4085
4086 /**
4087  * Test snmp object value before setting.
4088  *
4089  * @param od is the object definition
4090  * @param len return value space (in bytes)
4091  * @param value points to (varbind) space to copy value from.
4092  */
4093 static u8_t
4094 snmp_set_test(struct obj_def *od, u16_t len, void *value)
4095 {
4096   u8_t id, set_ok;
4097
4098   LWIP_UNUSED_ARG(len);
4099   set_ok = 0;
4100   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
4101   id = (u8_t)od->id_inst_ptr[0];
4102   if (id == 30)
4103   {
4104     /* snmpEnableAuthenTraps */
4105     s32_t *sint_ptr = (s32_t*)value;
4106
4107     if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default)
4108     {
4109       /* we should have writable non-volatile mem here */
4110       if ((*sint_ptr == 1) || (*sint_ptr == 2))
4111       {
4112         set_ok = 1;
4113       }
4114     }
4115     else
4116     {
4117       /* const or hardwired value */
4118       if (*sint_ptr == snmpenableauthentraps_default)
4119       {
4120         set_ok = 1;
4121       }
4122     }
4123   }
4124   return set_ok;
4125 }
4126
4127 static void
4128 snmp_set_value(struct obj_def *od, u16_t len, void *value)
4129 {
4130   u8_t id;
4131
4132   LWIP_UNUSED_ARG(len);
4133   LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
4134   id = (u8_t)od->id_inst_ptr[0];
4135   if (id == 30)
4136   {
4137     /* snmpEnableAuthenTraps */
4138     /* @todo @fixme: which kind of pointer is 'value'? s32_t or u8_t??? */
4139     u8_t *ptr = (u8_t*)value;
4140     *snmpenableauthentraps_ptr = *ptr;
4141   }
4142 }
4143
4144 #endif /* LWIP_SNMP */