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