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