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