Coverage Report

Created: 2026-05-30 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/parse.c
Line
Count
Source
1
/*
2
 * parse.c
3
 *
4
 */
5
/* Portions of this file are subject to the following copyrights.  See
6
 * the Net-SNMP's COPYING file for more details and other copyrights
7
 * that may apply:
8
 */
9
/******************************************************************
10
        Copyright 1989, 1991, 1992 by Carnegie Mellon University
11
12
                      All Rights Reserved
13
14
Permission to use, copy, modify, and distribute this software and its
15
documentation for any purpose and without fee is hereby granted,
16
provided that the above copyright notice appear in all copies and that
17
both that copyright notice and this permission notice appear in
18
supporting documentation, and that the name of CMU not be
19
used in advertising or publicity pertaining to distribution of the
20
software without specific, written prior permission.
21
22
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
24
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
25
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
26
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
27
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28
SOFTWARE.
29
******************************************************************/
30
/*
31
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
32
 * Use is subject to license terms specified in the COPYING file
33
 * distributed with the Net-SNMP package.
34
 */
35
#include <net-snmp/net-snmp-config.h>
36
#include <net-snmp/net-snmp-features.h>
37
38
#ifndef NETSNMP_DISABLE_MIB_LOADING
39
40
#ifdef HAVE_LIMITS_H
41
#include <limits.h>
42
#endif
43
#include <stdio.h>
44
#ifdef HAVE_STDLIB_H
45
#include <stdlib.h>
46
#endif
47
#ifdef HAVE_STRING_H
48
#include <string.h>
49
#else
50
#include <strings.h>
51
#endif
52
#include <ctype.h>
53
#include <sys/types.h>
54
#ifdef HAVE_SYS_STAT_H
55
#include <sys/stat.h>
56
#endif
57
58
#ifdef HAVE_DIRENT_H
59
#include <dirent.h>
60
#endif
61
#ifdef TIME_WITH_SYS_TIME
62
# include <sys/time.h>
63
# include <time.h>
64
#else
65
# ifdef HAVE_SYS_TIME_H
66
#  include <sys/time.h>
67
# else
68
#  include <time.h>
69
# endif
70
#endif
71
#ifdef HAVE_NETINET_IN_H
72
#include <netinet/in.h>
73
#endif
74
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
75
#include <regex.h>
76
#endif
77
#ifdef HAVE_UNISTD_H
78
#include <unistd.h>
79
#endif
80
81
#include <errno.h>
82
83
#include <net-snmp/types.h>
84
#include <net-snmp/output_api.h>
85
#include <net-snmp/config_api.h>
86
#include <net-snmp/utilities.h>
87
88
#include <net-snmp/library/parse.h>
89
#include <net-snmp/library/mib.h>
90
#include <net-snmp/library/snmp_api.h>
91
#include <net-snmp/library/tools.h>
92
93
netsnmp_feature_child_of(find_module, mib_api);
94
netsnmp_feature_child_of(get_tc_description, mib_api);
95
96
/*
97
 * A linked list of nodes.
98
 */
99
struct node {
100
    struct node    *next;
101
    char           *label;  /* This node's (unique) textual name */
102
    u_long          subid;  /* This node's integer subidentifier */
103
    int             modid;  /* The module containing this node */
104
    char           *parent; /* The parent's textual name */
105
    int             tc_index; /* index into tclist (-1 if NA) */
106
    int             type;   /* The type of object this represents */
107
    int             access;
108
    int             status;
109
    struct enum_list *enums; /* (optional) list of enumerated integers */
110
    struct range_list *ranges;
111
    struct index_list *indexes;
112
    char           *augments;
113
    struct varbind_list *varbinds;
114
    char           *hint;
115
    char           *units;
116
    char           *description; /* description (a quoted string) */
117
    char           *reference; /* references (a quoted string) */
118
    char           *defaultValue;
119
    char           *filename;
120
    int             lineno;
121
};
122
123
/*
124
 * This is one element of an object identifier with either an integer
125
 * subidentifier, or a textual string label, or both.
126
 * The subid is -1 if not present, and label is NULL if not present.
127
 */
128
struct subid_s {
129
    int             subid;
130
    int             modid;
131
    char           *label;
132
};
133
134
3.58k
#define TC_INCR 100
135
struct tc {                     /* textual conventions */
136
    int             type;
137
    int             modid;
138
    char           *descriptor;
139
    char           *hint;
140
    struct enum_list *enums;
141
    struct range_list *ranges;
142
    char           *description;
143
    int             lineno;
144
} *tclist;
145
int tc_alloc;
146
147
static int      mibLine;
148
static const char *File = "(none)";
149
static int      anonymous;
150
151
struct objgroup {
152
    char           *name;
153
    int             line;
154
    struct objgroup *next;
155
}              *objgroups = NULL, *objects = NULL, *notifs = NULL;
156
157
1.90M
#define SYNTAX_MASK     0x80
158
/*
159
 * types of tokens
160
 * Tokens with the SYNTAX_MASK bit set are syntax tokens 
161
 */
162
987k
#define CONTINUE    -1
163
9.87M
#define ENDOFFILE   0
164
8.18M
#define LABEL       1
165
#define SUBTREE     2
166
82.5k
#define SYNTAX      3
167
5.53k
#define OBJID       (4 | SYNTAX_MASK)
168
6.16k
#define OCTETSTR    (5 | SYNTAX_MASK)
169
98.8k
#define INTEGER     (6 | SYNTAX_MASK)
170
97.6k
#define NETADDR     (7 | SYNTAX_MASK)
171
98.0k
#define IPADDR      (8 | SYNTAX_MASK)
172
102k
#define COUNTER     (9 | SYNTAX_MASK)
173
103k
#define GAUGE       (10 | SYNTAX_MASK)
174
100k
#define TIMETICKS   (11 | SYNTAX_MASK)
175
99.6k
#define KW_OPAQUE   (12 | SYNTAX_MASK)
176
6.38k
#define NUL         (13 | SYNTAX_MASK)
177
75.9k
#define SEQUENCE    14
178
660
#define OF          15          /* SEQUENCE OF */
179
13.6k
#define OBJTYPE     16
180
13.5k
#define ACCESS      17
181
30.5k
#define READONLY    18
182
20.3k
#define READWRITE   19
183
21.2k
#define WRITEONLY   20
184
#ifdef NOACCESS
185
#undef NOACCESS                 /* agent 'NOACCESS' token */
186
#endif
187
22.6k
#define NOACCESS    21
188
29.0k
#define STATUS      22
189
26.8k
#define MANDATORY   23
190
14.0k
#define KW_OPTIONAL    24
191
15.5k
#define OBSOLETE    25
192
/*
193
 * #define RECOMMENDED 26 
194
 */
195
#define PUNCT       27
196
1.99M
#define EQUALS      28
197
240k
#define NUMBER      29
198
3.69M
#define LEFTBRACKET 30
199
15.5M
#define RIGHTBRACKET 31
200
351k
#define LEFTPAREN   32
201
44.1k
#define RIGHTPAREN  33
202
38.8k
#define COMMA       34
203
92.2k
#define DESCRIPTION 35
204
1.10M
#define QUOTESTRING 36
205
3.04k
#define INDEX       37
206
2.12k
#define DEFVAL      38
207
18.5k
#define DEPRECATED  39
208
6.05k
#define SIZE        40
209
11.3k
#define BITSTRING   (41 | SYNTAX_MASK)
210
99.9k
#define NSAPADDRESS (42 | SYNTAX_MASK)
211
99.2k
#define COUNTER64   (43 | SYNTAX_MASK)
212
6.10k
#define OBJGROUP    44
213
4.72k
#define NOTIFTYPE   45
214
459
#define AUGMENTS    46
215
13.9k
#define COMPLIANCE  47
216
17.4k
#define READCREATE  48
217
13.5k
#define UNITS       49
218
10.6k
#define REFERENCE   50
219
52
#define NUM_ENTRIES 51
220
9.40k
#define MODULEIDENTITY 52
221
5.91k
#define LASTUPDATED 53
222
4.58k
#define ORGANIZATION 54
223
2.98k
#define CONTACTINFO 55
224
99.1k
#define UINTEGER32 (56 | SYNTAX_MASK)
225
52.6k
#define CURRENT     57
226
23.7k
#define DEFINITIONS 58
227
38.2k
#define END         59
228
845k
#define SEMI        60
229
4.01k
#define TRAPTYPE    61
230
689
#define ENTERPRISE  62
231
/*
232
 * #define DISPLAYSTR (63 | SYNTAX_MASK) 
233
 */
234
289k
#define BEGIN       64
235
3.42k
#define IMPORTS     65
236
235
#define EXPORTS     66
237
4.09k
#define ACCNOTIFY   67
238
27.7k
#define BAR         68
239
217k
#define RANGE       69
240
13.8k
#define CONVENTION  70
241
30.0k
#define DISPLAYHINT 71
242
63.5k
#define FROM        72
243
7.45k
#define AGENTCAP    73
244
29.0k
#define MACRO       74
245
31.3k
#define IMPLIED     75
246
809
#define SUPPORTS    76
247
482
#define INCLUDES    77
248
1
#define VARIATION   78
249
2.04k
#define REVISION    79
250
0
#define NOTIMPL     80
251
4.71k
#define OBJECTS     81
252
300
#define NOTIFICATIONS 82
253
18.5k
#define MODULE      83
254
6.78k
#define MINACCESS   84
255
3.96k
#define PRODREL     85
256
6.78k
#define WRSYNTAX    86
257
0
#define CREATEREQ   87
258
3.78k
#define NOTIFGROUP  88
259
8.29k
#define MANDATORYGROUPS 89
260
30.1k
#define GROUP     90
261
38.5k
#define OBJECT      91
262
2.94k
#define IDENTIFIER  92
263
36.5k
#define CHOICE      93
264
28.5k
#define LEFTSQBRACK 95
265
454k
#define RIGHTSQBRACK  96
266
4.85k
#define IMPLICIT    97
267
93.9k
#define APPSYNTAX (98 | SYNTAX_MASK)
268
93.7k
#define OBJSYNTAX (99 | SYNTAX_MASK)
269
94.1k
#define SIMPLESYNTAX  (100 | SYNTAX_MASK)
270
94.1k
#define OBJNAME   (101 | SYNTAX_MASK)
271
94.4k
#define NOTIFNAME (102 | SYNTAX_MASK)
272
308
#define VARIABLES 103
273
100k
#define UNSIGNED32  (104 | SYNTAX_MASK)
274
98.9k
#define INTEGER32 (105 | SYNTAX_MASK)
275
4.45k
#define OBJIDENTITY 106
276
/*
277
 * Beware of reaching SYNTAX_MASK (0x80) 
278
 */
279
280
struct tok {
281
    const char     *name;       /* token name */
282
    int             len;        /* length not counting nul */
283
    int             token;      /* value */
284
    int             hash;       /* hash of name */
285
    struct tok     *next;       /* pointer to next in hash table */
286
};
287
288
289
static struct tok tokens[] = {
290
    {"obsolete", sizeof("obsolete") - 1, OBSOLETE}
291
    ,
292
    {"Opaque", sizeof("Opaque") - 1, KW_OPAQUE}
293
    ,
294
    {"optional", sizeof("optional") - 1, KW_OPTIONAL}
295
    ,
296
    {"LAST-UPDATED", sizeof("LAST-UPDATED") - 1, LASTUPDATED}
297
    ,
298
    {"ORGANIZATION", sizeof("ORGANIZATION") - 1, ORGANIZATION}
299
    ,
300
    {"CONTACT-INFO", sizeof("CONTACT-INFO") - 1, CONTACTINFO}
301
    ,
302
    {"MODULE-IDENTITY", sizeof("MODULE-IDENTITY") - 1, MODULEIDENTITY}
303
    ,
304
    {"MODULE-COMPLIANCE", sizeof("MODULE-COMPLIANCE") - 1, COMPLIANCE}
305
    ,
306
    {"DEFINITIONS", sizeof("DEFINITIONS") - 1, DEFINITIONS}
307
    ,
308
    {"END", sizeof("END") - 1, END}
309
    ,
310
    {"AUGMENTS", sizeof("AUGMENTS") - 1, AUGMENTS}
311
    ,
312
    {"not-accessible", sizeof("not-accessible") - 1, NOACCESS}
313
    ,
314
    {"write-only", sizeof("write-only") - 1, WRITEONLY}
315
    ,
316
    {"NsapAddress", sizeof("NsapAddress") - 1, NSAPADDRESS}
317
    ,
318
    {"UNITS", sizeof("Units") - 1, UNITS}
319
    ,
320
    {"REFERENCE", sizeof("REFERENCE") - 1, REFERENCE}
321
    ,
322
    {"NUM-ENTRIES", sizeof("NUM-ENTRIES") - 1, NUM_ENTRIES}
323
    ,
324
    {"BITSTRING", sizeof("BITSTRING") - 1, BITSTRING}
325
    ,
326
    {"BIT", sizeof("BIT") - 1, CONTINUE}
327
    ,
328
    {"BITS", sizeof("BITS") - 1, BITSTRING}
329
    ,
330
    {"Counter64", sizeof("Counter64") - 1, COUNTER64}
331
    ,
332
    {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS}
333
    ,
334
    {"NOTIFICATION-TYPE", sizeof("NOTIFICATION-TYPE") - 1, NOTIFTYPE}
335
    ,
336
    {"OBJECT-GROUP", sizeof("OBJECT-GROUP") - 1, OBJGROUP}
337
    ,
338
    {"OBJECT-IDENTITY", sizeof("OBJECT-IDENTITY") - 1, OBJIDENTITY}
339
    ,
340
    {"IDENTIFIER", sizeof("IDENTIFIER") - 1, IDENTIFIER}
341
    ,
342
    {"OBJECT", sizeof("OBJECT") - 1, OBJECT}
343
    ,
344
    {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR}
345
    ,
346
    {"Gauge", sizeof("Gauge") - 1, GAUGE}
347
    ,
348
    {"Gauge32", sizeof("Gauge32") - 1, GAUGE}
349
    ,
350
    {"Unsigned32", sizeof("Unsigned32") - 1, UNSIGNED32}
351
    ,
352
    {"read-write", sizeof("read-write") - 1, READWRITE}
353
    ,
354
    {"read-create", sizeof("read-create") - 1, READCREATE}
355
    ,
356
    {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR}
357
    ,
358
    {"OCTET", sizeof("OCTET") - 1, CONTINUE}
359
    ,
360
    {"OF", sizeof("OF") - 1, OF}
361
    ,
362
    {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE}
363
    ,
364
    {"NULL", sizeof("NULL") - 1, NUL}
365
    ,
366
    {"IpAddress", sizeof("IpAddress") - 1, IPADDR}
367
    ,
368
    {"UInteger32", sizeof("UInteger32") - 1, UINTEGER32}
369
    ,
370
    {"INTEGER", sizeof("INTEGER") - 1, INTEGER}
371
    ,
372
    {"Integer32", sizeof("Integer32") - 1, INTEGER32}
373
    ,
374
    {"Counter", sizeof("Counter") - 1, COUNTER}
375
    ,
376
    {"Counter32", sizeof("Counter32") - 1, COUNTER}
377
    ,
378
    {"read-only", sizeof("read-only") - 1, READONLY}
379
    ,
380
    {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION}
381
    ,
382
    {"INDEX", sizeof("INDEX") - 1, INDEX}
383
    ,
384
    {"DEFVAL", sizeof("DEFVAL") - 1, DEFVAL}
385
    ,
386
    {"deprecated", sizeof("deprecated") - 1, DEPRECATED}
387
    ,
388
    {"SIZE", sizeof("SIZE") - 1, SIZE}
389
    ,
390
    {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS}
391
    ,
392
    {"ACCESS", sizeof("ACCESS") - 1, ACCESS}
393
    ,
394
    {"mandatory", sizeof("mandatory") - 1, MANDATORY}
395
    ,
396
    {"current", sizeof("current") - 1, CURRENT}
397
    ,
398
    {"STATUS", sizeof("STATUS") - 1, STATUS}
399
    ,
400
    {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX}
401
    ,
402
    {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE}
403
    ,
404
    {"TRAP-TYPE", sizeof("TRAP-TYPE") - 1, TRAPTYPE}
405
    ,
406
    {"ENTERPRISE", sizeof("ENTERPRISE") - 1, ENTERPRISE}
407
    ,
408
    {"BEGIN", sizeof("BEGIN") - 1, BEGIN}
409
    ,
410
    {"IMPORTS", sizeof("IMPORTS") - 1, IMPORTS}
411
    ,
412
    {"EXPORTS", sizeof("EXPORTS") - 1, EXPORTS}
413
    ,
414
    {"accessible-for-notify", sizeof("accessible-for-notify") - 1,
415
     ACCNOTIFY}
416
    ,
417
    {"TEXTUAL-CONVENTION", sizeof("TEXTUAL-CONVENTION") - 1, CONVENTION}
418
    ,
419
    {"NOTIFICATION-GROUP", sizeof("NOTIFICATION-GROUP") - 1, NOTIFGROUP}
420
    ,
421
    {"DISPLAY-HINT", sizeof("DISPLAY-HINT") - 1, DISPLAYHINT}
422
    ,
423
    {"FROM", sizeof("FROM") - 1, FROM}
424
    ,
425
    {"AGENT-CAPABILITIES", sizeof("AGENT-CAPABILITIES") - 1, AGENTCAP}
426
    ,
427
    {"MACRO", sizeof("MACRO") - 1, MACRO}
428
    ,
429
    {"IMPLIED", sizeof("IMPLIED") - 1, IMPLIED}
430
    ,
431
    {"SUPPORTS", sizeof("SUPPORTS") - 1, SUPPORTS}
432
    ,
433
    {"INCLUDES", sizeof("INCLUDES") - 1, INCLUDES}
434
    ,
435
    {"VARIATION", sizeof("VARIATION") - 1, VARIATION}
436
    ,
437
    {"REVISION", sizeof("REVISION") - 1, REVISION}
438
    ,
439
    {"not-implemented", sizeof("not-implemented") - 1, NOTIMPL}
440
    ,
441
    {"OBJECTS", sizeof("OBJECTS") - 1, OBJECTS}
442
    ,
443
    {"NOTIFICATIONS", sizeof("NOTIFICATIONS") - 1, NOTIFICATIONS}
444
    ,
445
    {"MODULE", sizeof("MODULE") - 1, MODULE}
446
    ,
447
    {"MIN-ACCESS", sizeof("MIN-ACCESS") - 1, MINACCESS}
448
    ,
449
    {"PRODUCT-RELEASE", sizeof("PRODUCT-RELEASE") - 1, PRODREL}
450
    ,
451
    {"WRITE-SYNTAX", sizeof("WRITE-SYNTAX") - 1, WRSYNTAX}
452
    ,
453
    {"CREATION-REQUIRES", sizeof("CREATION-REQUIRES") - 1, CREATEREQ}
454
    ,
455
    {"MANDATORY-GROUPS", sizeof("MANDATORY-GROUPS") - 1, MANDATORYGROUPS}
456
    ,
457
    {"GROUP", sizeof("GROUP") - 1, GROUP}
458
    ,
459
    {"CHOICE", sizeof("CHOICE") - 1, CHOICE}
460
    ,
461
    {"IMPLICIT", sizeof("IMPLICIT") - 1, IMPLICIT}
462
    ,
463
    {"ObjectSyntax", sizeof("ObjectSyntax") - 1, OBJSYNTAX}
464
    ,
465
    {"SimpleSyntax", sizeof("SimpleSyntax") - 1, SIMPLESYNTAX}
466
    ,
467
    {"ApplicationSyntax", sizeof("ApplicationSyntax") - 1, APPSYNTAX}
468
    ,
469
    {"ObjectName", sizeof("ObjectName") - 1, OBJNAME}
470
    ,
471
    {"NotificationName", sizeof("NotificationName") - 1, NOTIFNAME}
472
    ,
473
    {"VARIABLES", sizeof("VARIABLES") - 1, VARIABLES}
474
    ,
475
    {NULL}
476
};
477
478
static struct module_compatability *module_map_head;
479
static struct module_compatability module_map[] = {
480
    {"RFC1065-SMI", "RFC1155-SMI", NULL, 0},
481
    {"RFC1066-MIB", "RFC1156-MIB", NULL, 0},
482
    /*
483
     * 'mib' -> 'mib-2' 
484
     */
485
    {"RFC1156-MIB", "RFC1158-MIB", NULL, 0},
486
    /*
487
     * 'snmpEnableAuthTraps' -> 'snmpEnableAuthenTraps' 
488
     */
489
    {"RFC1158-MIB", "RFC1213-MIB", NULL, 0},
490
    /*
491
     * 'nullOID' -> 'zeroDotZero' 
492
     */
493
    {"RFC1155-SMI", "SNMPv2-SMI", NULL, 0},
494
    {"RFC1213-MIB", "SNMPv2-SMI", "mib-2", 0},
495
    {"RFC1213-MIB", "SNMPv2-MIB", "sys", 3},
496
    {"RFC1213-MIB", "IF-MIB", "if", 2},
497
    {"RFC1213-MIB", "IP-MIB", "ip", 2},
498
    {"RFC1213-MIB", "IP-MIB", "icmp", 4},
499
    {"RFC1213-MIB", "TCP-MIB", "tcp", 3},
500
    {"RFC1213-MIB", "UDP-MIB", "udp", 3},
501
    {"RFC1213-MIB", "SNMPv2-SMI", "transmission", 0},
502
    {"RFC1213-MIB", "SNMPv2-MIB", "snmp", 4},
503
    {"RFC1231-MIB", "TOKENRING-MIB", NULL, 0},
504
    {"RFC1271-MIB", "RMON-MIB", NULL, 0},
505
    {"RFC1286-MIB", "SOURCE-ROUTING-MIB", "dot1dSr", 7},
506
    {"RFC1286-MIB", "BRIDGE-MIB", NULL, 0},
507
    {"RFC1315-MIB", "FRAME-RELAY-DTE-MIB", NULL, 0},
508
    {"RFC1316-MIB", "CHARACTER-MIB", NULL, 0},
509
    {"RFC1406-MIB", "DS1-MIB", NULL, 0},
510
    {"RFC-1213", "RFC1213-MIB", NULL, 0},
511
};
512
513
388k
#define MODULE_NOT_FOUND  0
514
21.0k
#define MODULE_LOADED_OK  1
515
6.91k
#define MODULE_ALREADY_LOADED 2
516
/*
517
 * #define MODULE_LOAD_FAILED   3       
518
 */
519
0
#define MODULE_LOAD_FAILED  MODULE_NOT_FOUND
520
33.6k
#define MODULE_SYNTAX_ERROR     4
521
522
int gMibError = 0,gLoop = 0;
523
static char *gpMibErrorString;
524
char gMibNames[STRINGMAX];
525
526
1.38M
#define HASHSIZE        32
527
1.38M
#define BUCKET(x)       (x & (HASHSIZE-1))
528
529
7.83M
#define NHASHSIZE    128
530
4.09M
#define NBUCKET(x)   (x & (NHASHSIZE-1))
531
532
static struct tok *buckets[HASHSIZE];
533
534
static struct node *nbuckets[NHASHSIZE];
535
static struct tree *tbuckets[NHASHSIZE];
536
static struct module *module_head = NULL;
537
538
static struct node *orphan_nodes = NULL;
539
NETSNMP_IMPORT struct tree *tree_head;
540
struct tree        *tree_head = NULL;
541
542
1.06k
#define NUMBER_OF_ROOT_NODES  3
543
static struct module_import root_imports[NUMBER_OF_ROOT_NODES];
544
545
static int      current_module = 0;
546
static int      max_module = 0;
547
static int      first_err_module = 1;
548
static char    *last_err_module = NULL; /* no repeats on "Cannot find module..." */
549
550
static void     tree_from_node(struct tree *tp, struct node *np);
551
static void     do_subtree(struct tree *, struct node **);
552
static void     do_linkup(struct module *, struct node *);
553
static void     dump_module_list(void);
554
static int      get_token(FILE *, char *, int);
555
static int      parseQuoteString(FILE *, char *, int);
556
static int      tossObjectIdentifier(FILE *);
557
static int      name_hash(const char *);
558
static void     init_node_hash(struct node *);
559
static void     print_error(const char *, const char *, int);
560
static void     free_tree(struct tree *);
561
static void     free_partial_tree(struct tree *, int);
562
static void     free_node(struct node *);
563
static void     build_translation_table(void);
564
static void     init_tree_roots(void);
565
static void     merge_anon_children(struct tree *, struct tree *);
566
static void     unlink_tbucket(struct tree *);
567
static void     unlink_tree(struct tree *);
568
static struct node *parse_objectid(FILE *, char *);
569
static int      get_tc(const char *, int, int *, struct enum_list **,
570
                       struct range_list **, char **);
571
static int      get_tc_index(const char *, int);
572
static struct enum_list *parse_enumlist(FILE *, struct enum_list **);
573
static struct range_list *parse_ranges(FILE * fp, struct range_list **);
574
static struct node *parse_asntype(FILE *, char *, int *, char *);
575
static struct node *parse_objecttype(FILE *, char *);
576
static struct node *parse_objectgroup(FILE *, char *, int,
577
                                      struct objgroup **);
578
static struct node *parse_notificationDefinition(FILE *, char *);
579
static struct node *parse_trapDefinition(FILE *, char *);
580
static struct node *parse_compliance(FILE *, char *);
581
static struct node *parse_capabilities(FILE *, char *);
582
static struct node *parse_moduleIdentity(FILE *, char *);
583
static struct node *parse_macro(FILE *, char *);
584
static void     parse_imports(FILE *);
585
static struct node *parse(FILE *);
586
587
static int     read_module_internal(const char *);
588
static int     read_module_replacements(const char *);
589
static int     read_import_replacements(const char *,
590
                                         struct module_import *);
591
592
static struct node *merge_parse_objectid(struct node *, FILE *, char *);
593
static struct index_list *getIndexes(FILE * fp, struct index_list **);
594
static struct varbind_list *getVarbinds(FILE * fp, struct varbind_list **);
595
static void     free_indexes(struct index_list **);
596
static void     free_varbinds(struct varbind_list **);
597
static void     free_ranges(struct range_list **);
598
static void     free_enums(struct enum_list **);
599
static struct range_list *copy_ranges(struct range_list *);
600
static struct enum_list *copy_enums(struct enum_list *);
601
602
static u_int    compute_match(const char *search_base, const char *key);
603
604
void
605
snmp_mib_toggle_options_usage(const char *lead, FILE * outf)
606
0
{
607
0
    fprintf(outf, "%su:  %sallow the use of underlines in MIB symbols\n",
608
0
            lead, ((netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
609
0
             NETSNMP_DS_LIB_MIB_PARSE_LABEL)) ?
610
0
       "dis" : ""));
611
0
    fprintf(outf, "%sc:  %sallow the use of \"--\" to terminate comments\n",
612
0
            lead, ((netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
613
0
             NETSNMP_DS_LIB_MIB_COMMENT_TERM)) ?
614
0
       "" : "dis"));
615
616
0
    fprintf(outf, "%sd:  %ssave the DESCRIPTIONs of the MIB objects\n",
617
0
            lead, ((netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
618
0
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) ?
619
0
       "do not " : ""));
620
621
0
    fprintf(outf, "%se:  disable errors when MIB symbols conflict\n", lead);
622
623
0
    fprintf(outf, "%sw:  enable warnings when MIB symbols conflict\n", lead);
624
625
0
    fprintf(outf, "%sW:  enable detailed warnings when MIB symbols conflict\n",
626
0
            lead);
627
628
0
    fprintf(outf, "%sR:  replace MIB symbols from latest module\n", lead);
629
0
}
630
631
char           *
632
snmp_mib_toggle_options(char *options)
633
57
{
634
57
    if (options) {
635
2.32k
        while (*options) {
636
2.30k
            switch (*options) {
637
404
            case 'u':
638
404
                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL,
639
404
                               !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
640
404
                                               NETSNMP_DS_LIB_MIB_PARSE_LABEL));
641
404
                break;
642
643
576
            case 'c':
644
576
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
645
576
            NETSNMP_DS_LIB_MIB_COMMENT_TERM);
646
576
                break;
647
648
262
            case 'e':
649
262
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
650
262
            NETSNMP_DS_LIB_MIB_ERRORS);
651
262
                break;
652
653
278
            case 'w':
654
278
                netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
655
278
           NETSNMP_DS_LIB_MIB_WARNINGS, 1);
656
278
                break;
657
658
330
            case 'W':
659
330
                netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
660
330
           NETSNMP_DS_LIB_MIB_WARNINGS, 2);
661
330
                break;
662
663
275
            case 'd':
664
275
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 
665
275
            NETSNMP_DS_LIB_SAVE_MIB_DESCRS);
666
275
                break;
667
668
147
            case 'R':
669
147
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 
670
147
            NETSNMP_DS_LIB_MIB_REPLACE);
671
147
                break;
672
673
29
            default:
674
                /*
675
                 * return at the unknown option 
676
                 */
677
29
                return options;
678
2.30k
            }
679
2.27k
            options++;
680
2.27k
        }
681
57
    }
682
28
    return NULL;
683
57
}
684
685
static int
686
name_hash(const char *name)
687
4.41M
{
688
4.41M
    int             hash = 0;
689
4.41M
    const char     *cp;
690
691
4.41M
    if (!name)
692
0
        return 0;
693
23.8M
    for (cp = name; *cp; cp++)
694
19.4M
        hash += tolower((unsigned char)(*cp));
695
4.41M
    return (hash);
696
4.41M
}
697
698
void
699
netsnmp_init_mib_internals(void)
700
213k
{
701
213k
    register struct tok *tp;
702
213k
    register int    b, i;
703
213k
    int             max_modc;
704
705
213k
    if (tree_head)
706
210k
        return;
707
708
    /*
709
     * Set up hash list of pre-defined tokens
710
     */
711
3.48k
    memset(buckets, 0, sizeof(buckets));
712
324k
    for (tp = tokens; tp->name; tp++) {
713
320k
        tp->hash = name_hash(tp->name);
714
320k
        b = BUCKET(tp->hash);
715
320k
        if (buckets[b])
716
209k
            tp->next = buckets[b];      /* BUG ??? */
717
320k
        buckets[b] = tp;
718
320k
    }
719
720
    /*
721
     * Initialise other internal structures
722
     */
723
724
3.48k
    max_modc = sizeof(module_map) / sizeof(module_map[0]) - 1;
725
76.7k
    for (i = 0; i < max_modc; ++i)
726
73.2k
        module_map[i].next = &(module_map[i + 1]);
727
3.48k
    module_map[max_modc].next = NULL;
728
3.48k
    module_map_head = module_map;
729
730
3.48k
    memset(nbuckets, 0, sizeof(nbuckets));
731
3.48k
    memset(tbuckets, 0, sizeof(tbuckets));
732
3.48k
    free(tclist);
733
3.48k
    tc_alloc = TC_INCR;
734
3.48k
    tclist = calloc(tc_alloc, sizeof(struct tc));
735
3.48k
    build_translation_table();
736
3.48k
    init_tree_roots();          /* Set up initial roots */
737
    /*
738
     * Relies on 'add_mibdir' having set up the modules 
739
     */
740
3.48k
}
741
742
#ifndef NETSNMP_NO_LEGACY_DEFINITIONS
743
void
744
init_mib_internals(void)
745
0
{
746
0
    netsnmp_init_mib_internals();
747
0
}
748
#endif
749
750
static void
751
init_node_hash(struct node *nodes)
752
14.1k
{
753
14.1k
    struct node    *np, *nextp;
754
14.1k
    int             hash;
755
756
14.1k
    memset(nbuckets, 0, sizeof(nbuckets));
757
329k
    for (np = nodes; np;) {
758
315k
        nextp = np->next;
759
315k
        hash = NBUCKET(name_hash(np->parent));
760
315k
        np->next = nbuckets[hash];
761
315k
        nbuckets[hash] = np;
762
315k
        np = nextp;
763
315k
    }
764
14.1k
}
765
766
static int      erroneousMibs = 0;
767
768
netsnmp_feature_child_of(parse_get_error_count, netsnmp_unused);
769
#ifndef NETSNMP_FEATURE_REMOVE_PARSE_GET_ERROR_COUNT
770
int
771
get_mib_parse_error_count(void)
772
0
{
773
0
    return erroneousMibs;
774
0
}
775
#endif /* NETSNMP_FEATURE_REMOVE_PARSE_GET_ERROR_COUNT */
776
777
778
static void
779
print_error(const char *str, const char *token, int type)
780
484k
{
781
484k
    erroneousMibs++;
782
484k
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
783
484k
                                NETSNMP_DS_LIB_MIB_ERRORS))
784
300k
  return;
785
183k
    DEBUGMSGTL(("parse-mibs", "\n"));
786
183k
    if (type == ENDOFFILE)
787
451
        snmp_log(LOG_ERR, "%s (EOF): At line %d in %s\n", str, mibLine,
788
451
                 File);
789
183k
    else if (token && *token)
790
182k
        snmp_log(LOG_ERR, "%s (%s): At line %d in %s\n", str, token,
791
182k
                 mibLine, File);
792
512
    else
793
512
        snmp_log(LOG_ERR, "%s: At line %d in %s\n", str, mibLine, File);
794
183k
}
795
796
static void
797
print_module_not_found(const char *cp)
798
184k
{
799
184k
    if (first_err_module) {
800
11
        snmp_log(LOG_ERR, "MIB search path: %s\n",
801
11
                           netsnmp_get_mib_directory());
802
11
        first_err_module = 0;
803
11
    }
804
184k
    if (!last_err_module || strcmp(cp, last_err_module))
805
165k
        print_error("Cannot find module", cp, CONTINUE);
806
184k
    if (last_err_module)
807
178k
        free(last_err_module);
808
184k
    last_err_module = strdup(cp);
809
184k
}
810
811
static struct node *
812
alloc_node(int modid)
813
339k
{
814
339k
    struct node    *np;
815
816
339k
    np = calloc(1, sizeof(struct node));
817
339k
    if (!np)
818
0
        return NULL;
819
820
339k
    np->tc_index = -1;
821
339k
    np->modid = modid;
822
339k
    np->filename = strdup(File);
823
339k
    np->lineno = mibLine;
824
825
339k
    return np;
826
339k
}
827
828
static void
829
unlink_tbucket(struct tree *tp)
830
57.6k
{
831
57.6k
    int             hash = NBUCKET(name_hash(tp->label));
832
57.6k
    struct tree    *otp = NULL, *ntp = tbuckets[hash];
833
834
93.2k
    while (ntp && ntp != tp) {
835
35.6k
        otp = ntp;
836
35.6k
        ntp = ntp->next;
837
35.6k
    }
838
57.6k
    if (!ntp)
839
0
        snmp_log(LOG_EMERG, "Can't find %s in tbuckets\n", tp->label);
840
57.6k
    else if (otp)
841
13.2k
        otp->next = ntp->next;
842
44.4k
    else
843
44.4k
        tbuckets[hash] = tp->next;
844
57.6k
}
845
846
static void
847
unlink_tree(struct tree *tp)
848
36.9k
{
849
36.9k
    struct tree    *otp = NULL, *ntp = tp->parent;
850
851
36.9k
    if (!ntp) {                 /* this tree has no parent */
852
10.4k
        DEBUGMSGTL(("unlink_tree", "Tree node %s has no parent\n",
853
10.4k
                    tp->label));
854
26.5k
    } else {
855
26.5k
        ntp = ntp->child_list;
856
857
720k
        while (ntp && ntp != tp) {
858
693k
            otp = ntp;
859
693k
            ntp = ntp->next_peer;
860
693k
        }
861
26.5k
        if (!ntp)
862
0
            snmp_log(LOG_EMERG, "Can't find %s in %s's children\n",
863
0
                     tp->label, tp->parent->label);
864
26.5k
        else if (otp)
865
2.87k
            otp->next_peer = ntp->next_peer;
866
23.6k
        else
867
23.6k
            tp->parent->child_list = tp->next_peer;
868
26.5k
    }
869
870
36.9k
    if (tree_head == tp)
871
10.4k
        tree_head = tp->next_peer;
872
36.9k
}
873
874
static void
875
free_partial_tree(struct tree *tp, int keep_label)
876
167k
{
877
167k
    if (!tp)
878
0
        return;
879
880
    /*
881
     * remove the data from this tree node 
882
     */
883
167k
    free_enums(&tp->enums);
884
167k
    free_ranges(&tp->ranges);
885
167k
    free_indexes(&tp->indexes);
886
167k
    free_varbinds(&tp->varbinds);
887
167k
    if (!keep_label)
888
167k
        SNMP_FREE(tp->label);
889
167k
    SNMP_FREE(tp->hint);
890
167k
    SNMP_FREE(tp->units);
891
167k
    SNMP_FREE(tp->description);
892
167k
    SNMP_FREE(tp->reference);
893
167k
    SNMP_FREE(tp->augments);
894
167k
    SNMP_FREE(tp->defaultValue);
895
167k
}
896
897
/*
898
 * free a tree node. Note: the node must already have been unlinked
899
 * from the tree when calling this routine
900
 */
901
static void
902
free_tree(struct tree *Tree)
903
43.8k
{
904
43.8k
    if (!Tree)
905
0
        return;
906
907
43.8k
    unlink_tbucket(Tree);
908
43.8k
    free_partial_tree(Tree, FALSE);
909
43.8k
    if (Tree->module_list != &Tree->modid)
910
526
        free(Tree->module_list);
911
43.8k
    free(Tree);
912
43.8k
}
913
914
static void
915
free_node(struct node *np)
916
264k
{
917
264k
    if (!np)
918
103
        return;
919
920
264k
    free_enums(&np->enums);
921
264k
    free_ranges(&np->ranges);
922
264k
    free_indexes(&np->indexes);
923
264k
    free_varbinds(&np->varbinds);
924
264k
    free(np->label);
925
264k
    free(np->hint);
926
264k
    free(np->units);
927
264k
    free(np->description);
928
264k
    free(np->reference);
929
264k
    free(np->defaultValue);
930
264k
    free(np->parent);
931
264k
    free(np->augments);
932
264k
    free(np->filename);
933
264k
    free(np);
934
264k
}
935
936
static void
937
print_range_value(FILE * fp, int type, struct range_list * rp)
938
0
{
939
0
    switch (type) {
940
0
    case TYPE_INTEGER:
941
0
    case TYPE_INTEGER32:
942
0
        if (rp->low == rp->high)
943
0
            fprintf(fp, "%d", rp->low);
944
0
        else
945
0
            fprintf(fp, "%d..%d", rp->low, rp->high);
946
0
        break;
947
0
    case TYPE_UNSIGNED32:
948
0
    case TYPE_OCTETSTR:
949
0
    case TYPE_GAUGE:
950
0
    case TYPE_UINTEGER:
951
0
        if (rp->low == rp->high)
952
0
            fprintf(fp, "%u", (unsigned)rp->low);
953
0
        else
954
0
            fprintf(fp, "%u..%u", (unsigned)rp->low, (unsigned)rp->high);
955
0
        break;
956
0
    default:
957
        /* No other range types allowed */
958
0
        break;
959
0
    }
960
0
}
961
962
#ifdef TEST
963
static void
964
print_nodes(FILE * fp, struct node *root)
965
{
966
    struct enum_list *ep;
967
    struct index_list *ip;
968
    struct varbind_list *vp;
969
    struct node    *np;
970
971
    for (np = root; np; np = np->next) {
972
        fprintf(fp, "%s ::= { %s %ld } (%d)\n", np->label, np->parent,
973
                np->subid, np->type);
974
        if (np->tc_index >= 0)
975
            fprintf(fp, "  TC = %s\n", tclist[np->tc_index].descriptor);
976
        if (np->enums) {
977
            fprintf(fp, "  Enums: \n");
978
            for (ep = np->enums; ep; ep = ep->next) {
979
                fprintf(fp, "    %s(%d)\n", ep->label, ep->value);
980
            }
981
        }
982
        if (np->ranges) {
983
            struct range_list *rp;
984
            fprintf(fp, "  Ranges: ");
985
            for (rp = np->ranges; rp; rp = rp->next) {
986
                fprintf(fp, "\n    ");
987
                print_range_value(fp, np->type, rp);
988
            }
989
            fprintf(fp, "\n");
990
        }
991
        if (np->indexes) {
992
            fprintf(fp, "  Indexes: \n");
993
            for (ip = np->indexes; ip; ip = ip->next) {
994
                fprintf(fp, "    %s\n", ip->ilabel);
995
            }
996
        }
997
        if (np->augments)
998
            fprintf(fp, "  Augments: %s\n", np->augments);
999
        if (np->varbinds) {
1000
            fprintf(fp, "  Varbinds: \n");
1001
            for (vp = np->varbinds; vp; vp = vp->next) {
1002
                fprintf(fp, "    %s\n", vp->vblabel);
1003
            }
1004
        }
1005
        if (np->hint)
1006
            fprintf(fp, "  Hint: %s\n", np->hint);
1007
        if (np->units)
1008
            fprintf(fp, "  Units: %s\n", np->units);
1009
        if (np->defaultValue)
1010
            fprintf(fp, "  DefaultValue: %s\n", np->defaultValue);
1011
    }
1012
}
1013
#endif
1014
1015
void
1016
print_subtree(FILE * f, struct tree *tree, int count)
1017
0
{
1018
0
    struct tree    *tp;
1019
0
    int             i;
1020
0
    char            modbuf[256];
1021
1022
0
    for (i = 0; i < count; i++)
1023
0
        fprintf(f, "  ");
1024
0
    fprintf(f, "Children of %s(%ld):\n", tree->label, tree->subid);
1025
0
    count++;
1026
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1027
0
        for (i = 0; i < count; i++)
1028
0
            fprintf(f, "  ");
1029
0
        fprintf(f, "%s:%s(%ld) type=%d",
1030
0
                module_name(tp->module_list[0], modbuf),
1031
0
                tp->label, tp->subid, tp->type);
1032
0
        if (tp->tc_index != -1)
1033
0
            fprintf(f, " tc=%d", tp->tc_index);
1034
0
        if (tp->hint)
1035
0
            fprintf(f, " hint=%s", tp->hint);
1036
0
        if (tp->units)
1037
0
            fprintf(f, " units=%s", tp->units);
1038
0
        if (tp->number_modules > 1) {
1039
0
            fprintf(f, " modules:");
1040
0
            for (i = 1; i < tp->number_modules; i++)
1041
0
                fprintf(f, " %s", module_name(tp->module_list[i], modbuf));
1042
0
        }
1043
0
        fprintf(f, "\n");
1044
0
    }
1045
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1046
0
        if (tp->child_list)
1047
0
            print_subtree(f, tp, count);
1048
0
    }
1049
0
}
1050
1051
void
1052
print_ascii_dump_tree(FILE * f, struct tree *tree, int count)
1053
0
{
1054
0
    struct tree    *tp;
1055
1056
0
    count++;
1057
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1058
0
        fprintf(f, "%s OBJECT IDENTIFIER ::= { %s %ld }\n", tp->label,
1059
0
                tree->label, tp->subid);
1060
0
    }
1061
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1062
0
        if (tp->child_list)
1063
0
            print_ascii_dump_tree(f, tp, count);
1064
0
    }
1065
0
}
1066
1067
static int      translation_table[256];
1068
1069
static void
1070
build_translation_table(void)
1071
3.48k
{
1072
3.48k
    int             count;
1073
1074
896k
    for (count = 0; count < 256; count++) {
1075
892k
        switch (count) {
1076
3.48k
        case OBJID:
1077
3.48k
            translation_table[count] = TYPE_OBJID;
1078
3.48k
            break;
1079
3.48k
        case OCTETSTR:
1080
3.48k
            translation_table[count] = TYPE_OCTETSTR;
1081
3.48k
            break;
1082
3.48k
        case INTEGER:
1083
3.48k
            translation_table[count] = TYPE_INTEGER;
1084
3.48k
            break;
1085
3.48k
        case NETADDR:
1086
3.48k
            translation_table[count] = TYPE_NETADDR;
1087
3.48k
            break;
1088
3.48k
        case IPADDR:
1089
3.48k
            translation_table[count] = TYPE_IPADDR;
1090
3.48k
            break;
1091
3.48k
        case COUNTER:
1092
3.48k
            translation_table[count] = TYPE_COUNTER;
1093
3.48k
            break;
1094
3.48k
        case GAUGE:
1095
3.48k
            translation_table[count] = TYPE_GAUGE;
1096
3.48k
            break;
1097
3.48k
        case TIMETICKS:
1098
3.48k
            translation_table[count] = TYPE_TIMETICKS;
1099
3.48k
            break;
1100
3.48k
        case KW_OPAQUE:
1101
3.48k
            translation_table[count] = TYPE_OPAQUE;
1102
3.48k
            break;
1103
3.48k
        case NUL:
1104
3.48k
            translation_table[count] = TYPE_NULL;
1105
3.48k
            break;
1106
3.48k
        case COUNTER64:
1107
3.48k
            translation_table[count] = TYPE_COUNTER64;
1108
3.48k
            break;
1109
3.48k
        case BITSTRING:
1110
3.48k
            translation_table[count] = TYPE_BITSTRING;
1111
3.48k
            break;
1112
3.48k
        case NSAPADDRESS:
1113
3.48k
            translation_table[count] = TYPE_NSAPADDRESS;
1114
3.48k
            break;
1115
3.48k
        case INTEGER32:
1116
3.48k
            translation_table[count] = TYPE_INTEGER32;
1117
3.48k
            break;
1118
3.48k
        case UINTEGER32:
1119
3.48k
            translation_table[count] = TYPE_UINTEGER;
1120
3.48k
            break;
1121
3.48k
        case UNSIGNED32:
1122
3.48k
            translation_table[count] = TYPE_UNSIGNED32;
1123
3.48k
            break;
1124
3.48k
        case TRAPTYPE:
1125
3.48k
            translation_table[count] = TYPE_TRAPTYPE;
1126
3.48k
            break;
1127
3.48k
        case NOTIFTYPE:
1128
3.48k
            translation_table[count] = TYPE_NOTIFTYPE;
1129
3.48k
            break;
1130
3.48k
        case NOTIFGROUP:
1131
3.48k
            translation_table[count] = TYPE_NOTIFGROUP;
1132
3.48k
            break;
1133
3.48k
        case OBJGROUP:
1134
3.48k
            translation_table[count] = TYPE_OBJGROUP;
1135
3.48k
            break;
1136
3.48k
        case MODULEIDENTITY:
1137
3.48k
            translation_table[count] = TYPE_MODID;
1138
3.48k
            break;
1139
3.48k
        case OBJIDENTITY:
1140
3.48k
            translation_table[count] = TYPE_OBJIDENTITY;
1141
3.48k
            break;
1142
3.48k
        case AGENTCAP:
1143
3.48k
            translation_table[count] = TYPE_AGENTCAP;
1144
3.48k
            break;
1145
3.48k
        case COMPLIANCE:
1146
3.48k
            translation_table[count] = TYPE_MODCOMP;
1147
3.48k
            break;
1148
809k
        default:
1149
809k
            translation_table[count] = TYPE_OTHER;
1150
809k
            break;
1151
892k
        }
1152
892k
    }
1153
3.48k
}
1154
1155
static void
1156
init_tree_roots(void)
1157
3.48k
{
1158
3.48k
    struct tree    *tp, *lasttp;
1159
3.48k
    int             base_modid;
1160
3.48k
    int             hash;
1161
1162
3.48k
    base_modid = which_module("SNMPv2-SMI");
1163
3.48k
    if (base_modid == -1)
1164
3.48k
        base_modid = which_module("RFC1155-SMI");
1165
3.48k
    if (base_modid == -1)
1166
3.48k
        base_modid = which_module("RFC1213-MIB");
1167
1168
    /*
1169
     * build root node 
1170
     */
1171
3.48k
    tp = calloc(1, sizeof(struct tree));
1172
3.48k
    if (tp == NULL)
1173
0
        return;
1174
3.48k
    tp->label = strdup("joint-iso-ccitt");
1175
3.48k
    tp->modid = base_modid;
1176
3.48k
    tp->number_modules = 1;
1177
3.48k
    tp->module_list = &(tp->modid);
1178
3.48k
    tp->subid = 2;
1179
3.48k
    tp->tc_index = -1;
1180
3.48k
    set_function(tp);           /* from mib.c */
1181
3.48k
    hash = NBUCKET(name_hash(tp->label));
1182
3.48k
    tp->next = tbuckets[hash];
1183
3.48k
    tbuckets[hash] = tp;
1184
3.48k
    lasttp = tp;
1185
3.48k
    root_imports[0].label = strdup(tp->label);
1186
3.48k
    root_imports[0].modid = base_modid;
1187
1188
    /*
1189
     * build root node 
1190
     */
1191
3.48k
    tp = calloc(1, sizeof(struct tree));
1192
3.48k
    if (tp == NULL)
1193
0
        return;
1194
3.48k
    tp->next_peer = lasttp;
1195
3.48k
    tp->label = strdup("ccitt");
1196
3.48k
    tp->modid = base_modid;
1197
3.48k
    tp->number_modules = 1;
1198
3.48k
    tp->module_list = &(tp->modid);
1199
3.48k
    tp->subid = 0;
1200
3.48k
    tp->tc_index = -1;
1201
3.48k
    set_function(tp);           /* from mib.c */
1202
3.48k
    hash = NBUCKET(name_hash(tp->label));
1203
3.48k
    tp->next = tbuckets[hash];
1204
3.48k
    tbuckets[hash] = tp;
1205
3.48k
    lasttp = tp;
1206
3.48k
    root_imports[1].label = strdup(tp->label);
1207
3.48k
    root_imports[1].modid = base_modid;
1208
1209
    /*
1210
     * build root node 
1211
     */
1212
3.48k
    tp = calloc(1, sizeof(struct tree));
1213
3.48k
    if (tp == NULL)
1214
0
        return;
1215
3.48k
    tp->next_peer = lasttp;
1216
3.48k
    tp->label = strdup("iso");
1217
3.48k
    tp->modid = base_modid;
1218
3.48k
    tp->number_modules = 1;
1219
3.48k
    tp->module_list = &(tp->modid);
1220
3.48k
    tp->subid = 1;
1221
3.48k
    tp->tc_index = -1;
1222
3.48k
    set_function(tp);           /* from mib.c */
1223
3.48k
    hash = NBUCKET(name_hash(tp->label));
1224
3.48k
    tp->next = tbuckets[hash];
1225
3.48k
    tbuckets[hash] = tp;
1226
3.48k
    lasttp = tp;
1227
3.48k
    root_imports[2].label = strdup(tp->label);
1228
3.48k
    root_imports[2].modid = base_modid;
1229
1230
3.48k
    tree_head = tp;
1231
3.48k
}
1232
1233
#ifdef STRICT_MIB_PARSEING
1234
#define label_compare strcasecmp
1235
#else
1236
1.55G
#define label_compare strcmp
1237
#endif
1238
1239
1240
struct tree    *
1241
find_tree_node(const char *name, int modid)
1242
609k
{
1243
609k
    struct tree    *tp, *headtp;
1244
609k
    int             count, *int_p;
1245
1246
609k
    if (!name || !*name)
1247
40.8k
        return (NULL);
1248
1249
568k
    headtp = tbuckets[NBUCKET(name_hash(name))];
1250
72.7M
    for (tp = headtp; tp; tp = tp->next) {
1251
72.4M
        if (tp->label && !label_compare(tp->label, name)) {
1252
1253
21.8M
            if (modid == -1)    /* Any module */
1254
116k
                return (tp);
1255
1256
21.7M
            for (int_p = tp->module_list, count = 0;
1257
55.2M
                 count < tp->number_modules; ++count, ++int_p)
1258
33.6M
                if (*int_p == modid)
1259
147k
                    return (tp);
1260
21.7M
        }
1261
72.4M
    }
1262
1263
304k
    return (NULL);
1264
568k
}
1265
1266
/*
1267
 * computes a value which represents how close name1 is to name2.
1268
 * * high scores mean a worse match.
1269
 * * (yes, the algorithm sucks!)
1270
 */
1271
2.73k
#define MAX_BAD 0xffffff
1272
1273
static          u_int
1274
compute_match(const char *search_base, const char *key)
1275
1.59k
{
1276
1.59k
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
1277
1.59k
    int             rc;
1278
1.59k
    regex_t         parsetree;
1279
1.59k
    regmatch_t      pmatch;
1280
1.59k
    rc = regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED);
1281
1.59k
    if (rc == 0)
1282
1.50k
        rc = regexec(&parsetree, search_base, 1, &pmatch, 0);
1283
1.59k
    regfree(&parsetree);
1284
1.59k
    if (rc == 0) {
1285
        /*
1286
         * found 
1287
         */
1288
75
        return pmatch.rm_so;
1289
75
    }
1290
#else                           /* use our own wildcard matcher */
1291
    /*
1292
     * first find the longest matching substring (ick) 
1293
     */
1294
    char           *first = NULL, *result = NULL, *entry;
1295
    const char     *position;
1296
    char           *newkey = strdup(key);
1297
    char           *st;
1298
1299
1300
    entry = strtok_r(newkey, "*", &st);
1301
    position = search_base;
1302
    while (entry) {
1303
        result = strcasestr(position, entry);
1304
1305
        if (result == NULL) {
1306
            free(newkey);
1307
            return MAX_BAD;
1308
        }
1309
1310
        if (first == NULL)
1311
            first = result;
1312
1313
        position = result + strlen(entry);
1314
        entry = strtok_r(NULL, "*", &st);
1315
    }
1316
    free(newkey);
1317
    if (result)
1318
        return (first - search_base);
1319
#endif
1320
1321
    /*
1322
     * not found 
1323
     */
1324
1.51k
    return MAX_BAD;
1325
1.59k
}
1326
1327
/*
1328
 * Find the tree node that best matches the pattern string.
1329
 * Use the "reported" flag such that only one match
1330
 * is attempted for every node.
1331
 *
1332
 * Warning! This function may recurse.
1333
 *
1334
 * Caller _must_ invoke clear_tree_flags before first call
1335
 * to this function.  This function may be called multiple times
1336
 * to ensure that the entire tree is traversed.
1337
 */
1338
1339
struct tree    *
1340
find_best_tree_node(const char *pattrn, struct tree *tree_top,
1341
                    u_int * match)
1342
608
{
1343
608
    struct tree    *tp, *best_so_far = NULL, *retptr;
1344
608
    u_int           old_match = MAX_BAD, new_match = MAX_BAD;
1345
1346
608
    if (!pattrn || !*pattrn)
1347
3
        return (NULL);
1348
1349
605
    if (!tree_top)
1350
66
        tree_top = get_tree_head();
1351
1352
2.17k
    for (tp = tree_top; tp; tp = tp->next_peer) {
1353
1.59k
        if (!tp->reported && tp->label)
1354
1.59k
            new_match = compute_match(tp->label, pattrn);
1355
1.59k
        tp->reported = 1;
1356
1357
1.59k
        if (new_match < old_match) {
1358
62
            best_so_far = tp;
1359
62
            old_match = new_match;
1360
62
        }
1361
1.59k
        if (new_match == 0)
1362
23
            break;              /* this is the best result we can get */
1363
1.57k
        if (tp->child_list) {
1364
0
            retptr =
1365
0
                find_best_tree_node(pattrn, tp->child_list, &new_match);
1366
0
            if (new_match < old_match) {
1367
0
                best_so_far = retptr;
1368
0
                old_match = new_match;
1369
0
            }
1370
0
            if (new_match == 0)
1371
0
                break;          /* this is the best result we can get */
1372
0
        }
1373
1.57k
    }
1374
605
    if (match)
1375
0
        *match = old_match;
1376
605
    return (best_so_far);
1377
608
}
1378
1379
1380
static void
1381
merge_anon_children(struct tree *tp1, struct tree *tp2)
1382
                /*
1383
                 * NB: tp1 is the 'anonymous' node 
1384
                 */
1385
14.7k
{
1386
14.7k
    struct tree    *child1, *child2, *previous;
1387
1388
38.2k
    for (child1 = tp1->child_list; child1;) {
1389
1390
23.4k
        for (child2 = tp2->child_list, previous = NULL;
1391
39.5k
             child2; previous = child2, child2 = child2->next_peer) {
1392
1393
29.7k
            if (child1->subid == child2->subid) {
1394
                /*
1395
                 * Found 'matching' children,
1396
                 *  so merge them
1397
                 */
1398
27.1k
                if (!strncmp(child1->label, ANON, ANON_LEN)) {
1399
0
                    merge_anon_children(child1, child2);
1400
1401
0
                    child1->child_list = NULL;
1402
0
                    previous = child1;  /* Finished with 'child1' */
1403
0
                    child1 = child1->next_peer;
1404
0
                    free_tree(previous);
1405
0
                    goto next;
1406
0
                }
1407
1408
27.1k
                else if (!strncmp(child2->label, ANON, ANON_LEN)) {
1409
0
                    merge_anon_children(child2, child1);
1410
1411
0
                    if (previous)
1412
0
                        previous->next_peer = child2->next_peer;
1413
0
                    else
1414
0
                        tp2->child_list = child2->next_peer;
1415
0
                    free_tree(child2);
1416
1417
0
                    previous = child1;  /* Move 'child1' to 'tp2' */
1418
0
                    child1 = child1->next_peer;
1419
0
                    previous->next_peer = tp2->child_list;
1420
0
                    tp2->child_list = previous;
1421
0
                    for (previous = tp2->child_list;
1422
0
                         previous; previous = previous->next_peer)
1423
0
                        previous->parent = tp2;
1424
0
                    goto next;
1425
27.1k
                } else if (!label_compare(child1->label, child2->label)) {
1426
13.4k
                    if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1427
13.4k
             NETSNMP_DS_LIB_MIB_WARNINGS)) {
1428
0
                        snmp_log(LOG_WARNING,
1429
0
                                 "Warning: %s.%ld is both %s and %s (%s)\n",
1430
0
                                 tp2->label, child1->subid, child1->label,
1431
0
                                 child2->label, File);
1432
0
        }
1433
13.4k
                    continue;
1434
13.7k
                } else {
1435
                    /*
1436
                     * Two copies of the same node.
1437
                     * 'child2' adopts the children of 'child1'
1438
                     */
1439
1440
13.7k
                    if (child2->child_list) {
1441
0
                        for (previous = child2->child_list; previous->next_peer; previous = previous->next_peer);       /* Find the end of the list */
1442
0
                        previous->next_peer = child1->child_list;
1443
0
                    } else
1444
13.7k
                        child2->child_list = child1->child_list;
1445
13.7k
                    for (previous = child1->child_list;
1446
23.3k
                         previous; previous = previous->next_peer)
1447
9.55k
                        previous->parent = child2;
1448
13.7k
                    child1->child_list = NULL;
1449
1450
13.7k
                    previous = child1;  /* Finished with 'child1' */
1451
13.7k
                    child1 = child1->next_peer;
1452
13.7k
                    free_tree(previous);
1453
13.7k
                    goto next;
1454
13.7k
                }
1455
27.1k
            }
1456
29.7k
        }
1457
        /*
1458
         * If no match, move 'child1' to 'tp2' child_list
1459
         */
1460
9.72k
        if (child1) {
1461
9.72k
            previous = child1;
1462
9.72k
            child1 = child1->next_peer;
1463
9.72k
            previous->parent = tp2;
1464
9.72k
            previous->next_peer = tp2->child_list;
1465
9.72k
            tp2->child_list = previous;
1466
9.72k
        }
1467
23.4k
      next:;
1468
23.4k
    }
1469
14.7k
}
1470
1471
1472
/*
1473
 * Find all the children of root in the list of nodes.  Link them into the
1474
 * tree and out of the nodes list.
1475
 */
1476
static void
1477
do_subtree(struct tree *root, struct node **nodes)
1478
446k
{
1479
446k
    struct tree    *tp, *anon_tp = NULL;
1480
446k
    struct tree    *xroot = root;
1481
446k
    struct node    *np, **headp;
1482
446k
    struct node    *oldnp = NULL, *child_list = NULL, *childp = NULL;
1483
446k
    int             hash;
1484
446k
    int            *int_p;
1485
1486
46.9M
    while (xroot->next_peer && xroot->next_peer->subid == root->subid) {
1487
#if 0
1488
        printf("xroot: %s.%s => %s\n", xroot->parent->label, xroot->label,
1489
               xroot->next_peer->label);
1490
#endif
1491
46.4M
        xroot = xroot->next_peer;
1492
46.4M
    }
1493
1494
446k
    tp = root;
1495
446k
    headp = &nbuckets[NBUCKET(name_hash(tp->label))];
1496
    /*
1497
     * Search each of the nodes for one whose parent is root, and
1498
     * move each into a separate list.
1499
     */
1500
656k
    for (np = *headp; np; np = np->next) {
1501
209k
        if (!label_compare(tp->label, np->parent)) {
1502
            /*
1503
             * take this node out of the node list 
1504
             */
1505
153k
            if (oldnp == NULL) {
1506
127k
                *headp = np->next;      /* fix root of node list */
1507
127k
            } else {
1508
25.3k
                oldnp->next = np->next; /* link around this node */
1509
25.3k
            }
1510
153k
            if (child_list)
1511
49.2k
                childp->next = np;
1512
104k
            else
1513
104k
                child_list = np;
1514
153k
            childp = np;
1515
153k
        } else {
1516
56.5k
            oldnp = np;
1517
56.5k
        }
1518
1519
209k
    }
1520
446k
    if (childp)
1521
104k
        childp->next = NULL;
1522
    /*
1523
     * Take each element in the child list and place it into the tree.
1524
     */
1525
599k
    for (np = child_list; np; np = np->next) {
1526
153k
        struct tree    *otp = NULL;
1527
153k
        struct tree    *xxroot = xroot;
1528
153k
        anon_tp = NULL;
1529
153k
        tp = xroot->child_list;
1530
1531
153k
        if (np->subid == -1) {
1532
            /*
1533
             * name ::= { parent } 
1534
             */
1535
1.07k
            np->subid = xroot->subid;
1536
1.07k
            tp = xroot;
1537
1.07k
            xxroot = xroot->parent;
1538
1.07k
        }
1539
1540
965k
        while (tp) {
1541
913k
            if (tp->subid == np->subid)
1542
101k
                break;
1543
812k
            else {
1544
812k
                otp = tp;
1545
812k
                tp = tp->next_peer;
1546
812k
            }
1547
913k
        }
1548
153k
        if (tp) {
1549
101k
            if (!label_compare(tp->label, np->label)) {
1550
                /*
1551
                 * Update list of modules 
1552
                 */
1553
36.8k
                int_p = malloc((tp->number_modules + 1) * sizeof(int));
1554
36.8k
                if (int_p == NULL)
1555
0
                    return;
1556
36.8k
                memcpy(int_p, tp->module_list,
1557
36.8k
                       tp->number_modules * sizeof(int));
1558
36.8k
                int_p[tp->number_modules] = np->modid;
1559
36.8k
                if (tp->module_list != &tp->modid)
1560
26.8k
                    free(tp->module_list);
1561
36.8k
                ++tp->number_modules;
1562
36.8k
                tp->module_list = int_p;
1563
1564
36.8k
                if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
1565
36.8k
             NETSNMP_DS_LIB_MIB_REPLACE)) {
1566
                    /*
1567
                     * Replace from node 
1568
                     */
1569
0
                    tree_from_node(tp, np);
1570
0
                }
1571
                /*
1572
                 * Handle children 
1573
                 */
1574
36.8k
                do_subtree(tp, nodes);
1575
36.8k
                continue;
1576
36.8k
            }
1577
64.8k
            if (!strncmp(np->label, ANON, ANON_LEN) ||
1578
56.9k
                !strncmp(tp->label, ANON, ANON_LEN)) {
1579
15.1k
                anon_tp = tp;   /* Need to merge these two trees later */
1580
49.6k
            } else if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1581
49.6k
            NETSNMP_DS_LIB_MIB_WARNINGS)) {
1582
0
                snmp_log(LOG_WARNING,
1583
0
                         "Warning: %s.%ld is both %s and %s (%s)\n",
1584
0
                         root->label, np->subid, tp->label, np->label,
1585
0
                         File);
1586
0
      }
1587
64.8k
        }
1588
1589
116k
        tp = calloc(1, sizeof(struct tree));
1590
116k
        if (tp == NULL)
1591
0
            return;
1592
116k
        tp->parent = xxroot;
1593
116k
        tp->modid = np->modid;
1594
116k
        tp->number_modules = 1;
1595
116k
        tp->module_list = &(tp->modid);
1596
116k
        tree_from_node(tp, np);
1597
116k
        if (!otp && !xxroot) {
1598
420
          free(tp);
1599
420
          return;
1600
420
        }
1601
116k
        tp->next_peer = otp ? otp->next_peer : xxroot->child_list;
1602
116k
        if (otp)
1603
10.3k
            otp->next_peer = tp;
1604
105k
        else
1605
105k
            xxroot->child_list = tp;
1606
116k
        hash = NBUCKET(name_hash(tp->label));
1607
116k
        tp->next = tbuckets[hash];
1608
116k
        tbuckets[hash] = tp;
1609
116k
        do_subtree(tp, nodes);
1610
1611
116k
        if (anon_tp) {
1612
15.1k
            if (!strncmp(tp->label, ANON, ANON_LEN)) {
1613
                /*
1614
                 * The new node is anonymous,
1615
                 *  so merge it with the existing one.
1616
                 */
1617
7.85k
                merge_anon_children(tp, anon_tp);
1618
1619
                /*
1620
                 * unlink and destroy tp 
1621
                 */
1622
7.85k
                unlink_tree(tp);
1623
7.85k
                free_tree(tp);
1624
7.85k
            } else if (!strncmp(anon_tp->label, ANON, ANON_LEN)) {
1625
6.87k
                struct tree    *ntp;
1626
                /*
1627
                 * The old node was anonymous,
1628
                 *  so merge it with the existing one,
1629
                 *  and fill in the full information.
1630
                 */
1631
6.87k
                merge_anon_children(anon_tp, tp);
1632
1633
                /*
1634
                 * unlink anon_tp from the hash 
1635
                 */
1636
6.87k
                unlink_tbucket(anon_tp);
1637
1638
                /*
1639
                 * get rid of old contents of anon_tp 
1640
                 */
1641
6.87k
                free_partial_tree(anon_tp, FALSE);
1642
1643
                /*
1644
                 * put in the current information 
1645
                 */
1646
6.87k
                anon_tp->label = tp->label;
1647
6.87k
                anon_tp->child_list = tp->child_list;
1648
6.87k
                anon_tp->modid = tp->modid;
1649
6.87k
                anon_tp->tc_index = tp->tc_index;
1650
6.87k
                anon_tp->type = tp->type;
1651
6.87k
                anon_tp->enums = tp->enums;
1652
6.87k
                anon_tp->indexes = tp->indexes;
1653
6.87k
                anon_tp->augments = tp->augments;
1654
6.87k
                anon_tp->varbinds = tp->varbinds;
1655
6.87k
                anon_tp->ranges = tp->ranges;
1656
6.87k
                anon_tp->hint = tp->hint;
1657
6.87k
                anon_tp->units = tp->units;
1658
6.87k
                anon_tp->description = tp->description;
1659
6.87k
                anon_tp->reference = tp->reference;
1660
6.87k
                anon_tp->defaultValue = tp->defaultValue;
1661
6.87k
                anon_tp->parent = tp->parent;
1662
1663
6.87k
                set_function(anon_tp);
1664
1665
                /*
1666
                 * update parent pointer in moved children 
1667
                 */
1668
6.87k
                ntp = anon_tp->child_list;
1669
16.5k
                while (ntp) {
1670
9.72k
                    ntp->parent = anon_tp;
1671
9.72k
                    ntp = ntp->next_peer;
1672
9.72k
                }
1673
1674
                /*
1675
                 * hash in anon_tp in its new place 
1676
                 */
1677
6.87k
                hash = NBUCKET(name_hash(anon_tp->label));
1678
6.87k
                anon_tp->next = tbuckets[hash];
1679
6.87k
                tbuckets[hash] = anon_tp;
1680
1681
                /*
1682
                 * unlink and destroy tp 
1683
                 */
1684
6.87k
                unlink_tbucket(tp);
1685
6.87k
                unlink_tree(tp);
1686
6.87k
                free(tp);
1687
6.87k
            } else {
1688
                /*
1689
                 * Uh?  One of these two should have been anonymous! 
1690
                 */
1691
410
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1692
410
               NETSNMP_DS_LIB_MIB_WARNINGS)) {
1693
0
                    snmp_log(LOG_WARNING,
1694
0
                             "Warning: expected anonymous node (either %s or %s) in %s\n",
1695
0
                             tp->label, anon_tp->label, File);
1696
0
    }
1697
410
            }
1698
15.1k
            anon_tp = NULL;
1699
15.1k
        }
1700
116k
    }
1701
    /*
1702
     * free all nodes that were copied into tree 
1703
     */
1704
445k
    oldnp = NULL;
1705
598k
    for (np = child_list; np; np = np->next) {
1706
152k
        if (oldnp)
1707
49.2k
            free_node(oldnp);
1708
152k
        oldnp = np;
1709
152k
    }
1710
445k
    if (oldnp)
1711
103k
        free_node(oldnp);
1712
445k
}
1713
1714
static void
1715
do_linkup(struct module *mp, struct node *np)
1716
10.8k
{
1717
10.8k
    struct module_import *mip;
1718
10.8k
    struct node    *onp, *oldp, *newp;
1719
10.8k
    struct tree    *tp;
1720
10.8k
    int             i, more;
1721
    /*
1722
     * All modules implicitly import
1723
     *   the roots of the tree
1724
     */
1725
10.8k
    if (snmp_get_do_debugging() > 1)
1726
0
        dump_module_list();
1727
10.8k
    DEBUGMSGTL(("parse-mibs", "Processing IMPORTS for module %d %s\n",
1728
10.8k
                mp->modid, mp->name));
1729
10.8k
    if (mp->no_imports == 0) {
1730
1.06k
        mp->no_imports = NUMBER_OF_ROOT_NODES;
1731
1.06k
        mp->imports = root_imports;
1732
1.06k
    }
1733
1734
    /*
1735
     * Build the tree
1736
     */
1737
10.8k
    init_node_hash(np);
1738
525k
    for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
1739
515k
        char            modbuf[256];
1740
515k
        DEBUGMSGTL(("parse-mibs", "  Processing import: %s\n",
1741
515k
                    mip->label));
1742
515k
        if (get_tc_index(mip->label, mip->modid) != -1)
1743
39.2k
            continue;
1744
475k
        tp = find_tree_node(mip->label, mip->modid);
1745
475k
        if (!tp) {
1746
212k
      if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS))
1747
374
                snmp_log(LOG_WARNING,
1748
374
                         "Did not find '%s' in module %s (%s)\n",
1749
374
                         mip->label, module_name(mip->modid, modbuf),
1750
374
                         File);
1751
212k
            continue;
1752
212k
        }
1753
263k
        do_subtree(tp, &np);
1754
263k
    }
1755
1756
    /*
1757
     * If any nodes left over,
1758
     *   check that they're not the result of a "fully qualified"
1759
     *   name, and then add them to the list of orphans
1760
     */
1761
1762
10.8k
    if (!np)
1763
827
        return;
1764
39.9k
    for (tp = tree_head; tp; tp = tp->next_peer)
1765
29.9k
        do_subtree(tp, &np);
1766
9.98k
    if (!np)
1767
0
        return;
1768
1769
    /*
1770
     * quietly move all internal references to the orphan list 
1771
     */
1772
9.98k
    oldp = orphan_nodes;
1773
11.9k
    do {
1774
1.54M
        for (i = 0; i < NHASHSIZE; i++)
1775
4.07M
            for (onp = nbuckets[i]; onp; onp = onp->next) {
1776
2.54M
                struct node    *op = NULL;
1777
2.54M
                int             hash = NBUCKET(name_hash(onp->label));
1778
2.54M
                np = nbuckets[hash];
1779
2.66M
                while (np) {
1780
126k
                    if (label_compare(onp->label, np->parent)) {
1781
101k
                        op = np;
1782
101k
                        np = np->next;
1783
101k
                    } else {
1784
24.8k
                        if (op)
1785
1.40k
                            op->next = np->next;
1786
23.4k
                        else
1787
23.4k
                            nbuckets[hash] = np->next;
1788
24.8k
      DEBUGMSGTL(("parse-mibs", "Moving %s to orphanage", np->label));
1789
24.8k
                        np->next = orphan_nodes;
1790
24.8k
                        orphan_nodes = np;
1791
24.8k
                        op = NULL;
1792
24.8k
                        np = nbuckets[hash];
1793
24.8k
                    }
1794
126k
                }
1795
2.54M
            }
1796
11.9k
        newp = orphan_nodes;
1797
11.9k
        more = 0;
1798
45.2k
        for (onp = orphan_nodes; onp != oldp; onp = onp->next) {
1799
33.2k
            struct node    *op = NULL;
1800
33.2k
            int             hash = NBUCKET(name_hash(onp->label));
1801
33.2k
            np = nbuckets[hash];
1802
52.7k
            while (np) {
1803
19.5k
                if (label_compare(onp->label, np->parent)) {
1804
11.1k
                    op = np;
1805
11.1k
                    np = np->next;
1806
11.1k
                } else {
1807
8.38k
                    if (op)
1808
697
                        op->next = np->next;
1809
7.68k
                    else
1810
7.68k
                        nbuckets[hash] = np->next;
1811
8.38k
                    np->next = orphan_nodes;
1812
8.38k
                    orphan_nodes = np;
1813
8.38k
                    op = NULL;
1814
8.38k
                    np = nbuckets[hash];
1815
8.38k
                    more = 1;
1816
8.38k
                }
1817
19.5k
            }
1818
33.2k
        }
1819
11.9k
        oldp = newp;
1820
11.9k
    } while (more);
1821
1822
    /*
1823
     * complain about left over nodes 
1824
     */
1825
158M
    for (np = orphan_nodes; np && np->next; np = np->next);     /* find the end of the orphan list */
1826
1.28M
    for (i = 0; i < NHASHSIZE; i++)
1827
1.27M
        if (nbuckets[i]) {
1828
6.50k
            if (orphan_nodes)
1829
6.50k
                onp = np->next = nbuckets[i];
1830
1
            else
1831
1
                onp = orphan_nodes = nbuckets[i];
1832
6.50k
            nbuckets[i] = NULL;
1833
14.3k
            while (onp) {
1834
7.84k
                snmp_log(LOG_WARNING,
1835
7.84k
                         "Cannot resolve OID in %s: %s ::= { %s %ld } at line %d in %s\n",
1836
7.84k
                         (mp->name ? mp->name : "<no module>"),
1837
7.84k
                         (onp->label ? onp->label : "<no label>"),
1838
7.84k
                         (onp->parent ? onp->parent : "<no parent>"),
1839
7.84k
                         onp->subid, onp->lineno, onp->filename);
1840
7.84k
                np = onp;
1841
7.84k
                onp = onp->next;
1842
7.84k
            }
1843
6.50k
        }
1844
9.98k
    return;
1845
9.98k
}
1846
1847
1848
/**
1849
 * Read an OID from a file.
1850
 * @param[in]  file   File to read from.
1851
 * @param[out] id_arg Array to store the OID in.
1852
 * @param[in]  length Number of elements in the @id_arg array.
1853
 *
1854
 * Takes a list of the form:
1855
 * { iso org(3) dod(6) 1 }
1856
 * and creates several nodes, one for each parent-child pair.
1857
 * Returns 0 on error.
1858
 */
1859
static int
1860
getoid(FILE * fp, struct subid_s *id_arg, int length)
1861
56.7k
{
1862
56.7k
    struct subid_s *id = id_arg;
1863
56.7k
    int             i, count, type;
1864
56.7k
    char            token[MAXTOKEN];
1865
1866
56.7k
    if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET) {
1867
1.57k
        print_error("Expected \"{\"", token, type);
1868
1.57k
        return 0;
1869
1.57k
    }
1870
55.2k
    type = get_token(fp, token, MAXTOKEN);
1871
412k
    for (count = 0; count < length; count++, id++) {
1872
412k
        id->label = NULL;
1873
412k
        id->modid = current_module;
1874
412k
        id->subid = -1;
1875
412k
        if (type == RIGHTBRACKET)
1876
53.5k
            return count;
1877
359k
        if (type == LABEL) {
1878
            /*
1879
             * this entry has a label 
1880
             */
1881
289k
            id->label = strdup(token);
1882
289k
            type = get_token(fp, token, MAXTOKEN);
1883
289k
            if (type == LEFTPAREN) {
1884
777
                type = get_token(fp, token, MAXTOKEN);
1885
777
                if (type == NUMBER) {
1886
373
                    id->subid = strtoul(token, NULL, 10);
1887
373
                    if ((type =
1888
373
                         get_token(fp, token, MAXTOKEN)) != RIGHTPAREN) {
1889
283
                        print_error("Expected a closing parenthesis",
1890
283
                                    token, type);
1891
283
                        goto free_labels;
1892
283
                    }
1893
404
                } else {
1894
404
                    print_error("Expected a number", token, type);
1895
404
                    goto free_labels;
1896
404
                }
1897
288k
            } else {
1898
288k
                continue;
1899
288k
            }
1900
289k
        } else if (type == NUMBER) {
1901
            /*
1902
             * this entry  has just an integer sub-identifier 
1903
             */
1904
68.8k
            id->subid = strtoul(token, NULL, 10);
1905
68.8k
        } else {
1906
740
            print_error("Expected label or number", token, type);
1907
740
            goto free_labels;
1908
740
        }
1909
68.9k
        type = get_token(fp, token, MAXTOKEN);
1910
68.9k
    }
1911
215
    print_error("Too long OID", token, type);
1912
215
    --count;
1913
1914
1.64k
free_labels:
1915
16.0k
    for (i = 0; i <= count; i++) {
1916
14.3k
        free(id_arg[i].label);
1917
14.3k
        id_arg[i].label = NULL;
1918
14.3k
    }
1919
1920
1.64k
    return 0;
1921
215
}
1922
1923
/*
1924
 * Parse a sequence of object subidentifiers for the given name.
1925
 * The "label OBJECT IDENTIFIER ::=" portion has already been parsed.
1926
 *
1927
 * The majority of cases take this form :
1928
 * label OBJECT IDENTIFIER ::= { parent 2 }
1929
 * where a parent label and a child subidentifier number are specified.
1930
 *
1931
 * Variations on the theme include cases where a number appears with
1932
 * the parent, or intermediate subidentifiers are specified by label,
1933
 * by number, or both.
1934
 *
1935
 * Here are some representative samples :
1936
 * internet        OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }
1937
 * mgmt            OBJECT IDENTIFIER ::= { internet 2 }
1938
 * rptrInfoHealth  OBJECT IDENTIFIER ::= { snmpDot3RptrMgt 0 4 }
1939
 *
1940
 * Here is a very rare form :
1941
 * iso             OBJECT IDENTIFIER ::= { 1 }
1942
 *
1943
 * Returns NULL on error.  When this happens, memory may be leaked.
1944
 */
1945
static struct node *
1946
parse_objectid(FILE * fp, char *name)
1947
56.7k
{
1948
56.7k
    register int    count;
1949
56.7k
    register struct subid_s *op, *nop;
1950
56.7k
    int             length;
1951
56.7k
    struct subid_s  loid[32];
1952
56.7k
    struct node    *np, *root = NULL, *oldnp = NULL;
1953
56.7k
    struct tree    *tp;
1954
1955
56.7k
    if ((length = getoid(fp, loid, 32)) == 0) {
1956
3.22k
        print_error("Bad object identifier", NULL, CONTINUE);
1957
3.22k
        return NULL;
1958
3.22k
    }
1959
1960
    /*
1961
     * Handle numeric-only object identifiers,
1962
     *  by labeling the first sub-identifier
1963
     */
1964
53.5k
    op = loid;
1965
53.5k
    if (!op->label) {
1966
7.26k
        if (length == 1) {
1967
220
            print_error("Attempt to define a root oid", name, OBJECT);
1968
220
            return NULL;
1969
220
        }
1970
15.8k
        for (tp = tree_head; tp; tp = tp->next_peer)
1971
14.8k
            if ((int) tp->subid == op->subid) {
1972
6.09k
                op->label = strdup(tp->label);
1973
6.09k
                break;
1974
6.09k
            }
1975
7.04k
    }
1976
1977
    /*
1978
     * Handle  "label OBJECT-IDENTIFIER ::= { subid }"
1979
     */
1980
53.3k
    if (length == 1) {
1981
9.44k
        op = loid;
1982
9.44k
        np = alloc_node(op->modid);
1983
9.44k
        if (np == NULL)
1984
0
            return (NULL);
1985
9.44k
        np->subid = op->subid;
1986
9.44k
        np->label = strdup(name);
1987
9.44k
        np->parent = op->label;
1988
9.44k
        return np;
1989
9.44k
    }
1990
1991
    /*
1992
     * For each parent-child subid pair in the subid array,
1993
     * create a node and link it into the node list.
1994
     */
1995
334k
    for (count = 0, op = loid, nop = loid + 1; count < (length - 1);
1996
291k
         count++, op++, nop++) {
1997
        /*
1998
         * every node must have parent's name and child's name or number 
1999
         */
2000
        /*
2001
         * XX the next statement is always true -- does it matter ?? 
2002
         */
2003
291k
        if (op->label && (nop->label || (nop->subid != -1))) {
2004
284k
            np = alloc_node(nop->modid);
2005
284k
            if (np == NULL)
2006
0
                goto err;
2007
284k
            if (root == NULL) {
2008
43.8k
                root = np;
2009
240k
            } else {
2010
240k
                netsnmp_assert(oldnp);
2011
240k
                oldnp->next = np;
2012
240k
            }
2013
284k
            oldnp = np;
2014
2015
284k
            np->parent = strdup(op->label);
2016
284k
            if (count == (length - 2)) {
2017
                /*
2018
                 * The name for this node is the label for this entry 
2019
                 */
2020
41.1k
                np->label = strdup(name);
2021
41.1k
                if (np->label == NULL)
2022
0
                    goto err;
2023
243k
            } else {
2024
243k
                if (!nop->label) {
2025
32.4k
                    if (asprintf(&nop->label, "%s%d", ANON, anonymous++) < 0)
2026
0
                        goto err;
2027
32.4k
                }
2028
243k
                np->label = strdup(nop->label);
2029
243k
            }
2030
284k
            if (nop->subid != -1)
2031
56.6k
                np->subid = nop->subid;
2032
227k
            else
2033
227k
                print_error("Warning: This entry is pretty silly",
2034
227k
                            np->label, CONTINUE);
2035
284k
        }                       /* end if(op->label... */
2036
291k
    }
2037
2038
43.8k
out:
2039
    /*
2040
     * free the loid array 
2041
     */
2042
378k
    for (count = 0, op = loid; count < length; count++, op++) {
2043
334k
        free(op->label);
2044
334k
        op->label = NULL;
2045
334k
    }
2046
2047
43.8k
    return root;
2048
2049
0
err:
2050
0
    for (; root; root = np) {
2051
0
        np = root->next;
2052
0
        free_node(root);
2053
0
    }
2054
0
    goto out;
2055
43.8k
}
2056
2057
static int
2058
get_tc(const char *descriptor,
2059
       int modid,
2060
       int *tc_index,
2061
       struct enum_list **ep, struct range_list **rp, char **hint)
2062
13.4k
{
2063
13.4k
    int             i;
2064
13.4k
    struct tc      *tcp;
2065
2066
13.4k
    i = get_tc_index(descriptor, modid);
2067
13.4k
    if (tc_index)
2068
4.13k
        *tc_index = i;
2069
13.4k
    if (i != -1) {
2070
925
        tcp = &tclist[i];
2071
925
        if (ep) {
2072
362
            free_enums(ep);
2073
362
            *ep = copy_enums(tcp->enums);
2074
362
        }
2075
925
        if (rp) {
2076
362
            free_ranges(rp);
2077
362
            *rp = copy_ranges(tcp->ranges);
2078
362
        }
2079
925
        if (hint) {
2080
362
            if (*hint)
2081
0
                free(*hint);
2082
362
            *hint = (tcp->hint ? strdup(tcp->hint) : NULL);
2083
362
        }
2084
925
        return tcp->type;
2085
925
    }
2086
12.5k
    return LABEL;
2087
13.4k
}
2088
2089
/*
2090
 * return index into tclist of given TC descriptor
2091
 * return -1 if not found
2092
 */
2093
static int
2094
get_tc_index(const char *descriptor, int modid)
2095
528k
{
2096
528k
    int             i;
2097
528k
    struct tc      *tcp;
2098
528k
    struct module  *mp;
2099
528k
    struct module_import *mip;
2100
2101
    /*
2102
     * Check that the descriptor isn't imported
2103
     *  by searching the import list
2104
     */
2105
2106
3.69G
    for (mp = module_head; mp; mp = mp->next)
2107
3.69G
        if (mp->modid == modid)
2108
364k
            break;
2109
528k
    if (mp)
2110
23.9M
        for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
2111
23.9M
            if (!label_compare(mip->label, descriptor)) {
2112
                /*
2113
                 * Found it - so amend the module ID 
2114
                 */
2115
326k
                modid = mip->modid;
2116
326k
                break;
2117
326k
            }
2118
23.9M
        }
2119
2120
2121
1.15G
    for (i = 0, tcp = tclist; i < tc_alloc; i++, tcp++) {
2122
1.15G
        if (tcp->type == 0)
2123
488k
            break;
2124
1.15G
        if (!label_compare(descriptor, tcp->descriptor) &&
2125
25.6M
            ((modid == tcp->modid) || (modid == -1))) {
2126
40.1k
            return i;
2127
40.1k
        }
2128
1.15G
    }
2129
488k
    return -1;
2130
528k
}
2131
2132
/*
2133
 * translate integer tc_index to string identifier from tclist
2134
 * *
2135
 * * Returns pointer to string in table (should not be modified) or NULL
2136
 */
2137
const char     *
2138
get_tc_descriptor(int tc_index)
2139
0
{
2140
0
    if (tc_index < 0 || tc_index >= tc_alloc)
2141
0
        return NULL;
2142
0
    return tclist[tc_index].descriptor;
2143
0
}
2144
2145
#ifndef NETSNMP_FEATURE_REMOVE_GET_TC_DESCRIPTION
2146
/* used in the perl module */
2147
const char     *
2148
get_tc_description(int tc_index)
2149
0
{
2150
0
    if (tc_index < 0 || tc_index >= tc_alloc)
2151
0
        return NULL;
2152
0
    return tclist[tc_index].description;
2153
0
}
2154
#endif /* NETSNMP_FEATURE_REMOVE_GET_TC_DESCRIPTION */
2155
2156
2157
/*
2158
 * Parses an enumeration list of the form:
2159
 *        { label(value) label(value) ... }
2160
 * The initial { has already been parsed.
2161
 * Returns NULL on error.
2162
 */
2163
2164
static struct enum_list *
2165
parse_enumlist(FILE * fp, struct enum_list **retp)
2166
2.72k
{
2167
2.72k
    register int    type;
2168
2.72k
    char            token[MAXTOKEN];
2169
2.72k
    struct enum_list *ep = NULL, **epp = &ep;
2170
2171
2.72k
    free_enums(retp);
2172
2173
14.5k
    while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
2174
14.4k
        if (type == RIGHTBRACKET)
2175
1.77k
            break;
2176
        /* some enums use "deprecated" to indicate a no longer value label */
2177
        /* (EG: IP-MIB's IpAddressStatusTC) */
2178
12.6k
        if (type == LABEL || type == DEPRECATED) {
2179
            /*
2180
             * this is an enumerated label 
2181
             */
2182
7.37k
            *epp = calloc(1, sizeof(struct enum_list));
2183
7.37k
            if (*epp == NULL)
2184
0
                return (NULL);
2185
            /*
2186
             * a reasonable approximation for the length 
2187
             */
2188
7.37k
            (*epp)->label = strdup(token);
2189
7.37k
            type = get_token(fp, token, MAXTOKEN);
2190
7.37k
            if (type != LEFTPAREN) {
2191
466
                print_error("Expected \"(\"", token, type);
2192
466
                goto err;
2193
466
            }
2194
6.90k
            type = get_token(fp, token, MAXTOKEN);
2195
6.90k
            if (type != NUMBER) {
2196
267
                print_error("Expected integer", token, type);
2197
267
                goto err;
2198
267
            }
2199
6.63k
            (*epp)->value = strtol(token, NULL, 10);
2200
6.63k
            (*epp)->lineno = mibLine;
2201
6.63k
            type = get_token(fp, token, MAXTOKEN);
2202
6.63k
            if (type != RIGHTPAREN) {
2203
151
                print_error("Expected \")\"", token, type);
2204
151
                goto err;
2205
6.48k
            } else {
2206
6.48k
                struct enum_list *op = ep;
2207
48.1k
                while (op != *epp) {
2208
42.6k
                    if (strcmp((*epp)->label, op->label) == 0) {
2209
318
                        snmp_log(LOG_ERR,
2210
318
                            "Duplicate enum label '%s' at line %d in %s. First at line %d\n",
2211
318
                            (*epp)->label, mibLine, File, op->lineno);
2212
318
                        erroneousMibs++;
2213
318
                        break;
2214
318
                    }
2215
42.3k
                    else if ((*epp)->value == op->value) {
2216
645
                        snmp_log(LOG_ERR,
2217
645
                            "Duplicate enum value '%d' at line %d in %s. First at line %d\n",
2218
645
                            (*epp)->value, mibLine, File, op->lineno);
2219
645
                        erroneousMibs++;
2220
645
                        break;
2221
645
                    }
2222
41.6k
                    op = op->next;
2223
41.6k
                }
2224
6.48k
            }
2225
6.48k
            epp = &(*epp)->next;
2226
6.48k
        }
2227
12.6k
    }
2228
1.83k
    if (type == ENDOFFILE) {
2229
60
        print_error("Expected \"}\"", token, type);
2230
60
        goto err;
2231
60
    }
2232
1.77k
    *retp = ep;
2233
1.77k
    return ep;
2234
2235
944
err:
2236
944
    free_enums(&ep);
2237
944
    return NULL;
2238
1.83k
}
2239
2240
static struct range_list *
2241
parse_ranges(FILE * fp, struct range_list **retp)
2242
3.96k
{
2243
3.96k
    int             low, high;
2244
3.96k
    char            nexttoken[MAXTOKEN];
2245
3.96k
    int             nexttype;
2246
3.96k
    struct range_list *rp = NULL, **rpp = &rp;
2247
3.96k
    int             size = 0, taken = 1;
2248
2249
3.96k
    free_ranges(retp);
2250
2251
3.96k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
2252
3.96k
    if (nexttype == SIZE) {
2253
423
        size = 1;
2254
423
        taken = 0;
2255
423
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2256
423
        if (nexttype != LEFTPAREN)
2257
175
            print_error("Expected \"(\" after SIZE", nexttoken, nexttype);
2258
423
    }
2259
2260
7.59k
    do {
2261
7.59k
        if (!taken)
2262
4.06k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2263
3.53k
        else
2264
3.53k
            taken = 0;
2265
7.59k
        high = low = strtoul(nexttoken, NULL, 10);
2266
7.59k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2267
7.59k
        if (nexttype == RANGE) {
2268
3.89k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2269
3.89k
            errno = 0;
2270
3.89k
            high = strtoul(nexttoken, NULL, 10);
2271
3.89k
            if ( errno == ERANGE ) {
2272
1.04k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
2273
1.04k
                                       NETSNMP_DS_LIB_MIB_WARNINGS))
2274
0
                    snmp_log(LOG_WARNING,
2275
0
                             "Warning: Upper bound not handled correctly (%s != %d): At line %d in %s\n",
2276
0
                                 nexttoken, high, mibLine, File);
2277
1.04k
            }
2278
3.89k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2279
3.89k
        }
2280
7.59k
        *rpp = (struct range_list *) calloc(1, sizeof(struct range_list));
2281
7.59k
        if (*rpp == NULL)
2282
0
            break;
2283
7.59k
        (*rpp)->low = low;
2284
7.59k
        (*rpp)->high = high;
2285
7.59k
        rpp = &(*rpp)->next;
2286
2287
7.59k
    } while (nexttype == BAR);
2288
3.96k
    if (size) {
2289
423
        if (nexttype != RIGHTPAREN)
2290
237
            print_error("Expected \")\" after SIZE", nexttoken, nexttype);
2291
423
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2292
423
    }
2293
3.96k
    if (nexttype != RIGHTPAREN)
2294
814
        print_error("Expected \")\"", nexttoken, nexttype);
2295
2296
3.96k
    *retp = rp;
2297
3.96k
    return rp;
2298
3.96k
}
2299
2300
/*
2301
 * Parses an asn type.  Structures are ignored by this parser.
2302
 * Returns NULL on error.
2303
 */
2304
static struct node *
2305
parse_asntype(FILE * fp, char *name, int *ntype, char *ntoken)
2306
37.6k
{
2307
37.6k
    int             type, i;
2308
37.6k
    char            token[MAXTOKEN];
2309
37.6k
    char            quoted_string_buffer[MAXQUOTESTR];
2310
37.6k
    char           *hint = NULL;
2311
37.6k
    char           *descr = NULL;
2312
37.6k
    struct tc      *tcp;
2313
37.6k
    int             level;
2314
2315
37.6k
    type = get_token(fp, token, MAXTOKEN);
2316
37.6k
    if (type == SEQUENCE || type == CHOICE) {
2317
1.79k
        level = 0;
2318
1.43M
        while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
2319
1.43M
            if (type == LEFTBRACKET) {
2320
113k
                level++;
2321
1.32M
            } else if (type == RIGHTBRACKET && --level == 0) {
2322
1.71k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2323
1.71k
                return NULL;
2324
1.71k
            }
2325
1.43M
        }
2326
87
        print_error("Expected \"}\"", token, type);
2327
87
        return NULL;
2328
35.8k
    } else if (type == LEFTBRACKET) {
2329
17.1k
        struct node    *np;
2330
17.1k
        int             ch_next = '{';
2331
17.1k
        ungetc(ch_next, fp);
2332
17.1k
        np = parse_objectid(fp, name);
2333
17.1k
        if (np != NULL) {
2334
15.3k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2335
15.3k
            return np;
2336
15.3k
        }
2337
1.80k
        return NULL;
2338
18.7k
    } else if (type == LEFTSQBRACK) {
2339
4.90k
        int             size = 0;
2340
436k
        do {
2341
436k
            type = get_token(fp, token, MAXTOKEN);
2342
436k
        } while (type != ENDOFFILE && type != RIGHTSQBRACK);
2343
4.90k
        if (type != RIGHTSQBRACK) {
2344
48
            print_error("Expected \"]\"", token, type);
2345
48
            return NULL;
2346
48
        }
2347
4.85k
        type = get_token(fp, token, MAXTOKEN);
2348
4.85k
        if (type == IMPLICIT)
2349
1.59k
            type = get_token(fp, token, MAXTOKEN);
2350
4.85k
        *ntype = get_token(fp, ntoken, MAXTOKEN);
2351
4.85k
        if (*ntype == LEFTPAREN) {
2352
3.91k
            switch (type) {
2353
1.66k
            case OCTETSTR:
2354
1.66k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2355
1.66k
                if (*ntype != SIZE) {
2356
481
                    print_error("Expected SIZE", ntoken, *ntype);
2357
481
                    return NULL;
2358
481
                }
2359
1.18k
                size = 1;
2360
1.18k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2361
1.18k
                if (*ntype != LEFTPAREN) {
2362
465
                    print_error("Expected \"(\" after SIZE", ntoken,
2363
465
                                *ntype);
2364
465
                    return NULL;
2365
465
                }
2366
721
                NETSNMP_FALLTHROUGH;
2367
2.30k
            case INTEGER:
2368
2.30k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2369
5.48k
                do {
2370
5.48k
                    if (*ntype != NUMBER)
2371
3.49k
                        print_error("Expected NUMBER", ntoken, *ntype);
2372
5.48k
                    *ntype = get_token(fp, ntoken, MAXTOKEN);
2373
5.48k
                    if (*ntype == RANGE) {
2374
2.04k
                        *ntype = get_token(fp, ntoken, MAXTOKEN);
2375
2.04k
                        if (*ntype != NUMBER)
2376
778
                            print_error("Expected NUMBER", ntoken, *ntype);
2377
2.04k
                        *ntype = get_token(fp, ntoken, MAXTOKEN);
2378
2.04k
                    }
2379
5.48k
                } while (*ntype == BAR);
2380
2.30k
                if (*ntype != RIGHTPAREN) {
2381
496
                    print_error("Expected \")\"", ntoken, *ntype);
2382
496
                    return NULL;
2383
496
                }
2384
1.81k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2385
1.81k
                if (size) {
2386
715
                    if (*ntype != RIGHTPAREN) {
2387
204
                        print_error("Expected \")\" to terminate SIZE",
2388
204
                                    ntoken, *ntype);
2389
204
                        return NULL;
2390
204
                    }
2391
511
                    *ntype = get_token(fp, ntoken, MAXTOKEN);
2392
511
                }
2393
3.91k
            }
2394
3.91k
        }
2395
3.21k
        return NULL;
2396
13.8k
    } else {
2397
13.8k
        if (type == CONVENTION) {
2398
31.0k
            while (type != SYNTAX && type != ENDOFFILE) {
2399
30.0k
                if (type == DISPLAYHINT) {
2400
1.50k
                    type = get_token(fp, token, MAXTOKEN);
2401
1.50k
                    if (type != QUOTESTRING) {
2402
222
                        print_error("DISPLAY-HINT must be string", token,
2403
222
                                    type);
2404
1.28k
                    } else {
2405
1.28k
                        free(hint);
2406
1.28k
                        hint = strdup(token);
2407
1.28k
                    }
2408
28.5k
                } else if (type == DESCRIPTION &&
2409
247
                           netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2410
247
                                                  NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2411
0
                    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2412
0
                    if (type != QUOTESTRING) {
2413
0
                        print_error("DESCRIPTION must be string", token,
2414
0
                                    type);
2415
0
                    } else {
2416
0
                        free(descr);
2417
0
                        descr = strdup(quoted_string_buffer);
2418
0
                    }
2419
0
                } else
2420
28.5k
                    type =
2421
28.5k
                        get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2422
30.0k
            }
2423
959
            type = get_token(fp, token, MAXTOKEN);
2424
959
            if (type == OBJECT) {
2425
424
                type = get_token(fp, token, MAXTOKEN);
2426
424
                if (type != IDENTIFIER) {
2427
204
                    print_error("Expected IDENTIFIER", token, type);
2428
204
                    goto err;
2429
204
                }
2430
220
                type = OBJID;
2431
220
            }
2432
12.8k
        } else if (type == OBJECT) {
2433
592
            type = get_token(fp, token, MAXTOKEN);
2434
592
            if (type != IDENTIFIER) {
2435
256
                print_error("Expected IDENTIFIER", token, type);
2436
256
                goto err;
2437
256
            }
2438
336
            type = OBJID;
2439
336
        }
2440
2441
13.3k
        if (type == LABEL) {
2442
9.29k
            type = get_tc(token, current_module, NULL, NULL, NULL, NULL);
2443
9.29k
        }
2444
2445
        /*
2446
         * textual convention 
2447
         */
2448
13.3k
        tcp = NULL;
2449
18.4M
        for (i = 0; i < tc_alloc; i++) {
2450
18.4M
            if (tclist[i].type == 0) {
2451
738k
                if (tcp == NULL)
2452
13.3k
                    tcp = &tclist[i];
2453
17.7M
            } else if (strcmp(name, tclist[i].descriptor) == 0 &&
2454
411k
                       tclist[i].modid == current_module) {
2455
71.2k
                snmp_log(LOG_ERR,
2456
71.2k
                         "Duplicate TEXTUAL-CONVENTION '%s' at line %d in %s. First at line %d\n",
2457
71.2k
                         name, mibLine, File, tclist[i].lineno);
2458
71.2k
                erroneousMibs++;
2459
71.2k
            }
2460
18.4M
        }
2461
2462
13.3k
        if (tcp == NULL) {
2463
33
            tclist = realloc(tclist, (tc_alloc + TC_INCR)*sizeof(struct tc));
2464
33
            memset(tclist+tc_alloc, 0, TC_INCR*sizeof(struct tc));
2465
33
            tcp = tclist + tc_alloc;
2466
33
            tc_alloc += TC_INCR;
2467
33
        }
2468
13.3k
        if (!(type & SYNTAX_MASK)) {
2469
9.60k
            print_error("Textual convention doesn't map to real type",
2470
9.60k
                        token, type);
2471
9.60k
            goto err;
2472
9.60k
        }
2473
3.77k
        tcp->modid = current_module;
2474
3.77k
        tcp->descriptor = strdup(name);
2475
3.77k
        tcp->hint = hint;
2476
3.77k
        tcp->description = descr;
2477
3.77k
        tcp->lineno = mibLine;
2478
3.77k
        tcp->type = type;
2479
3.77k
        *ntype = get_token(fp, ntoken, MAXTOKEN);
2480
3.77k
        if (*ntype == LEFTPAREN) {
2481
733
            tcp->ranges = parse_ranges(fp, &tcp->ranges);
2482
733
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2483
3.04k
        } else if (*ntype == LEFTBRACKET) {
2484
            /*
2485
             * if there is an enumeration list, parse it 
2486
             */
2487
1.17k
            tcp->enums = parse_enumlist(fp, &tcp->enums);
2488
1.17k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2489
1.17k
        }
2490
3.77k
        return NULL;
2491
13.3k
    }
2492
2493
10.0k
err:
2494
10.0k
    SNMP_FREE(descr);
2495
10.0k
    SNMP_FREE(hint);
2496
10.0k
    return NULL;
2497
37.6k
}
2498
2499
2500
/*
2501
 * Parses an OBJECT TYPE macro.
2502
 * Returns 0 on error.
2503
 */
2504
static struct node *
2505
parse_objecttype(FILE * fp, char *name)
2506
13.6k
{
2507
13.6k
    register int    type;
2508
13.6k
    char            token[MAXTOKEN];
2509
13.6k
    char            nexttoken[MAXTOKEN];
2510
13.6k
    char            quoted_string_buffer[MAXQUOTESTR];
2511
13.6k
    int             nexttype, tctype;
2512
13.6k
    register struct node *np;
2513
2514
13.6k
    type = get_token(fp, token, MAXTOKEN);
2515
13.6k
    if (type != SYNTAX) {
2516
33
        print_error("Bad format for OBJECT-TYPE", token, type);
2517
33
        return NULL;
2518
33
    }
2519
13.6k
    np = alloc_node(current_module);
2520
13.6k
    if (np == NULL)
2521
0
        return (NULL);
2522
13.6k
    type = get_token(fp, token, MAXTOKEN);
2523
13.6k
    if (type == OBJECT) {
2524
706
        type = get_token(fp, token, MAXTOKEN);
2525
706
        if (type != IDENTIFIER) {
2526
10
            print_error("Expected IDENTIFIER", token, type);
2527
10
            free_node(np);
2528
10
            return NULL;
2529
10
        }
2530
696
        type = OBJID;
2531
696
    }
2532
13.6k
    if (type == LABEL) {
2533
4.13k
        int             tmp_index;
2534
4.13k
        tctype = get_tc(token, current_module, &tmp_index,
2535
4.13k
                        &np->enums, &np->ranges, &np->hint);
2536
4.13k
        if (tctype == LABEL &&
2537
3.77k
            netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
2538
3.77k
             NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
2539
0
            print_error("Warning: No known translation for type", token,
2540
0
                        type);
2541
0
        }
2542
4.13k
        type = tctype;
2543
4.13k
        np->tc_index = tmp_index;       /* store TC for later reference */
2544
4.13k
    }
2545
13.6k
    np->type = type;
2546
13.6k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
2547
13.6k
    switch (type) {
2548
660
    case SEQUENCE:
2549
660
        if (nexttype == OF) {
2550
642
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2551
642
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2552
2553
642
        }
2554
660
        break;
2555
1.46k
    case INTEGER:
2556
2.77k
    case INTEGER32:
2557
2.77k
    case UINTEGER32:
2558
3.65k
    case UNSIGNED32:
2559
4.91k
    case COUNTER:
2560
5.23k
    case GAUGE:
2561
5.53k
    case BITSTRING:
2562
9.30k
    case LABEL:
2563
9.30k
        if (nexttype == LEFTBRACKET) {
2564
            /*
2565
             * if there is an enumeration list, parse it 
2566
             */
2567
774
            np->enums = parse_enumlist(fp, &np->enums);
2568
774
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2569
8.53k
        } else if (nexttype == LEFTPAREN) {
2570
            /*
2571
             * if there is a range list, parse it 
2572
             */
2573
1.76k
            np->ranges = parse_ranges(fp, &np->ranges);
2574
1.76k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2575
1.76k
        }
2576
9.30k
        break;
2577
667
    case OCTETSTR:
2578
881
    case KW_OPAQUE:
2579
        /*
2580
         * parse any SIZE specification 
2581
         */
2582
881
        if (nexttype == LEFTPAREN) {
2583
151
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2584
151
            if (nexttype == SIZE) {
2585
143
                nexttype = get_token(fp, nexttoken, MAXTOKEN);
2586
143
                if (nexttype == LEFTPAREN) {
2587
138
                    np->ranges = parse_ranges(fp, &np->ranges);
2588
138
                    nexttype = get_token(fp, nexttoken, MAXTOKEN);      /* ) */
2589
138
                    if (nexttype == RIGHTPAREN) {
2590
129
                        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2591
129
                        break;
2592
129
                    }
2593
138
                }
2594
143
            }
2595
22
            print_error("Bad SIZE syntax", token, type);
2596
22
            free_node(np);
2597
22
            return NULL;
2598
151
        }
2599
730
        break;
2600
730
    case OBJID:
2601
1.13k
    case NETADDR:
2602
1.36k
    case IPADDR:
2603
1.71k
    case TIMETICKS:
2604
2.55k
    case NUL:
2605
2.55k
    case NSAPADDRESS:
2606
2.76k
    case COUNTER64:
2607
2.76k
        break;
2608
8
    default:
2609
8
        print_error("Bad syntax", token, type);
2610
8
        free_node(np);
2611
8
        return NULL;
2612
13.6k
    }
2613
13.5k
    if (nexttype == UNITS) {
2614
1.44k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2615
1.44k
        if (type != QUOTESTRING) {
2616
9
            print_error("Bad UNITS", quoted_string_buffer, type);
2617
9
            free_node(np);
2618
9
            return NULL;
2619
9
        }
2620
1.43k
        np->units = strdup(quoted_string_buffer);
2621
1.43k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2622
1.43k
    }
2623
13.5k
    if (nexttype != ACCESS) {
2624
119
        print_error("Should be ACCESS", nexttoken, nexttype);
2625
119
        free_node(np);
2626
119
        return NULL;
2627
119
    }
2628
13.4k
    type = get_token(fp, token, MAXTOKEN);
2629
13.4k
    if (type != READONLY && type != READWRITE && type != WRITEONLY
2630
5.29k
        && type != NOACCESS && type != READCREATE && type != ACCNOTIFY) {
2631
36
        print_error("Bad ACCESS type", token, type);
2632
36
        free_node(np);
2633
36
        return NULL;
2634
36
    }
2635
13.4k
    np->access = type;
2636
13.4k
    type = get_token(fp, token, MAXTOKEN);
2637
13.4k
    if (type != STATUS) {
2638
26
        print_error("Should be STATUS", token, type);
2639
26
        free_node(np);
2640
26
        return NULL;
2641
26
    }
2642
13.4k
    type = get_token(fp, token, MAXTOKEN);
2643
13.4k
    if (type != MANDATORY && type != CURRENT && type != KW_OPTIONAL &&
2644
647
        type != OBSOLETE && type != DEPRECATED) {
2645
27
        print_error("Bad STATUS", token, type);
2646
27
        free_node(np);
2647
27
        return NULL;
2648
27
    }
2649
13.3k
    np->status = type;
2650
    /*
2651
     * Optional parts of the OBJECT-TYPE macro
2652
     */
2653
13.3k
    type = get_token(fp, token, MAXTOKEN);
2654
30.1k
    while (type != EQUALS && type != ENDOFFILE) {
2655
17.0k
        switch (type) {
2656
11.2k
        case DESCRIPTION:
2657
11.2k
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2658
2659
11.2k
            if (type != QUOTESTRING) {
2660
36
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2661
36
                free_node(np);
2662
36
                return NULL;
2663
36
            }
2664
11.1k
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2665
11.1k
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2666
0
                np->description = strdup(quoted_string_buffer);
2667
0
            }
2668
11.1k
            break;
2669
2670
109
        case REFERENCE:
2671
109
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2672
109
            if (type != QUOTESTRING) {
2673
11
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2674
11
                free_node(np);
2675
11
                return NULL;
2676
11
            }
2677
98
            np->reference = strdup(quoted_string_buffer);
2678
98
            break;
2679
3.04k
        case INDEX:
2680
3.04k
            if (np->augments) {
2681
1
                print_error("Cannot have both INDEX and AUGMENTS", token,
2682
1
                            type);
2683
1
                free_node(np);
2684
1
                return NULL;
2685
1
            }
2686
3.04k
            np->indexes = getIndexes(fp, &np->indexes);
2687
3.04k
            if (np->indexes == NULL) {
2688
15
                print_error("Bad INDEX list", token, type);
2689
15
                free_node(np);
2690
15
                return NULL;
2691
15
            }
2692
3.03k
            break;
2693
3.03k
        case AUGMENTS:
2694
459
            if (np->indexes) {
2695
1
                print_error("Cannot have both INDEX and AUGMENTS", token,
2696
1
                            type);
2697
1
                free_node(np);
2698
1
                return NULL;
2699
1
            }
2700
458
            np->indexes = getIndexes(fp, &np->indexes);
2701
458
            if (np->indexes == NULL) {
2702
2
                print_error("Bad AUGMENTS list", token, type);
2703
2
                free_node(np);
2704
2
                return NULL;
2705
2
            }
2706
456
            np->augments = strdup(np->indexes->ilabel);
2707
456
            free_indexes(&np->indexes);
2708
456
            break;
2709
2.12k
        case DEFVAL:
2710
            /*
2711
             * Mark's defVal section 
2712
             */
2713
2.12k
            type = get_token(fp, quoted_string_buffer,
2714
2.12k
                             sizeof(quoted_string_buffer));
2715
2.12k
            if (type != LEFTBRACKET) {
2716
12
                print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2717
12
                            type);
2718
12
                free_node(np);
2719
12
                return NULL;
2720
12
            }
2721
2722
2.11k
            {
2723
2.11k
                int             level = 1;
2724
2.11k
                char            defbuf[512];
2725
2726
2.11k
                defbuf[0] = 0;
2727
433k
                while (1) {
2728
433k
                    type = get_token(fp, quoted_string_buffer,
2729
433k
                                     sizeof(quoted_string_buffer));
2730
433k
                    if ((type == RIGHTBRACKET && --level == 0)
2731
431k
                        || type == ENDOFFILE)
2732
2.11k
                        break;
2733
431k
                    else if (type == LEFTBRACKET)
2734
317k
                        level++;
2735
431k
                    if (type == QUOTESTRING)
2736
301
                        strlcat(defbuf, "\\\"", sizeof(defbuf));
2737
431k
                    strlcat(defbuf, quoted_string_buffer, sizeof(defbuf));
2738
431k
                    if (type == QUOTESTRING)
2739
301
                        strlcat(defbuf, "\\\"", sizeof(defbuf));
2740
431k
                    strlcat(defbuf, " ", sizeof(defbuf));
2741
431k
                }
2742
2743
2.11k
                if (type != RIGHTBRACKET) {
2744
70
                    print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2745
70
                                type);
2746
70
                    free_node(np);
2747
70
                    return NULL;
2748
70
                }
2749
2750
                /*
2751
                 * Ensure strlen(defbuf) is above zero
2752
                 */
2753
2.04k
                if (strlen(defbuf) == 0) {
2754
1
                    print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2755
1
                                type);
2756
1
                    free_node(np);
2757
1
                    return NULL;
2758
1
                }
2759
2.04k
                defbuf[strlen(defbuf) - 1] = 0;
2760
2.04k
                np->defaultValue = strdup(defbuf);
2761
2.04k
            }
2762
2763
0
            break;
2764
2765
52
        case NUM_ENTRIES:
2766
52
            if (tossObjectIdentifier(fp) != OBJID) {
2767
37
                print_error("Bad Object Identifier", token, type);
2768
37
                free_node(np);
2769
37
                return NULL;
2770
37
            }
2771
15
            break;
2772
2773
80
        default:
2774
80
            print_error("Bad format of optional clauses", token, type);
2775
80
            free_node(np);
2776
80
            return NULL;
2777
2778
17.0k
        }
2779
16.8k
        type = get_token(fp, token, MAXTOKEN);
2780
16.8k
    }
2781
13.1k
    if (type != EQUALS) {
2782
73
        print_error("Bad format", token, type);
2783
73
        free_node(np);
2784
73
        return NULL;
2785
73
    }
2786
13.0k
    return merge_parse_objectid(np, fp, name);
2787
13.1k
}
2788
2789
/*
2790
 * Parses an OBJECT GROUP macro.
2791
 * Returns 0 on error.
2792
 *
2793
 * Also parses object-identity, since they are similar (ignore STATUS).
2794
 *   - WJH 10/96
2795
 */
2796
static struct node *
2797
parse_objectgroup(FILE * fp, char *name, int what, struct objgroup **ol)
2798
3.88k
{
2799
3.88k
    int             type;
2800
3.88k
    char            token[MAXTOKEN];
2801
3.88k
    char            quoted_string_buffer[MAXQUOTESTR];
2802
3.88k
    struct node    *np;
2803
2804
3.88k
    np = alloc_node(current_module);
2805
3.88k
    if (np == NULL)
2806
0
        return (NULL);
2807
3.88k
    type = get_token(fp, token, MAXTOKEN);
2808
3.88k
    if (type == what) {
2809
2.07k
        type = get_token(fp, token, MAXTOKEN);
2810
2.07k
        if (type != LEFTBRACKET) {
2811
199
            print_error("Expected \"{\"", token, type);
2812
199
            goto skip;
2813
199
        }
2814
4.62k
        do {
2815
4.62k
            struct objgroup *o;
2816
4.62k
            type = get_token(fp, token, MAXTOKEN);
2817
4.62k
            if (type != LABEL) {
2818
328
                print_error("Bad identifier", token, type);
2819
328
                goto skip;
2820
328
            }
2821
4.29k
            o = (struct objgroup *) malloc(sizeof(struct objgroup));
2822
4.29k
            if (!o) {
2823
0
                print_error("Resource failure", token, type);
2824
0
                goto skip;
2825
0
            }
2826
4.29k
            o->line = mibLine;
2827
4.29k
            o->name = strdup(token);
2828
4.29k
            o->next = *ol;
2829
4.29k
            *ol = o;
2830
4.29k
            type = get_token(fp, token, MAXTOKEN);
2831
4.29k
        } while (type == COMMA);
2832
1.55k
        if (type != RIGHTBRACKET) {
2833
979
            print_error("Expected \"}\" after list", token, type);
2834
979
            goto skip;
2835
979
        }
2836
571
        type = get_token(fp, token, type);
2837
571
    }
2838
2.37k
    if (type != STATUS) {
2839
988
        print_error("Expected STATUS", token, type);
2840
988
        goto skip;
2841
988
    }
2842
1.38k
    type = get_token(fp, token, MAXTOKEN);
2843
1.38k
    if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
2844
258
        print_error("Bad STATUS value", token, type);
2845
258
        goto skip;
2846
258
    }
2847
1.12k
    type = get_token(fp, token, MAXTOKEN);
2848
1.12k
    if (type != DESCRIPTION) {
2849
545
        print_error("Expected DESCRIPTION", token, type);
2850
545
        goto skip;
2851
545
    }
2852
584
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2853
584
    if (type != QUOTESTRING) {
2854
7
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2855
7
        free_node(np);
2856
7
        return NULL;
2857
7
    }
2858
577
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2859
577
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2860
0
        np->description = strdup(quoted_string_buffer);
2861
0
    }
2862
577
    type = get_token(fp, token, MAXTOKEN);
2863
577
    if (type == REFERENCE) {
2864
315
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2865
315
        if (type != QUOTESTRING) {
2866
2
            print_error("Bad REFERENCE", quoted_string_buffer, type);
2867
2
            free_node(np);
2868
2
            return NULL;
2869
2
        }
2870
313
        np->reference = strdup(quoted_string_buffer);
2871
313
        type = get_token(fp, token, MAXTOKEN);
2872
313
    }
2873
575
    if (type != EQUALS)
2874
138
        print_error("Expected \"::=\"", token, type);
2875
3.87k
  skip:
2876
40.4k
    while (type != EQUALS && type != ENDOFFILE)
2877
36.5k
        type = get_token(fp, token, MAXTOKEN);
2878
2879
3.87k
    return merge_parse_objectid(np, fp, name);
2880
575
}
2881
2882
/*
2883
 * Parses a NOTIFICATION-TYPE macro.
2884
 * Returns 0 on error.
2885
 */
2886
static struct node *
2887
parse_notificationDefinition(FILE * fp, char *name)
2888
1.23k
{
2889
1.23k
    register int    type;
2890
1.23k
    char            token[MAXTOKEN];
2891
1.23k
    char            quoted_string_buffer[MAXQUOTESTR];
2892
1.23k
    register struct node *np;
2893
2894
1.23k
    np = alloc_node(current_module);
2895
1.23k
    if (np == NULL)
2896
0
        return (NULL);
2897
1.23k
    type = get_token(fp, token, MAXTOKEN);
2898
45.7k
    while (type != EQUALS && type != ENDOFFILE) {
2899
44.5k
        switch (type) {
2900
290
        case DESCRIPTION:
2901
290
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2902
290
            if (type != QUOTESTRING) {
2903
10
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2904
10
                goto free_node;
2905
10
            }
2906
280
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2907
280
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2908
0
                np->description = strdup(quoted_string_buffer);
2909
0
            }
2910
280
            break;
2911
335
        case REFERENCE:
2912
335
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2913
335
            if (type != QUOTESTRING) {
2914
15
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2915
15
                goto free_node;
2916
15
            }
2917
320
            free(np->reference);
2918
320
            np->reference = strdup(quoted_string_buffer);
2919
320
            break;
2920
1.13k
        case OBJECTS:
2921
1.13k
            np->varbinds = getVarbinds(fp, &np->varbinds);
2922
1.13k
            if (!np->varbinds) {
2923
15
                print_error("Bad OBJECTS list", token, type);
2924
15
                goto free_node;
2925
15
            }
2926
1.12k
            break;
2927
42.8k
        default:
2928
            /*
2929
             * NOTHING 
2930
             */
2931
42.8k
            break;
2932
44.5k
        }
2933
44.5k
        type = get_token(fp, token, MAXTOKEN);
2934
44.5k
    }
2935
1.19k
    return merge_parse_objectid(np, fp, name);
2936
2937
40
free_node:
2938
40
    free_node(np);
2939
40
    return NULL;
2940
1.23k
}
2941
2942
/*
2943
 * Parses a TRAP-TYPE macro.
2944
 * Returns 0 on error.
2945
 */
2946
static struct node *
2947
parse_trapDefinition(FILE * fp, char *name)
2948
530
{
2949
530
    register int    type;
2950
530
    char            token[MAXTOKEN];
2951
530
    char            quoted_string_buffer[MAXQUOTESTR];
2952
530
    register struct node *np;
2953
2954
530
    np = alloc_node(current_module);
2955
530
    if (np == NULL)
2956
0
        return (NULL);
2957
530
    type = get_token(fp, token, MAXTOKEN);
2958
15.4k
    while (type != EQUALS && type != ENDOFFILE) {
2959
15.0k
        switch (type) {
2960
210
        case DESCRIPTION:
2961
210
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2962
210
            if (type != QUOTESTRING) {
2963
9
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2964
9
                goto free_node;
2965
9
            }
2966
201
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2967
201
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2968
0
                np->description = strdup(quoted_string_buffer);
2969
0
            }
2970
201
            break;
2971
218
        case REFERENCE:
2972
            /* I'm not sure REFERENCEs are legal in smiv1 traps??? */
2973
218
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2974
218
            if (type != QUOTESTRING) {
2975
17
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2976
17
                goto free_node;
2977
17
            }
2978
201
            np->reference = strdup(quoted_string_buffer);
2979
201
            break;
2980
689
        case ENTERPRISE:
2981
689
            type = get_token(fp, token, MAXTOKEN);
2982
689
            if (type == LEFTBRACKET) {
2983
200
                type = get_token(fp, token, MAXTOKEN);
2984
200
                if (type != LABEL) {
2985
3
                    print_error("Bad Trap Format", token, type);
2986
3
                    goto free_node;
2987
3
                }
2988
197
                np->parent = strdup(token);
2989
                /*
2990
                 * Get right bracket 
2991
                 */
2992
197
                type = get_token(fp, token, MAXTOKEN);
2993
489
            } else if (type == LABEL) {
2994
476
                np->parent = strdup(token);
2995
476
            } else {
2996
13
                goto free_node;
2997
13
            }
2998
673
            break;
2999
673
        case VARIABLES:
3000
308
            np->varbinds = getVarbinds(fp, &np->varbinds);
3001
308
            if (!np->varbinds) {
3002
17
                print_error("Bad VARIABLES list", token, type);
3003
17
                goto free_node;
3004
17
            }
3005
291
            break;
3006
13.5k
        default:
3007
            /*
3008
             * NOTHING 
3009
             */
3010
13.5k
            break;
3011
15.0k
        }
3012
14.9k
        type = get_token(fp, token, MAXTOKEN);
3013
14.9k
    }
3014
471
    type = get_token(fp, token, MAXTOKEN);
3015
3016
471
    np->label = strdup(name);
3017
3018
471
    if (type != NUMBER) {
3019
124
        print_error("Expected a Number", token, type);
3020
124
        goto free_node;
3021
124
    }
3022
347
    np->subid = strtoul(token, NULL, 10);
3023
347
    np->next = alloc_node(current_module);
3024
347
    if (np->next == NULL)
3025
0
        goto free_node;
3026
3027
    /* Catch the syntax error */
3028
347
    if (np->parent == NULL) {
3029
3
        gMibError = MODULE_SYNTAX_ERROR;
3030
3
        goto free_next_node;
3031
3
    }
3032
3033
344
    np->next->parent = np->parent;
3034
344
    np->parent = NULL;
3035
344
    if (asprintf(&np->parent, "%s#", np->next->parent) < 0)
3036
0
        goto free_next_node;
3037
344
    np->next->label = strdup(np->parent);
3038
344
    return np;
3039
3040
3
free_next_node:
3041
3
    free_node(np->next);
3042
3043
186
free_node:
3044
186
    free_node(np);
3045
186
    return NULL;
3046
3
}
3047
3048
3049
/*
3050
 * Parses a compliance macro
3051
 * Returns 0 on error.
3052
 */
3053
static int
3054
eat_syntax(FILE * fp, char *token, int maxtoken)
3055
4.37k
{
3056
4.37k
    int             type, nexttype;
3057
4.37k
    struct node    *np = alloc_node(current_module);
3058
4.37k
    char            nexttoken[MAXTOKEN];
3059
3060
4.37k
    if (!np)
3061
0
  return 0;
3062
3063
4.37k
    type = get_token(fp, token, maxtoken);
3064
4.37k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
3065
4.37k
    switch (type) {
3066
720
    case INTEGER:
3067
1.44k
    case INTEGER32:
3068
1.51k
    case UINTEGER32:
3069
1.86k
    case UNSIGNED32:
3070
2.22k
    case COUNTER:
3071
2.29k
    case GAUGE:
3072
2.36k
    case BITSTRING:
3073
2.67k
    case LABEL:
3074
2.67k
        if (nexttype == LEFTBRACKET) {
3075
            /*
3076
             * if there is an enumeration list, parse it 
3077
             */
3078
769
            np->enums = parse_enumlist(fp, &np->enums);
3079
769
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3080
1.91k
        } else if (nexttype == LEFTPAREN) {
3081
            /*
3082
             * if there is a range list, parse it 
3083
             */
3084
1.23k
            np->ranges = parse_ranges(fp, &np->ranges);
3085
1.23k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3086
1.23k
        }
3087
2.67k
        break;
3088
338
    case OCTETSTR:
3089
408
    case KW_OPAQUE:
3090
        /*
3091
         * parse any SIZE specification 
3092
         */
3093
408
        if (nexttype == LEFTPAREN) {
3094
281
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3095
281
            if (nexttype == SIZE) {
3096
203
                nexttype = get_token(fp, nexttoken, MAXTOKEN);
3097
203
                if (nexttype == LEFTPAREN) {
3098
94
                    np->ranges = parse_ranges(fp, &np->ranges);
3099
94
                    nexttype = get_token(fp, nexttoken, MAXTOKEN);      /* ) */
3100
94
                    if (nexttype == RIGHTPAREN) {
3101
68
                        nexttype = get_token(fp, nexttoken, MAXTOKEN);
3102
68
                        break;
3103
68
                    }
3104
94
                }
3105
203
            }
3106
213
            print_error("Bad SIZE syntax", token, type);
3107
213
            free_node(np);
3108
213
            return nexttype;
3109
281
        }
3110
127
        break;
3111
127
    case OBJID:
3112
68
    case NETADDR:
3113
262
    case IPADDR:
3114
275
    case TIMETICKS:
3115
341
    case NUL:
3116
689
    case NSAPADDRESS:
3117
886
    case COUNTER64:
3118
886
        break;
3119
400
    default:
3120
400
        print_error("Bad syntax", token, type);
3121
400
        free_node(np);
3122
400
        return nexttype;
3123
4.37k
    }
3124
3.76k
    free_node(np);
3125
3.76k
    return nexttype;
3126
4.37k
}
3127
3128
static int
3129
compliance_lookup(const char *name, int modid)
3130
15.0k
{
3131
15.0k
    struct objgroup *op;
3132
3133
15.0k
    if (modid != -1)
3134
901
        return find_tree_node(name, modid) != NULL;
3135
3136
14.1k
    op = malloc(sizeof(struct objgroup));
3137
14.1k
    if (!op)
3138
0
        return 0;
3139
3140
14.1k
    op->next = objgroups;
3141
14.1k
    op->name = strdup(name);
3142
14.1k
    if (!op->name) {
3143
0
        free(op);
3144
0
        return 0;
3145
0
    }
3146
14.1k
    op->line = mibLine;
3147
14.1k
    objgroups = op;
3148
14.1k
    return 1;
3149
14.1k
}
3150
3151
static struct node *
3152
parse_compliance(FILE * fp, char *name)
3153
10.4k
{
3154
10.4k
    int             type;
3155
10.4k
    char            token[MAXTOKEN];
3156
10.4k
    char            quoted_string_buffer[MAXQUOTESTR];
3157
10.4k
    struct node    *np;
3158
3159
10.4k
    np = alloc_node(current_module);
3160
10.4k
    if (np == NULL)
3161
0
        return (NULL);
3162
10.4k
    type = get_token(fp, token, MAXTOKEN);
3163
10.4k
    if (type != STATUS) {
3164
551
        print_error("Expected STATUS", token, type);
3165
551
        goto skip;
3166
551
    }
3167
9.93k
    type = get_token(fp, token, MAXTOKEN);
3168
9.93k
    if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
3169
361
        print_error("Bad STATUS", token, type);
3170
361
        goto skip;
3171
361
    }
3172
9.57k
    type = get_token(fp, token, MAXTOKEN);
3173
9.57k
    if (type != DESCRIPTION) {
3174
631
        print_error("Expected DESCRIPTION", token, type);
3175
631
        goto skip;
3176
631
    }
3177
8.94k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3178
8.94k
    if (type != QUOTESTRING) {
3179
412
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3180
412
        goto skip;
3181
412
    }
3182
8.53k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3183
8.53k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS))
3184
0
        np->description = strdup(quoted_string_buffer);
3185
8.53k
    type = get_token(fp, token, MAXTOKEN);
3186
8.53k
    if (type == REFERENCE) {
3187
268
        type = get_token(fp, quoted_string_buffer,
3188
268
                         sizeof(quoted_string_buffer));
3189
268
        if (type != QUOTESTRING) {
3190
207
            print_error("Bad REFERENCE", quoted_string_buffer, type);
3191
207
            goto skip;
3192
207
        }
3193
61
        np->reference = strdup(quoted_string_buffer);
3194
61
        type = get_token(fp, token, MAXTOKEN);
3195
61
    }
3196
8.32k
    if (type != MODULE) {
3197
763
        print_error("Expected MODULE", token, type);
3198
763
        goto skip;
3199
763
    }
3200
10.2k
    while (type == MODULE) {
3201
8.98k
        int             modid = -1;
3202
8.98k
        char            modname[MAXTOKEN];
3203
8.98k
        type = get_token(fp, token, MAXTOKEN);
3204
8.98k
        if (type == LABEL
3205
2.20k
            && strcmp(token, module_name(current_module, modname))) {
3206
1.83k
            modid = read_module_internal(token);
3207
1.83k
            if (modid != MODULE_LOADED_OK
3208
1.83k
                && modid != MODULE_ALREADY_LOADED) {
3209
686
                print_error("Unknown module", token, type);
3210
686
                goto skip;
3211
686
            }
3212
1.14k
            modid = which_module(token);
3213
1.14k
            type = get_token(fp, token, MAXTOKEN);
3214
1.14k
        }
3215
8.29k
        if (type == MANDATORYGROUPS) {
3216
3.93k
            type = get_token(fp, token, MAXTOKEN);
3217
3.93k
            if (type != LEFTBRACKET) {
3218
34
                print_error("Expected \"{\"", token, type);
3219
34
                goto skip;
3220
34
            }
3221
7.31k
            do {
3222
7.31k
                type = get_token(fp, token, MAXTOKEN);
3223
7.31k
                if (type != LABEL) {
3224
123
                    print_error("Bad group name", token, type);
3225
123
                    goto skip;
3226
123
                }
3227
7.19k
                if (!compliance_lookup(token, modid))
3228
92
                    print_error("Unknown group", token, type);
3229
7.19k
                type = get_token(fp, token, MAXTOKEN);
3230
7.19k
            } while (type == COMMA);
3231
3.77k
            if (type != RIGHTBRACKET) {
3232
691
                print_error("Expected \"}\"", token, type);
3233
691
                goto skip;
3234
691
            }
3235
3.08k
            type = get_token(fp, token, MAXTOKEN);
3236
3.08k
        }
3237
10.9k
        while (type == GROUP || type == OBJECT) {
3238
8.29k
            if (type == GROUP) {
3239
1.34k
                type = get_token(fp, token, MAXTOKEN);
3240
1.34k
                if (type != LABEL) {
3241
245
                    print_error("Bad group name", token, type);
3242
245
                    goto skip;
3243
245
                }
3244
1.09k
                if (!compliance_lookup(token, modid))
3245
345
                    print_error("Unknown group", token, type);
3246
1.09k
                type = get_token(fp, token, MAXTOKEN);
3247
6.95k
            } else {
3248
6.95k
                type = get_token(fp, token, MAXTOKEN);
3249
6.95k
                if (type != LABEL) {
3250
171
                    print_error("Bad object name", token, type);
3251
171
                    goto skip;
3252
171
                }
3253
6.78k
                if (!compliance_lookup(token, modid))
3254
131
                    print_error("Unknown group", token, type);
3255
6.78k
                type = get_token(fp, token, MAXTOKEN);
3256
6.78k
                if (type == SYNTAX)
3257
3.53k
                    type = eat_syntax(fp, token, MAXTOKEN);
3258
6.78k
                if (type == WRSYNTAX)
3259
839
                    type = eat_syntax(fp, token, MAXTOKEN);
3260
6.78k
                if (type == MINACCESS) {
3261
1.94k
                    type = get_token(fp, token, MAXTOKEN);
3262
1.94k
                    if (type != NOACCESS && type != ACCNOTIFY
3263
1.70k
                        && type != READONLY && type != WRITEONLY
3264
341
                        && type != READCREATE && type != READWRITE) {
3265
69
                        print_error("Bad MIN-ACCESS spec", token, type);
3266
69
                        goto skip;
3267
69
                    }
3268
1.87k
                    type = get_token(fp, token, MAXTOKEN);
3269
1.87k
                }
3270
6.78k
            }
3271
7.80k
            if (type != DESCRIPTION) {
3272
3.88k
                print_error("Expected DESCRIPTION", token, type);
3273
3.88k
                goto skip;
3274
3.88k
            }
3275
3.92k
            type = get_token(fp, token, MAXTOKEN);
3276
3.92k
            if (type != QUOTESTRING) {
3277
435
                print_error("Bad DESCRIPTION", token, type);
3278
435
                goto skip;
3279
435
            }
3280
3.49k
            type = get_token(fp, token, MAXTOKEN);
3281
3.49k
        }
3282
7.45k
    }
3283
10.4k
  skip:
3284
308k
    while (type != EQUALS && type != ENDOFFILE)
3285
297k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3286
3287
10.4k
    return merge_parse_objectid(np, fp, name);
3288
7.56k
}
3289
3290
3291
/*
3292
 * Parses a capabilities macro
3293
 * Returns 0 on error.
3294
 */
3295
static struct node *
3296
parse_capabilities(FILE * fp, char *name)
3297
3.96k
{
3298
3.96k
    int             type;
3299
3.96k
    char            token[MAXTOKEN];
3300
3.96k
    char            quoted_string_buffer[MAXQUOTESTR];
3301
3.96k
    struct node    *np;
3302
3303
3.96k
    np = alloc_node(current_module);
3304
3.96k
    if (np == NULL)
3305
0
        return (NULL);
3306
3.96k
    type = get_token(fp, token, MAXTOKEN);
3307
3.96k
    if (type != PRODREL) {
3308
591
        print_error("Expected PRODUCT-RELEASE", token, type);
3309
591
        goto skip;
3310
591
    }
3311
3.37k
    type = get_token(fp, token, MAXTOKEN);
3312
3.37k
    if (type != QUOTESTRING) {
3313
626
        print_error("Expected STRING after PRODUCT-RELEASE", token, type);
3314
626
        goto skip;
3315
626
    }
3316
2.74k
    type = get_token(fp, token, MAXTOKEN);
3317
2.74k
    if (type != STATUS) {
3318
585
        print_error("Expected STATUS", token, type);
3319
585
        goto skip;
3320
585
    }
3321
2.16k
    type = get_token(fp, token, MAXTOKEN);
3322
2.16k
    if (type != CURRENT && type != OBSOLETE) {
3323
341
        print_error("STATUS should be current or obsolete", token, type);
3324
341
        goto skip;
3325
341
    }
3326
1.82k
    type = get_token(fp, token, MAXTOKEN);
3327
1.82k
    if (type != DESCRIPTION) {
3328
524
        print_error("Expected DESCRIPTION", token, type);
3329
524
        goto skip;
3330
524
    }
3331
1.29k
    type = get_token(fp, quoted_string_buffer, sizeof(quoted_string_buffer));
3332
1.29k
    if (type != QUOTESTRING) {
3333
411
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3334
411
        goto skip;
3335
411
    }
3336
887
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3337
887
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
3338
0
        np->description = strdup(quoted_string_buffer);
3339
0
    }
3340
887
    type = get_token(fp, token, MAXTOKEN);
3341
887
    if (type == REFERENCE) {
3342
152
        type = get_token(fp, quoted_string_buffer,
3343
152
                         sizeof(quoted_string_buffer));
3344
152
        if (type != QUOTESTRING) {
3345
79
            print_error("Bad REFERENCE", quoted_string_buffer, type);
3346
79
            goto skip;
3347
79
        }
3348
73
        np->reference = strdup(quoted_string_buffer);
3349
73
        type = get_token(fp, token, type);
3350
73
    }
3351
809
    while (type == SUPPORTS) {
3352
582
        int             modid;
3353
582
        struct tree    *tp;
3354
3355
582
        type = get_token(fp, token, MAXTOKEN);
3356
582
        if (type != LABEL) {
3357
71
            print_error("Bad module name", token, type);
3358
71
            goto skip;
3359
71
        }
3360
511
        modid = read_module_internal(token);
3361
511
        if (modid != MODULE_LOADED_OK && modid != MODULE_ALREADY_LOADED) {
3362
29
            print_error("Module not found", token, type);
3363
29
            goto skip;
3364
29
        }
3365
482
        modid = which_module(token);
3366
482
        type = get_token(fp, token, MAXTOKEN);
3367
482
        if (type != INCLUDES) {
3368
26
            print_error("Expected INCLUDES", token, type);
3369
26
            goto skip;
3370
26
        }
3371
456
        type = get_token(fp, token, MAXTOKEN);
3372
456
        if (type != LEFTBRACKET) {
3373
13
            print_error("Expected \"{\"", token, type);
3374
13
            goto skip;
3375
13
        }
3376
535
        do {
3377
535
            type = get_token(fp, token, MAXTOKEN);
3378
535
            if (type != LABEL) {
3379
350
                print_error("Expected group name", token, type);
3380
350
                goto skip;
3381
350
            }
3382
185
            tp = find_tree_node(token, modid);
3383
185
            if (!tp)
3384
179
                print_error("Group not found in module", token, type);
3385
185
            type = get_token(fp, token, MAXTOKEN);
3386
185
        } while (type == COMMA);
3387
93
        if (type != RIGHTBRACKET) {
3388
92
            print_error("Expected \"}\" after group list", token, type);
3389
92
            goto skip;
3390
92
        }
3391
1
        type = get_token(fp, token, MAXTOKEN);
3392
1
        while (type == VARIATION) {
3393
0
            type = get_token(fp, token, MAXTOKEN);
3394
0
            if (type != LABEL) {
3395
0
                print_error("Bad object name", token, type);
3396
0
                goto skip;
3397
0
            }
3398
0
            tp = find_tree_node(token, modid);
3399
0
            if (!tp)
3400
0
                print_error("Object not found in module", token, type);
3401
0
            type = get_token(fp, token, MAXTOKEN);
3402
0
            if (type == SYNTAX) {
3403
0
                type = eat_syntax(fp, token, MAXTOKEN);
3404
0
            }
3405
0
            if (type == WRSYNTAX) {
3406
0
                type = eat_syntax(fp, token, MAXTOKEN);
3407
0
            }
3408
0
            if (type == ACCESS) {
3409
0
                type = get_token(fp, token, MAXTOKEN);
3410
0
                if (type != ACCNOTIFY && type != READONLY
3411
0
                    && type != READWRITE && type != READCREATE
3412
0
                    && type != WRITEONLY && type != NOTIMPL) {
3413
0
                    print_error("Bad ACCESS", token, type);
3414
0
                    goto skip;
3415
0
                }
3416
0
                type = get_token(fp, token, MAXTOKEN);
3417
0
            }
3418
0
            if (type == CREATEREQ) {
3419
0
                type = get_token(fp, token, MAXTOKEN);
3420
0
                if (type != LEFTBRACKET) {
3421
0
                    print_error("Expected \"{\"", token, type);
3422
0
                    goto skip;
3423
0
                }
3424
0
                do {
3425
0
                    type = get_token(fp, token, MAXTOKEN);
3426
0
                    if (type != LABEL) {
3427
0
                        print_error("Bad object name in list", token,
3428
0
                                    type);
3429
0
                        goto skip;
3430
0
                    }
3431
0
                    type = get_token(fp, token, MAXTOKEN);
3432
0
                } while (type == COMMA);
3433
0
                if (type != RIGHTBRACKET) {
3434
0
                    print_error("Expected \"}\" after list", token, type);
3435
0
                    goto skip;
3436
0
                }
3437
0
                type = get_token(fp, token, MAXTOKEN);
3438
0
            }
3439
0
            if (type == DEFVAL) {
3440
0
                int             level = 1;
3441
0
                type = get_token(fp, token, MAXTOKEN);
3442
0
                if (type != LEFTBRACKET) {
3443
0
                    print_error("Expected \"{\" after DEFVAL", token,
3444
0
                                type);
3445
0
                    goto skip;
3446
0
                }
3447
0
                do {
3448
0
                    type = get_token(fp, token, MAXTOKEN);
3449
0
                    if (type == LEFTBRACKET)
3450
0
                        level++;
3451
0
                    else if (type == RIGHTBRACKET)
3452
0
                        level--;
3453
0
                } while ((type != RIGHTBRACKET || level != 0)
3454
0
                         && type != ENDOFFILE);
3455
0
                if (type != RIGHTBRACKET) {
3456
0
                    print_error("Missing \"}\" after DEFVAL", token, type);
3457
0
                    goto skip;
3458
0
                }
3459
0
                type = get_token(fp, token, MAXTOKEN);
3460
0
            }
3461
0
            if (type != DESCRIPTION) {
3462
0
                print_error("Expected DESCRIPTION", token, type);
3463
0
                goto skip;
3464
0
            }
3465
0
            type = get_token(fp, quoted_string_buffer,
3466
0
                             sizeof(quoted_string_buffer));
3467
0
            if (type != QUOTESTRING) {
3468
0
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3469
0
                goto skip;
3470
0
            }
3471
0
            type = get_token(fp, token, MAXTOKEN);
3472
0
        }
3473
1
    }
3474
227
    if (type != EQUALS)
3475
172
        print_error("Expected \"::=\"", token, type);
3476
3.96k
  skip:
3477
310k
    while (type != EQUALS && type != ENDOFFILE) {
3478
306k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3479
306k
    }
3480
3.96k
    return merge_parse_objectid(np, fp, name);
3481
227
}
3482
3483
/*
3484
 * Parses a module identity macro
3485
 * Returns 0 on error.
3486
 */
3487
static void
3488
check_utc(const char *utc)
3489
5.46k
{
3490
5.46k
    int             len, year, month, day, hour, minute;
3491
3492
5.46k
    len = strlen(utc);
3493
5.46k
    if (len == 0) {
3494
203
        print_error("Timestamp has zero length", utc, QUOTESTRING);
3495
203
        return;
3496
203
    }
3497
5.25k
    if (utc[len - 1] != 'Z' && utc[len - 1] != 'z') {
3498
888
        print_error("Timestamp should end with Z", utc, QUOTESTRING);
3499
888
        return;
3500
888
    }
3501
4.36k
    if (len == 11) {
3502
698
        len = sscanf(utc, "%2d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
3503
698
                     &minute);
3504
698
        year += 1900;
3505
3.67k
    } else if (len == 13)
3506
421
        len = sscanf(utc, "%4d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
3507
421
                     &minute);
3508
3.25k
    else {
3509
3.25k
        print_error("Bad timestamp format (11 or 13 characters)",
3510
3.25k
                    utc, QUOTESTRING);
3511
3.25k
        return;
3512
3.25k
    }
3513
1.11k
    if (len != 5) {
3514
435
        print_error("Bad timestamp format", utc, QUOTESTRING);
3515
435
        return;
3516
435
    }
3517
684
    if (month < 1 || month > 12)
3518
221
        print_error("Bad month in timestamp", utc, QUOTESTRING);
3519
684
    if (day < 1 || day > 31)
3520
208
        print_error("Bad day in timestamp", utc, QUOTESTRING);
3521
684
    if (hour < 0 || hour > 23)
3522
354
        print_error("Bad hour in timestamp", utc, QUOTESTRING);
3523
684
    if (minute < 0 || minute > 59)
3524
193
        print_error("Bad minute in timestamp", utc, QUOTESTRING);
3525
684
}
3526
3527
static struct node *
3528
parse_moduleIdentity(FILE * fp, char *name)
3529
5.91k
{
3530
5.91k
    register int    type;
3531
5.91k
    char            token[MAXTOKEN];
3532
5.91k
    char            quoted_string_buffer[MAXQUOTESTR];
3533
5.91k
    register struct node *np;
3534
3535
5.91k
    np = alloc_node(current_module);
3536
5.91k
    if (np == NULL)
3537
0
        return (NULL);
3538
5.91k
    type = get_token(fp, token, MAXTOKEN);
3539
5.91k
    if (type != LASTUPDATED) {
3540
1.01k
        print_error("Expected LAST-UPDATED", token, type);
3541
1.01k
        goto skip;
3542
1.01k
    }
3543
4.90k
    type = get_token(fp, token, MAXTOKEN);
3544
4.90k
    if (type != QUOTESTRING) {
3545
318
        print_error("Need STRING for LAST-UPDATED", token, type);
3546
318
        goto skip;
3547
318
    }
3548
4.58k
    check_utc(token);
3549
4.58k
    type = get_token(fp, token, MAXTOKEN);
3550
4.58k
    if (type != ORGANIZATION) {
3551
1.33k
        print_error("Expected ORGANIZATION", token, type);
3552
1.33k
        goto skip;
3553
1.33k
    }
3554
3.25k
    type = get_token(fp, token, MAXTOKEN);
3555
3.25k
    if (type != QUOTESTRING) {
3556
262
        print_error("Bad ORGANIZATION", token, type);
3557
262
        goto skip;
3558
262
    }
3559
2.98k
    type = get_token(fp, token, MAXTOKEN);
3560
2.98k
    if (type != CONTACTINFO) {
3561
610
        print_error("Expected CONTACT-INFO", token, type);
3562
610
        goto skip;
3563
610
    }
3564
2.37k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3565
2.37k
    if (type != QUOTESTRING) {
3566
205
        print_error("Bad CONTACT-INFO", quoted_string_buffer, type);
3567
205
        goto skip;
3568
205
    }
3569
2.17k
    type = get_token(fp, token, MAXTOKEN);
3570
2.17k
    if (type != DESCRIPTION) {
3571
412
        print_error("Expected DESCRIPTION", token, type);
3572
412
        goto skip;
3573
412
    }
3574
1.76k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3575
1.76k
    if (type != QUOTESTRING) {
3576
95
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3577
95
        goto skip;
3578
95
    }
3579
1.66k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3580
1.66k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
3581
0
        np->description = strdup(quoted_string_buffer);
3582
0
    }
3583
1.66k
    type = get_token(fp, token, MAXTOKEN);
3584
2.04k
    while (type == REVISION) {
3585
1.34k
        type = get_token(fp, token, MAXTOKEN);
3586
1.34k
        if (type != QUOTESTRING) {
3587
472
            print_error("Bad REVISION", token, type);
3588
472
            goto skip;
3589
472
        }
3590
876
        check_utc(token);
3591
876
        type = get_token(fp, token, MAXTOKEN);
3592
876
        if (type != DESCRIPTION) {
3593
292
            print_error("Expected DESCRIPTION", token, type);
3594
292
            goto skip;
3595
292
        }
3596
584
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3597
584
        if (type != QUOTESTRING) {
3598
208
            print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3599
208
            goto skip;
3600
208
        }
3601
376
        type = get_token(fp, token, MAXTOKEN);
3602
376
    }
3603
695
    if (type != EQUALS)
3604
478
        print_error("Expected \"::=\"", token, type);
3605
5.91k
  skip:
3606
172k
    while (type != EQUALS && type != ENDOFFILE) {
3607
166k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3608
166k
    }
3609
5.91k
    return merge_parse_objectid(np, fp, name);
3610
695
}
3611
3612
3613
/*
3614
 * Parses a MACRO definition
3615
 * Expect BEGIN, discard everything to end.
3616
 * Returns 0 on error.
3617
 */
3618
static struct node *
3619
parse_macro(FILE * fp, char *name)
3620
951
{
3621
951
    register int    type;
3622
951
    char            token[MAXTOKEN];
3623
951
    struct node    *np;
3624
951
    int             iLine = mibLine;
3625
3626
951
    np = alloc_node(current_module);
3627
951
    if (np == NULL)
3628
0
        return (NULL);
3629
951
    type = get_token(fp, token, sizeof(token));
3630
2.05k
    while (type != EQUALS && type != ENDOFFILE) {
3631
1.09k
        type = get_token(fp, token, sizeof(token));
3632
1.09k
    }
3633
951
    if (type != EQUALS) {
3634
42
        if (np)
3635
42
            free_node(np);
3636
42
        return NULL;
3637
42
    }
3638
3.08k
    while (type != BEGIN && type != ENDOFFILE) {
3639
2.17k
        type = get_token(fp, token, sizeof(token));
3640
2.17k
    }
3641
909
    if (type != BEGIN) {
3642
33
        if (np)
3643
33
            free_node(np);
3644
33
        return NULL;
3645
33
    }
3646
13.2k
    while (type != END && type != ENDOFFILE) {
3647
12.3k
        type = get_token(fp, token, sizeof(token));
3648
12.3k
    }
3649
876
    if (type != END) {
3650
28
        if (np)
3651
28
            free_node(np);
3652
28
        return NULL;
3653
28
    }
3654
3655
848
    if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3656
848
         NETSNMP_DS_LIB_MIB_WARNINGS)) {
3657
0
        snmp_log(LOG_WARNING,
3658
0
                 "%s MACRO (lines %d..%d parsed and ignored).\n", name,
3659
0
                 iLine, mibLine);
3660
0
    }
3661
3662
848
    return np;
3663
876
}
3664
3665
/*
3666
 * Parses a module import clause
3667
 *   loading any modules referenced
3668
 */
3669
static void
3670
parse_imports(FILE * fp)
3671
3.42k
{
3672
3.42k
    register int    type;
3673
3.42k
    char            token[MAXTOKEN];
3674
3.42k
    char            modbuf[256];
3675
185k
#define MAX_IMPORTS 512
3676
3.42k
    struct module_import *import_list;
3677
3.42k
    int             this_module;
3678
3.42k
    struct module  *mp;
3679
3680
3.42k
    int             import_count = 0;   /* Total number of imported descriptors */
3681
3.42k
    int             i = 0, old_i;       /* index of first import from each module */
3682
3683
3.42k
    import_list = malloc(MAX_IMPORTS * sizeof(*import_list));
3684
3685
3.42k
    type = get_token(fp, token, MAXTOKEN);
3686
3687
    /*
3688
     * Parse the IMPORTS clause
3689
     */
3690
248k
    while (type != SEMI && type != ENDOFFILE) {
3691
245k
        if (type == LABEL) {
3692
182k
            if (import_count == MAX_IMPORTS) {
3693
163
                print_error("Too many imported symbols", token, type);
3694
165k
                do {
3695
165k
                    type = get_token(fp, token, MAXTOKEN);
3696
165k
                } while (type != SEMI && type != ENDOFFILE);
3697
163
                goto out;
3698
163
            }
3699
181k
            import_list[import_count++].label = strdup(token);
3700
181k
        } else if (type == FROM) {
3701
2.75k
            type = get_token(fp, token, MAXTOKEN);
3702
2.75k
            if (import_count == i) {    /* All imports are handled internally */
3703
288
                type = get_token(fp, token, MAXTOKEN);
3704
288
                continue;
3705
288
            }
3706
2.46k
            this_module = which_module(token);
3707
3708
49.7k
            for (old_i = i; i < import_count; ++i)
3709
47.2k
                import_list[i].modid = this_module;
3710
3711
            /*
3712
             * Recursively read any pre-requisite modules
3713
             */
3714
2.46k
            if (read_module_internal(token) == MODULE_NOT_FOUND) {
3715
1.77k
    int found = 0;
3716
29.9k
                for (; old_i < import_count; ++old_i) {
3717
28.1k
                    found += read_import_replacements(token, &import_list[old_i]);
3718
28.1k
                }
3719
1.77k
    if (!found)
3720
1.21k
        print_module_not_found(token);
3721
1.77k
            }
3722
2.46k
        }
3723
245k
        type = get_token(fp, token, MAXTOKEN);
3724
245k
    }
3725
3726
    /* Initialize modid in case the module name was missing. */
3727
56.6k
    for (; i < import_count; ++i)
3728
53.4k
        import_list[i].modid = -1;
3729
3730
    /*
3731
     * Save the import information
3732
     *   in the global module table
3733
     */
3734
8.56M
    for (mp = module_head; mp; mp = mp->next) {
3735
8.56M
        if (mp->modid == current_module) {
3736
3.25k
            if (import_count == 0)
3737
255
                goto out;
3738
3.00k
            if (mp->imports && (mp->imports != root_imports)) {
3739
                /*
3740
                 * this can happen if all modules are in one source file. 
3741
                 */
3742
69.4k
                for (i = 0; i < mp->no_imports; ++i) {
3743
67.6k
                    DEBUGMSGTL(("parse-mibs",
3744
67.6k
                                "#### freeing Module %d '%s' %d\n",
3745
67.6k
                                mp->modid, mp->imports[i].label,
3746
67.6k
                                mp->imports[i].modid));
3747
67.6k
                    free(mp->imports[i].label);
3748
67.6k
                }
3749
1.82k
                free(mp->imports);
3750
1.82k
            }
3751
3.00k
            mp->imports = (struct module_import *)
3752
3.00k
                calloc(import_count, sizeof(struct module_import));
3753
3.00k
            if (mp->imports == NULL)
3754
0
                goto out;
3755
101k
            for (i = 0; i < import_count; ++i) {
3756
98.5k
                mp->imports[i].label = import_list[i].label;
3757
98.5k
                import_list[i].label = NULL;
3758
98.5k
                mp->imports[i].modid = import_list[i].modid;
3759
98.5k
                DEBUGMSGTL(("parse-mibs",
3760
98.5k
                            "#### adding Module %d '%s' %d\n", mp->modid,
3761
98.5k
                            mp->imports[i].label, mp->imports[i].modid));
3762
98.5k
            }
3763
3.00k
            mp->no_imports = import_count;
3764
3.00k
            goto out;
3765
3.00k
        }
3766
8.56M
    }
3767
3768
    /*
3769
     * Shouldn't get this far
3770
     */
3771
0
    print_module_not_found(module_name(current_module, modbuf));
3772
3773
3.42k
out:
3774
185k
    for (i = 0; i < import_count; ++i)
3775
181k
        free(import_list[i].label);
3776
3.42k
    free(import_list);
3777
3.42k
    return;
3778
0
}
3779
3780
3781
3782
/*
3783
 * MIB module handling routines
3784
 */
3785
3786
static void
3787
dump_module_list(void)
3788
0
{
3789
0
    struct module  *mp = module_head;
3790
3791
0
    DEBUGMSGTL(("parse-mibs", "Module list:\n"));
3792
0
    while (mp) {
3793
0
        DEBUGMSGTL(("parse-mibs", "  %s %d %s %d\n", mp->name, mp->modid,
3794
0
                    mp->file, mp->no_imports));
3795
0
        mp = mp->next;
3796
0
    }
3797
0
}
3798
3799
int
3800
which_module(const char *name)
3801
31.4k
{
3802
31.4k
    struct module  *mp;
3803
3804
90.9M
    for (mp = module_head; mp; mp = mp->next)
3805
90.9M
        if (!label_compare(mp->name, name))
3806
14.9k
            return (mp->modid);
3807
3808
16.4k
    DEBUGMSGTL(("parse-mibs", "Module %s not found\n", name));
3809
16.4k
    return (-1);
3810
31.4k
}
3811
3812
/*
3813
 * module_name - copy module name to user buffer, return ptr to same.
3814
 */
3815
char           *
3816
module_name(int modid, char *cp)
3817
124k
{
3818
124k
    struct module  *mp;
3819
3820
2.93M
    for (mp = module_head; mp; mp = mp->next)
3821
2.89M
        if (mp->modid == modid) {
3822
77.9k
            strcpy(cp, mp->name);
3823
77.9k
            return (cp);
3824
77.9k
        }
3825
3826
46.9k
    if (modid != -1) DEBUGMSGTL(("parse-mibs", "Module %d not found\n", modid));
3827
46.9k
    sprintf(cp, "#%d", modid);
3828
46.9k
    return (cp);
3829
124k
}
3830
3831
/*
3832
 *  Backwards compatability
3833
 *  Read newer modules that replace the one specified:-
3834
 *      either all of them (read_module_replacements),
3835
 *      or those relating to a specified identifier (read_import_replacements)
3836
 *      plus an interface to add new replacement requirements
3837
 */
3838
netsnmp_feature_child_of(parse_add_module_replacement, netsnmp_unused);
3839
#ifndef NETSNMP_FEATURE_REMOVE_PARSE_ADD_MODULE_REPLACEMENT
3840
void
3841
add_module_replacement(const char *old_module,
3842
                       const char *new_module_name,
3843
                       const char *tag, int len)
3844
0
{
3845
0
    struct module_compatability *mcp;
3846
3847
0
    mcp = (struct module_compatability *)
3848
0
        calloc(1, sizeof(struct module_compatability));
3849
0
    if (mcp == NULL)
3850
0
        return;
3851
3852
0
    mcp->old_module = strdup(old_module);
3853
0
    mcp->new_module = strdup(new_module_name);
3854
0
    if (tag)
3855
0
        mcp->tag = strdup(tag);
3856
0
    mcp->tag_len = len;
3857
3858
0
    mcp->next = module_map_head;
3859
0
    module_map_head = mcp;
3860
0
}
3861
#endif /* NETSNMP_FEATURE_REMOVE_PARSE_ADD_MODULE_REPLACEMENT */
3862
3863
static int
3864
read_module_replacements(const char *name)
3865
210k
{
3866
210k
    struct module_compatability *mcp;
3867
3868
4.50M
    for (mcp = module_map_head; mcp; mcp = mcp->next) {
3869
4.30M
        if (!label_compare(mcp->old_module, name)) {
3870
20.3k
            if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3871
20.3k
           NETSNMP_DS_LIB_MIB_WARNINGS)) {
3872
0
                snmp_log(LOG_WARNING,
3873
0
                         "Loading replacement module %s for %s (%s)\n",
3874
0
                         mcp->new_module, name, File);
3875
0
      }
3876
20.3k
            (void) netsnmp_read_module(mcp->new_module);
3877
20.3k
            return 1;
3878
20.3k
        }
3879
4.30M
    }
3880
190k
    return 0;
3881
210k
}
3882
3883
static int
3884
read_import_replacements(const char *old_module_name,
3885
                         struct module_import *identifier)
3886
28.1k
{
3887
28.1k
    struct module_compatability *mcp;
3888
3889
    /*
3890
     * Look for matches first
3891
     */
3892
624k
    for (mcp = module_map_head; mcp; mcp = mcp->next) {
3893
599k
        if (!label_compare(mcp->old_module, old_module_name)) {
3894
3895
172k
            if (                /* exact match */
3896
172k
                   (mcp->tag_len == 0 &&
3897
40.0k
                    (mcp->tag == NULL ||
3898
38.3k
                     !label_compare(mcp->tag, identifier->label))) ||
3899
                   /*
3900
                    * prefix match 
3901
                    */
3902
170k
                   (mcp->tag_len != 0 &&
3903
132k
                    !strncmp(mcp->tag, identifier->label, mcp->tag_len))
3904
172k
                ) {
3905
3906
2.87k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3907
2.87k
               NETSNMP_DS_LIB_MIB_WARNINGS)) {
3908
0
                    snmp_log(LOG_WARNING,
3909
0
                             "Importing %s from replacement module %s instead of %s (%s)\n",
3910
0
                             identifier->label, mcp->new_module,
3911
0
                             old_module_name, File);
3912
0
    }
3913
2.87k
                (void) netsnmp_read_module(mcp->new_module);
3914
2.87k
                identifier->modid = which_module(mcp->new_module);
3915
2.87k
                return 1;         /* finished! */
3916
2.87k
            }
3917
172k
        }
3918
599k
    }
3919
3920
    /*
3921
     * If no exact match, load everything relevant
3922
     */
3923
25.2k
    return read_module_replacements(old_module_name);
3924
28.1k
}
3925
3926
static int
3927
read_from_file(struct module *mp, const char *name)
3928
15.3k
{
3929
15.3k
    const char     *oldFile = File;
3930
15.3k
    int             oldLine = mibLine;
3931
15.3k
    int             oldModule = current_module;
3932
15.3k
    FILE           *fp;
3933
15.3k
    struct node    *np;
3934
15.3k
    int             res;
3935
3936
15.3k
    if (mp->no_imports != -1) {
3937
4.57k
        DEBUGMSGTL(("parse-mibs", "Module %s already loaded\n",
3938
4.57k
                    name));
3939
4.57k
        return MODULE_ALREADY_LOADED;
3940
4.57k
    }
3941
10.7k
    if ((fp = fopen(mp->file, "r")) == NULL) {
3942
0
        int rval;
3943
0
        if (errno == ENOTDIR || errno == ENOENT)
3944
0
            rval = MODULE_NOT_FOUND;
3945
0
        else
3946
0
            rval = MODULE_LOAD_FAILED;
3947
0
        snmp_log_perror(mp->file);
3948
0
        return rval;
3949
0
    }
3950
10.7k
#ifdef HAVE_FLOCKFILE
3951
10.7k
    flockfile(fp);
3952
10.7k
#endif
3953
10.7k
    mp->no_imports = 0; /* Note that we've read the file */
3954
10.7k
    File = mp->file;
3955
10.7k
    mibLine = 1;
3956
10.7k
    current_module = mp->modid;
3957
    /*
3958
     * Parse the file
3959
     */
3960
10.7k
    np = parse(fp);
3961
10.7k
#ifdef HAVE_FUNLOCKFILE
3962
10.7k
    funlockfile(fp);
3963
10.7k
#endif
3964
10.7k
    fclose(fp);
3965
10.7k
    File = oldFile;
3966
10.7k
    mibLine = oldLine;
3967
10.7k
    current_module = oldModule;
3968
10.7k
    res = !np && gMibError == MODULE_SYNTAX_ERROR ?
3969
5.63k
        MODULE_SYNTAX_ERROR : MODULE_LOADED_OK;
3970
17.2k
    while (np) {
3971
6.46k
        struct node *nnp = np->next;
3972
6.46k
        free_node(np);
3973
6.46k
        np = nnp;
3974
6.46k
    }
3975
10.7k
    return res;
3976
10.7k
}
3977
3978
/*
3979
 *  Read in the named module
3980
 *      Returns the root of the whole tree
3981
 *      (by analogy with 'read_mib')
3982
 */
3983
static int
3984
read_module_internal(const char *name)
3985
203k
{
3986
203k
    struct module  *mp;
3987
3988
203k
    netsnmp_init_mib_internals();
3989
3990
172M
    for (mp = module_head; mp; mp = mp->next)
3991
171M
        if (!label_compare(mp->name, name))
3992
15.3k
            return read_from_file(mp, name);
3993
3994
187k
    return MODULE_NOT_FOUND;
3995
203k
}
3996
3997
void
3998
adopt_orphans(void)
3999
3.48k
{
4000
3.48k
    struct node    *np = NULL, *onp;
4001
3.48k
    struct tree    *tp;
4002
3.48k
    int             i, adopted = 1;
4003
4004
3.48k
    if (!orphan_nodes)
4005
95
        return;
4006
3.38k
    init_node_hash(orphan_nodes);
4007
3.38k
    orphan_nodes = NULL;
4008
4009
7.01k
    while (adopted) {
4010
3.62k
        adopted = 0;
4011
467k
        for (i = 0; i < NHASHSIZE; i++)
4012
464k
            if (nbuckets[i]) {
4013
204k
                for (np = nbuckets[i]; np != NULL; np = np->next) {
4014
130k
                    tp = find_tree_node(np->parent, -1);
4015
130k
        if (tp) {
4016
338
      do_subtree(tp, &np);
4017
338
      adopted = 1;
4018
                        /*
4019
                         * if do_subtree adopted the entire bucket, stop
4020
                         */
4021
338
                        if(NULL == nbuckets[i])
4022
304
                            break;
4023
4024
                        /*
4025
                         * do_subtree may modify nbuckets, and if np
4026
                         * was adopted, np->next probably isn't an orphan
4027
                         * anymore. if np is still in the bucket (do_subtree
4028
                         * didn't adopt it) keep on plugging. otherwise
4029
                         * start over, at the top of the bucket.
4030
                         */
4031
117
                        for(onp = nbuckets[i]; onp; onp = onp->next)
4032
83
                            if(onp == np)
4033
0
                                break;
4034
34
                        if(NULL == onp) { /* not in the list */
4035
34
                            np = nbuckets[i]; /* start over */
4036
34
                        }
4037
34
        }
4038
130k
    }
4039
74.2k
            }
4040
3.62k
    }
4041
4042
    /*
4043
     * Report on outstanding orphans
4044
     *    and link them back into the orphan list
4045
     */
4046
436k
    for (i = 0; i < NHASHSIZE; i++)
4047
433k
        if (nbuckets[i]) {
4048
68.7k
            if (orphan_nodes)
4049
65.3k
                onp = np->next = nbuckets[i];
4050
3.38k
            else
4051
3.38k
                onp = orphan_nodes = nbuckets[i];
4052
68.7k
            nbuckets[i] = NULL;
4053
189k
            while (onp) {
4054
121k
                char            modbuf[256];
4055
121k
                snmp_log(LOG_WARNING,
4056
121k
                         "Cannot resolve OID in %s: %s ::= { %s %ld } at line %d in %s\n",
4057
121k
                         module_name(onp->modid, modbuf),
4058
121k
                         (onp->label ? onp->label : "<no label>"),
4059
121k
                         (onp->parent ? onp->parent : "<no parent>"),
4060
121k
                         onp->subid, onp->lineno, onp->filename);
4061
121k
                np = onp;
4062
121k
                onp = onp->next;
4063
121k
            }
4064
68.7k
        }
4065
3.38k
}
4066
4067
#ifndef NETSNMP_NO_LEGACY_DEFINITIONS
4068
struct tree    *
4069
read_module(const char *name)
4070
0
{
4071
0
    return netsnmp_read_module(name);
4072
0
}
4073
#endif
4074
4075
struct tree    *
4076
netsnmp_read_module(const char *name)
4077
198k
{
4078
198k
    int status = 0;
4079
198k
    status = read_module_internal(name);
4080
4081
198k
    if (status == MODULE_NOT_FOUND) {
4082
185k
        if (!read_module_replacements(name))
4083
183k
            print_module_not_found(name);
4084
185k
    } else if (status == MODULE_SYNTAX_ERROR) {
4085
5.13k
        gMibError = 0;
4086
5.13k
        gLoop = 1;
4087
4088
5.13k
        strncat(gMibNames, " ", sizeof(gMibNames) - strlen(gMibNames) - 1);
4089
5.13k
        strncat(gMibNames, name, sizeof(gMibNames) - strlen(gMibNames) - 1);
4090
5.13k
    }
4091
4092
198k
    return tree_head;
4093
198k
}
4094
4095
/*
4096
 * Prototype definition 
4097
 */
4098
void            unload_module_by_ID(int modID, struct tree *tree_top);
4099
4100
void
4101
unload_module_by_ID(int modID, struct tree *tree_top)
4102
14.1k
{
4103
14.1k
    struct tree    *tp, *next;
4104
14.1k
    int             i;
4105
4106
45.8k
    for (tp = tree_top; tp; tp = next) {
4107
        /*
4108
         * Essentially, this is equivalent to the code fragment:
4109
         *      if (tp->modID == modID)
4110
         *        tp->number_modules--;
4111
         * but handles one tree node being part of several modules,
4112
         * and possible multiple copies of the same module ID.
4113
         */
4114
31.6k
        int             nmod = tp->number_modules;
4115
31.6k
        if (nmod > 0) {         /* in some module */
4116
            /*
4117
             * Remove all copies of this module ID
4118
             */
4119
31.6k
            int             cnt = 0, *pi1, *pi2 = tp->module_list;
4120
64.6k
            for (i = 0, pi1 = pi2; i < nmod; i++, pi2++) {
4121
33.0k
                if (*pi2 == modID)
4122
23.3k
                    continue;
4123
9.66k
                cnt++;
4124
9.66k
                *pi1++ = *pi2;
4125
9.66k
            }
4126
31.6k
            if (nmod != cnt) {  /* in this module */
4127
                /*
4128
                 * if ( (nmod - cnt) > 1)
4129
                 * printf("Dup modid %d,  %d times, '%s'\n", tp->modid, (nmod-cnt), tp->label); fflush(stdout); ?* XXDEBUG 
4130
                 */
4131
22.2k
                tp->number_modules = cnt;
4132
22.2k
                switch (cnt) {
4133
22.2k
                case 0:
4134
22.2k
                    tp->module_list[0] = -1;    /* Mark unused, */
4135
22.2k
        NETSNMP_FALLTHROUGH;
4136
4137
22.2k
                case 1:        /* save the remaining module */
4138
22.2k
                    if (&(tp->modid) != tp->module_list) {
4139
728
                        tp->modid = tp->module_list[0];
4140
728
                        free(tp->module_list);
4141
728
                        tp->module_list = &(tp->modid);
4142
728
                    }
4143
22.2k
                    break;
4144
4145
0
                default:
4146
0
                    break;
4147
22.2k
                }
4148
22.2k
            }                   /* if tree node is in this module */
4149
31.6k
        }
4150
        /*
4151
         * if tree node is in some module 
4152
         */
4153
31.6k
        next = tp->next_peer;
4154
4155
4156
        /*
4157
         *  OK - that's dealt with *this* node.
4158
         *    Now let's look at the children.
4159
         *    (Isn't recursion wonderful!)
4160
         */
4161
31.6k
        if (tp->child_list)
4162
7.98k
            unload_module_by_ID(modID, tp->child_list);
4163
4164
4165
31.6k
        if (tp->number_modules == 0) {
4166
            /*
4167
             * This node isn't needed any more (except perhaps
4168
             * for the sake of the children) 
4169
             */
4170
22.2k
            if (tp->child_list == NULL) {
4171
22.2k
                unlink_tree(tp);
4172
22.2k
                free_tree(tp);
4173
22.2k
            } else {
4174
10
                free_partial_tree(tp, TRUE);
4175
10
            }
4176
22.2k
        }
4177
31.6k
    }
4178
14.1k
}
4179
4180
#ifndef NETSNMP_NO_LEGACY_DEFINITIONS
4181
int
4182
unload_module(const char *name)
4183
0
{
4184
0
    return netsnmp_unload_module(name);
4185
0
}
4186
#endif
4187
4188
int
4189
netsnmp_unload_module(const char *name)
4190
0
{
4191
0
    struct module  *mp;
4192
0
    int             modID = -1;
4193
4194
0
    for (mp = module_head; mp; mp = mp->next)
4195
0
        if (!label_compare(mp->name, name)) {
4196
0
            modID = mp->modid;
4197
0
            break;
4198
0
        }
4199
4200
0
    if (modID == -1) {
4201
0
        DEBUGMSGTL(("unload-mib", "Module %s not found to unload\n",
4202
0
                    name));
4203
0
        return MODULE_NOT_FOUND;
4204
0
    }
4205
0
    unload_module_by_ID(modID, tree_head);
4206
0
    mp->no_imports = -1;        /* mark as unloaded */
4207
0
    return MODULE_LOADED_OK;    /* Well, you know what I mean! */
4208
0
}
4209
4210
/*
4211
 * Clear module map, tree nodes, textual convention table.
4212
 */
4213
void
4214
unload_all_mibs(void)
4215
3.47k
{
4216
3.47k
    struct module  *mp;
4217
3.47k
    struct module_compatability *mcp;
4218
3.47k
    struct tc      *ptc;
4219
3.47k
    unsigned int    i;
4220
4221
3.47k
    for (mcp = module_map_head; mcp; mcp = module_map_head) {
4222
3.47k
        if (mcp == module_map)
4223
3.47k
            break;
4224
0
        module_map_head = mcp->next;
4225
0
        if (mcp->tag) free(NETSNMP_REMOVE_CONST(char *, mcp->tag));
4226
0
        free(NETSNMP_REMOVE_CONST(char *, mcp->old_module));
4227
0
        free(NETSNMP_REMOVE_CONST(char *, mcp->new_module));
4228
0
        free(mcp);
4229
0
    }
4230
4231
6.20k
    for (mp = module_head; mp; mp = module_head) {
4232
2.73k
        struct module_import *mi = mp->imports;
4233
2.73k
        if (mi) {
4234
7.65k
            for (i = 0; i < (unsigned int)mp->no_imports; ++i) {
4235
6.26k
                SNMP_FREE((mi + i)->label);
4236
6.26k
            }
4237
1.38k
            mp->no_imports = 0;
4238
1.38k
            if (mi == root_imports)
4239
1.00k
                memset(mi, 0, sizeof(*mi));
4240
379
            else
4241
379
                free(mi);
4242
1.38k
        }
4243
4244
2.73k
        unload_module_by_ID(mp->modid, tree_head);
4245
2.73k
        module_head = mp->next;
4246
2.73k
        free(mp->name);
4247
2.73k
        free(mp->file);
4248
2.73k
        free(mp);
4249
2.73k
    }
4250
3.47k
    unload_module_by_ID(-1, tree_head);
4251
    /*
4252
     * tree nodes are cleared 
4253
     */
4254
4255
351k
    for (i = 0, ptc = tclist; i < tc_alloc; i++, ptc++) {
4256
347k
        if (ptc->type == 0)
4257
347k
            continue;
4258
380
        free_enums(&ptc->enums);
4259
380
        free_ranges(&ptc->ranges);
4260
380
        free(ptc->descriptor);
4261
380
        if (ptc->hint)
4262
0
            free(ptc->hint);
4263
380
        if (ptc->description)
4264
0
            free(ptc->description);
4265
380
    }
4266
3.47k
    SNMP_FREE(tclist);
4267
3.47k
    tc_alloc = 0;
4268
4269
3.47k
    memset(buckets, 0, sizeof(buckets));
4270
3.47k
    memset(nbuckets, 0, sizeof(nbuckets));
4271
3.47k
    memset(tbuckets, 0, sizeof(tbuckets));
4272
4273
13.9k
    for (i = 0; i < sizeof(root_imports) / sizeof(root_imports[0]); i++) {
4274
10.4k
        SNMP_FREE(root_imports[i].label);
4275
10.4k
    }
4276
4277
3.47k
    max_module = 0;
4278
3.47k
    current_module = 0;
4279
3.47k
    module_map_head = NULL;
4280
3.47k
    SNMP_FREE(last_err_module);
4281
3.47k
}
4282
4283
static void
4284
new_module(const char *name, const char *file)
4285
15.7k
{
4286
15.7k
    struct module  *mp;
4287
4288
29.1M
    for (mp = module_head; mp; mp = mp->next)
4289
29.1M
        if (!label_compare(mp->name, name)) {
4290
4.65k
            DEBUGMSGTL(("parse-mibs", "  Module %s already noted\n", name));
4291
            /*
4292
             * Not the same file 
4293
             */
4294
4.65k
            if (label_compare(mp->file, file)) {
4295
2.80k
                DEBUGMSGTL(("parse-mibs", "    %s is now in %s\n",
4296
2.80k
                            name, file));
4297
2.80k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
4298
2.80k
               NETSNMP_DS_LIB_MIB_WARNINGS)) {
4299
4
                    snmp_log(LOG_WARNING,
4300
4
                             "Warning: Module %s was in %s now is %s\n",
4301
4
                             name, mp->file, file);
4302
4
    }
4303
4304
                /*
4305
                 * Use the new one in preference 
4306
                 */
4307
2.80k
                free(mp->file);
4308
2.80k
                mp->file = strdup(file);
4309
2.80k
            }
4310
4.65k
            return;
4311
4.65k
        }
4312
4313
    /*
4314
     * Add this module to the list 
4315
     */
4316
11.0k
    DEBUGMSGTL(("parse-mibs", "  Module %d %s is in %s\n", max_module,
4317
11.0k
                name, file));
4318
11.0k
    mp = calloc(1, sizeof(struct module));
4319
11.0k
    if (mp == NULL)
4320
0
        return;
4321
11.0k
    mp->name = strdup(name);
4322
11.0k
    mp->file = strdup(file);
4323
11.0k
    if (mp->name == NULL || mp->file == NULL) {
4324
0
        free(mp->name);
4325
0
        free(mp->file);
4326
0
        free(mp);
4327
0
        return;
4328
0
    }
4329
11.0k
    mp->imports = NULL;
4330
11.0k
    mp->no_imports = -1;        /* Not yet loaded */
4331
11.0k
    mp->modid = max_module;
4332
11.0k
    ++max_module;
4333
4334
11.0k
    mp->next = module_head;     /* Or add to the *end* of the list? */
4335
11.0k
    module_head = mp;
4336
11.0k
}
4337
4338
4339
static void
4340
scan_objlist(struct node *root, struct module *mp, struct objgroup *list, const char *error)
4341
32.4k
{
4342
32.4k
    int             oLine = mibLine;
4343
4344
34.0k
    while (list) {
4345
1.57k
        struct objgroup *gp = list;
4346
1.57k
        struct node    *np;
4347
1.57k
        list = list->next;
4348
1.57k
        np = root;
4349
19.4k
        while (np)
4350
18.2k
            if (label_compare(np->label, gp->name))
4351
17.9k
                np = np->next;
4352
317
            else
4353
317
                break;
4354
1.57k
        if (!np) {
4355
1.26k
      int i;
4356
1.26k
      struct module_import *mip;
4357
      /* if not local, check if it was IMPORTed */
4358
56.1k
      for (i = 0, mip = mp->imports; i < mp->no_imports; i++, mip++)
4359
55.2k
    if (strcmp(mip->label, gp->name) == 0)
4360
364
        break;
4361
1.26k
      if (i == mp->no_imports) {
4362
860
    mibLine = gp->line;
4363
860
    print_error(error, gp->name, QUOTESTRING);
4364
860
      }
4365
1.26k
        }
4366
1.57k
        free(gp->name);
4367
1.57k
        free(gp);
4368
1.57k
    }
4369
32.4k
    mibLine = oLine;
4370
32.4k
}
4371
4372
static void free_objgroup(struct objgroup *o)
4373
15.0k
{
4374
31.9k
    while (o) {
4375
16.8k
        struct objgroup *next = o->next;
4376
4377
16.8k
        free(o->name);
4378
16.8k
        free(o);
4379
16.8k
        o = next;
4380
16.8k
    }
4381
15.0k
}
4382
4383
/*
4384
 * Parses a mib file and returns a linked list of nodes found in the file.
4385
 * Returns NULL on error.
4386
 */
4387
static struct node *
4388
parse(FILE * fp)
4389
10.7k
{
4390
#ifdef TEST
4391
    extern void     xmalloc_stats(FILE *);
4392
#endif
4393
10.7k
    char            token[MAXTOKEN];
4394
10.7k
    char            name[MAXTOKEN+1];
4395
10.7k
    int             type = LABEL;
4396
10.7k
    int             lasttype = LABEL;
4397
4398
34.1k
#define BETWEEN_MIBS          1
4399
23.4k
#define IN_MIB                2
4400
10.7k
    int             state = BETWEEN_MIBS;
4401
10.7k
    struct node    *np = NULL, *root = NULL;
4402
10.7k
    struct objgroup *oldgroups = NULL, *oldobjects = NULL, *oldnotifs =
4403
10.7k
        NULL;
4404
4405
10.7k
    DEBUGMSGTL(("parse-file", "Parsing file:  %s...\n", File));
4406
4407
10.7k
    if (last_err_module)
4408
2.88k
        free(last_err_module);
4409
10.7k
    last_err_module = NULL;
4410
4411
147k
    while (type != ENDOFFILE) {
4412
141k
        struct node *nnp;
4413
4414
141k
        if (lasttype == CONTINUE)
4415
37.2k
            lasttype = type;
4416
104k
        else
4417
104k
            type = lasttype = get_token(fp, token, MAXTOKEN);
4418
4419
141k
        switch (type) {
4420
10.8k
        case END:
4421
10.8k
            if (state != IN_MIB) {
4422
18
                print_error("Error, END before start of MIB", NULL, type);
4423
18
                gMibError = MODULE_SYNTAX_ERROR;
4424
18
                goto free_mib;
4425
10.8k
            } else {
4426
10.8k
                struct module  *mp;
4427
#ifdef TEST
4428
                printf("\nNodes for Module %s:\n", name);
4429
                print_nodes(stdout, root);
4430
#endif
4431
51.2M
                for (mp = module_head; mp; mp = mp->next)
4432
51.2M
                    if (mp->modid == current_module)
4433
10.8k
                        break;
4434
10.8k
                scan_objlist(root, mp, objgroups, "Undefined OBJECT-GROUP");
4435
10.8k
                scan_objlist(root, mp, objects, "Undefined OBJECT");
4436
10.8k
                scan_objlist(root, mp, notifs, "Undefined NOTIFICATION");
4437
10.8k
                objgroups = oldgroups;
4438
10.8k
                objects = oldobjects;
4439
10.8k
                notifs = oldnotifs;
4440
10.8k
                do_linkup(mp, root);
4441
10.8k
                np = root = NULL;
4442
10.8k
            }
4443
10.8k
            state = BETWEEN_MIBS;
4444
#ifdef TEST
4445
            if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
4446
           NETSNMP_DS_LIB_MIB_WARNINGS)) {
4447
                /* xmalloc_stats(stderr); */
4448
      }
4449
#endif
4450
10.8k
            continue;
4451
3.42k
        case IMPORTS:
4452
3.42k
            parse_imports(fp);
4453
3.42k
            continue;
4454
235
        case EXPORTS:
4455
1.88k
            while (type != SEMI && type != ENDOFFILE)
4456
1.64k
                type = get_token(fp, token, MAXTOKEN);
4457
235
            continue;
4458
90.7k
        case LABEL:
4459
90.8k
        case INTEGER:
4460
91.2k
        case INTEGER32:
4461
91.4k
        case UINTEGER32:
4462
91.4k
        case UNSIGNED32:
4463
92.0k
        case COUNTER:
4464
92.1k
        case COUNTER64:
4465
92.4k
        case GAUGE:
4466
92.8k
        case IPADDR:
4467
92.9k
        case NETADDR:
4468
93.1k
        case NSAPADDRESS:
4469
93.7k
        case OBJSYNTAX:
4470
93.9k
        case APPSYNTAX:
4471
94.1k
        case SIMPLESYNTAX:
4472
94.1k
        case OBJNAME:
4473
94.4k
        case NOTIFNAME:
4474
94.8k
        case KW_OPAQUE:
4475
95.1k
        case TIMETICKS:
4476
95.1k
            break;
4477
2.94k
        case ENDOFFILE:
4478
2.94k
            continue;
4479
28.8k
        default:
4480
28.8k
            strlcpy(name, token, sizeof(name));
4481
28.8k
            type = get_token(fp, token, MAXTOKEN);
4482
28.8k
            nnp = NULL;
4483
28.8k
            if (type == MACRO) {
4484
670
                nnp = parse_macro(fp, name);
4485
670
                if (nnp == NULL) {
4486
25
                    print_error("Bad parse of MACRO", NULL, type);
4487
25
                    gMibError = MODULE_SYNTAX_ERROR;
4488
25
                }
4489
670
                free_node(nnp); /* IGNORE */
4490
670
                nnp = NULL;
4491
670
            } else
4492
28.1k
                print_error(name, "is a reserved word", lasttype);
4493
28.8k
            continue;           /* see if we can parse the rest of the file */
4494
141k
        }
4495
95.1k
        strlcpy(name, token, sizeof(name));
4496
95.1k
        type = get_token(fp, token, MAXTOKEN);
4497
95.1k
        nnp = NULL;
4498
4499
        /*
4500
         * Handle obsolete method to assign an object identifier to a
4501
         * module
4502
         */
4503
95.1k
        if (lasttype == LABEL && type == LEFTBRACKET) {
4504
4.18M
            while (type != RIGHTBRACKET && type != ENDOFFILE)
4505
4.18M
                type = get_token(fp, token, MAXTOKEN);
4506
3.69k
            if (type == ENDOFFILE) {
4507
525
                print_error("Expected \"}\"", token, type);
4508
525
                gMibError = MODULE_SYNTAX_ERROR;
4509
525
                goto free_mib;
4510
525
            }
4511
3.16k
            type = get_token(fp, token, MAXTOKEN);
4512
3.16k
        }
4513
4514
94.5k
        switch (type) {
4515
12.6k
        case DEFINITIONS:
4516
12.6k
            if (state != BETWEEN_MIBS) {
4517
7
                print_error("Error, nested MIBS", NULL, type);
4518
7
                gMibError = MODULE_SYNTAX_ERROR;
4519
7
                goto free_mib;
4520
7
            }
4521
12.6k
            state = IN_MIB;
4522
12.6k
            current_module = which_module(name);
4523
12.6k
            oldgroups = objgroups;
4524
12.6k
            objgroups = NULL;
4525
12.6k
            oldobjects = objects;
4526
12.6k
            objects = NULL;
4527
12.6k
            oldnotifs = notifs;
4528
12.6k
            notifs = NULL;
4529
12.6k
            if (current_module == -1) {
4530
304
                new_module(name, File);
4531
304
                current_module = which_module(name);
4532
304
            }
4533
12.6k
            DEBUGMSGTL(("parse-mibs", "Parsing MIB: %d %s\n",
4534
12.6k
                        current_module, name));
4535
283k
            while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE)
4536
282k
                if (type == BEGIN)
4537
12.2k
                    break;
4538
12.6k
            break;
4539
13.6k
        case OBJTYPE:
4540
13.6k
            nnp = parse_objecttype(fp, name);
4541
13.6k
            if (nnp == NULL) {
4542
645
                print_error("Bad parse of OBJECT-TYPE", NULL, type);
4543
645
                gMibError = MODULE_SYNTAX_ERROR;
4544
645
                goto free_mib;
4545
645
            }
4546
13.0k
            break;
4547
13.0k
        case OBJGROUP:
4548
2.61k
            nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
4549
2.61k
            if (nnp == NULL) {
4550
77
                print_error("Bad parse of OBJECT-GROUP", NULL, type);
4551
77
                gMibError = MODULE_SYNTAX_ERROR;
4552
77
                goto free_mib;
4553
77
            }
4554
2.53k
            break;
4555
2.53k
        case NOTIFGROUP:
4556
300
            nnp = parse_objectgroup(fp, name, NOTIFICATIONS, &notifs);
4557
300
            if (nnp == NULL) {
4558
42
                print_error("Bad parse of NOTIFICATION-GROUP", NULL, type);
4559
42
                gMibError = MODULE_SYNTAX_ERROR;
4560
42
                goto free_mib;
4561
42
            }
4562
258
            break;
4563
530
        case TRAPTYPE:
4564
530
            nnp = parse_trapDefinition(fp, name);
4565
530
            if (nnp == NULL) {
4566
186
                print_error("Bad parse of TRAP-TYPE", NULL, type);
4567
186
                gMibError = MODULE_SYNTAX_ERROR;
4568
186
                goto free_mib;
4569
186
            }
4570
344
            break;
4571
1.23k
        case NOTIFTYPE:
4572
1.23k
            nnp = parse_notificationDefinition(fp, name);
4573
1.23k
            if (nnp == NULL) {
4574
134
                print_error("Bad parse of NOTIFICATION-TYPE", NULL, type);
4575
134
                gMibError = MODULE_SYNTAX_ERROR;
4576
134
                goto free_mib;
4577
134
            }
4578
1.10k
            break;
4579
10.4k
        case COMPLIANCE:
4580
10.4k
            nnp = parse_compliance(fp, name);
4581
10.4k
            if (nnp == NULL) {
4582
716
                print_error("Bad parse of MODULE-COMPLIANCE", NULL, type);
4583
716
                gMibError = MODULE_SYNTAX_ERROR;
4584
716
                goto free_mib;
4585
716
            }
4586
9.77k
            break;
4587
9.77k
        case AGENTCAP:
4588
3.96k
            nnp = parse_capabilities(fp, name);
4589
3.96k
            if (nnp == NULL) {
4590
285
                print_error("Bad parse of AGENT-CAPABILITIES", NULL, type);
4591
285
                gMibError = MODULE_SYNTAX_ERROR;
4592
285
                goto free_mib;
4593
285
            }
4594
3.68k
            break;
4595
3.68k
        case MACRO:
4596
281
            nnp = parse_macro(fp, name);
4597
281
            if (nnp == NULL) {
4598
78
                print_error("Bad parse of MACRO", NULL, type);
4599
78
                gMibError = MODULE_SYNTAX_ERROR;
4600
78
            }
4601
281
            free_node(nnp);     /* IGNORE */
4602
281
            nnp = NULL;
4603
281
            break;
4604
5.91k
        case MODULEIDENTITY:
4605
5.91k
            nnp = parse_moduleIdentity(fp, name);
4606
5.91k
            if (nnp == NULL) {
4607
367
                print_error("Bad parse of MODULE-IDENTITY", NULL, type);
4608
367
                gMibError = MODULE_SYNTAX_ERROR;
4609
367
                goto free_mib;
4610
367
            }
4611
5.54k
            break;
4612
5.54k
        case OBJIDENTITY:
4613
965
            nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
4614
965
            if (nnp == NULL) {
4615
79
                print_error("Bad parse of OBJECT-IDENTITY", NULL, type);
4616
79
                gMibError = MODULE_SYNTAX_ERROR;
4617
79
                goto free_mib;
4618
79
            }
4619
886
            break;
4620
1.22k
        case OBJECT:
4621
1.22k
            type = get_token(fp, token, MAXTOKEN);
4622
1.22k
            if (type != IDENTIFIER) {
4623
26
                print_error("Expected IDENTIFIER", token, type);
4624
26
                gMibError = MODULE_SYNTAX_ERROR;
4625
26
                goto free_mib;
4626
26
            }
4627
1.20k
            type = get_token(fp, token, MAXTOKEN);
4628
1.20k
            if (type != EQUALS) {
4629
9
                print_error("Expected \"::=\"", token, type);
4630
9
                gMibError = MODULE_SYNTAX_ERROR;
4631
9
                goto free_mib;
4632
9
            }
4633
1.19k
            nnp = parse_objectid(fp, name);
4634
1.19k
            if (nnp == NULL) {
4635
4
                print_error("Bad parse of OBJECT IDENTIFIER", NULL, type);
4636
4
                gMibError = MODULE_SYNTAX_ERROR;
4637
4
                goto free_mib;
4638
4
            }
4639
1.18k
            break;
4640
37.6k
        case EQUALS:
4641
37.6k
            nnp = parse_asntype(fp, name, &type, token);
4642
37.6k
            lasttype = CONTINUE;
4643
37.6k
            break;
4644
1.22k
        case ENDOFFILE:
4645
1.22k
            break;
4646
1.91k
        default:
4647
1.91k
            print_error("Bad operator", token, type);
4648
1.91k
            gMibError = MODULE_SYNTAX_ERROR;
4649
1.91k
            goto free_mib;
4650
94.5k
        }
4651
90.1k
        if (nnp) {
4652
53.6k
            struct node *op;
4653
53.6k
            if (np)
4654
41.9k
                np->next = nnp;
4655
11.7k
            else
4656
11.7k
                np = root = nnp;
4657
336k
            while (np->next)
4658
282k
                np = np->next;
4659
53.6k
            if (np->type == TYPE_OTHER)
4660
40.6k
                np->type = type;
4661
53.6k
            op = root;
4662
9.80M
            while (op != nnp) {
4663
9.75M
                if (strcmp(nnp->label, op->label) == 0 && nnp->subid != op->subid) {
4664
89.3k
                    snmp_log(LOG_ERR, 
4665
89.3k
                        "Duplicate Object '%s' at line %d in %s. First at line %d\n",
4666
89.3k
                        op->label, mibLine, File, op->lineno);
4667
89.3k
        erroneousMibs++;
4668
89.3k
    }
4669
9.75M
                op = op->next;
4670
9.75M
            }
4671
53.6k
        }
4672
90.1k
    }
4673
5.73k
    DEBUGMSGTL(("parse-file", "End of file (%s)\n", File));
4674
5.73k
    return root;
4675
4676
5.03k
free_mib:
4677
101k
    for (; root; root = np) {
4678
96.8k
        np = root->next;
4679
96.8k
        free_node(root);
4680
96.8k
    }
4681
5.03k
    free_objgroup(objgroups);
4682
5.03k
    objgroups = NULL;
4683
5.03k
    free_objgroup(objects);
4684
5.03k
    objects = NULL;
4685
5.03k
    free_objgroup(notifs);
4686
5.03k
    notifs = NULL;
4687
5.03k
    return NULL;
4688
10.7k
}
4689
4690
/*
4691
 * return zero if character is not a label character. 
4692
 */
4693
static int
4694
is_labelchar(int ich)
4695
17.6M
{
4696
17.6M
    netsnmp_assert(ich == EOF || (0 <= ich && ich < 256));
4697
17.6M
    if ((isalnum(ich)) || (ich == '-'))
4698
11.0M
        return 1;
4699
6.61M
    if (ich == '_' && netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
4700
8.96k
               NETSNMP_DS_LIB_MIB_PARSE_LABEL)) {
4701
0
        return 1;
4702
0
    }
4703
4704
6.61M
    return 0;
4705
6.61M
}
4706
4707
/**
4708
 * Read a single character from a file. Assumes that the caller has invoked
4709
 * flockfile(). Uses fgetc_unlocked() instead of getc() since the former is
4710
 * implemented as an inline function in glibc. See also bug 3447196
4711
 * (http://sourceforge.net/tracker/?func=detail&aid=3447196&group_id=12694&atid=112694).
4712
 */
4713
static int netsnmp_getc(FILE *stream)
4714
51.7M
{
4715
51.7M
#ifdef HAVE_FGETC_UNLOCKED
4716
51.7M
    return fgetc_unlocked(stream);
4717
#else
4718
    return getc(stream);
4719
#endif
4720
51.7M
}
4721
4722
/*
4723
 * Parses a token from the file.  The type of the token parsed is returned,
4724
 * and the text is placed in the string pointed to by token.
4725
 * Warning: this method may recurse.
4726
 */
4727
static int
4728
get_token(FILE *const fp, char *const token, const int maxtlen)
4729
10.2M
{
4730
10.2M
    int             ch, ch_next;
4731
10.2M
    char           *cp;
4732
10.2M
    int             hash;
4733
10.2M
    struct tok     *tp;
4734
10.2M
    int             too_long;
4735
10.2M
    enum { bdigits, xdigits, other } seenSymbols;
4736
4737
10.9M
fetch_next_token:
4738
10.9M
    cp = token;
4739
10.9M
    hash = 0;
4740
10.9M
    too_long = 0;
4741
    /*
4742
     * skip all white space 
4743
     */
4744
14.4M
    do {
4745
14.4M
        ch = netsnmp_getc(fp);
4746
14.4M
        if (ch == '\n')
4747
359k
            mibLine++;
4748
14.4M
    }
4749
14.4M
    while (isspace(ch) && ch != EOF);
4750
10.9M
    *cp++ = ch;
4751
10.9M
    *cp = '\0';
4752
10.9M
    switch (ch) {
4753
11.6k
    case EOF:
4754
11.6k
        return ENDOFFILE;
4755
183k
    case '"':
4756
183k
        return parseQuoteString(fp, token, maxtlen);
4757
274k
    case '\'':                 /* binary or hex constant */
4758
274k
        seenSymbols = bdigits;
4759
7.29M
        while ((ch = netsnmp_getc(fp)) != EOF && ch != '\'') {
4760
7.01M
            switch (seenSymbols) {
4761
39.0k
            case bdigits:
4762
39.0k
                if (ch == '0' || ch == '1')
4763
5.47k
                    break;
4764
33.5k
                seenSymbols = xdigits;
4765
33.5k
                NETSNMP_FALLTHROUGH;
4766
46.1k
            case xdigits:
4767
46.1k
                if (isxdigit(ch))
4768
13.6k
                    break;
4769
32.5k
                seenSymbols = other;
4770
32.5k
                NETSNMP_FALLTHROUGH;
4771
6.99M
            case other:
4772
6.99M
                break;
4773
7.01M
            }
4774
7.01M
            if (cp - token < maxtlen - 2)
4775
2.12M
                *cp++ = ch;
4776
7.01M
        }
4777
274k
        if (ch == '\'') {
4778
273k
            unsigned long   val = 0;
4779
273k
            char           *run = token + 1;
4780
273k
            ch = netsnmp_getc(fp);
4781
273k
            switch (ch) {
4782
33
            case EOF:
4783
33
                return ENDOFFILE;
4784
875
            case 'b':
4785
1.59k
            case 'B':
4786
1.59k
                if (seenSymbols > bdigits) {
4787
1.00k
                    *cp++ = '\'';
4788
1.00k
                    *cp = 0;
4789
1.00k
                    return LABEL;
4790
1.00k
                }
4791
1.84k
                while (run != cp)
4792
1.26k
                    val = val * 2 + *run++ - '0';
4793
585
                break;
4794
1.66k
            case 'h':
4795
3.45k
            case 'H':
4796
3.45k
                if (seenSymbols > xdigits) {
4797
2.13k
                    *cp++ = '\'';
4798
2.13k
                    *cp = 0;
4799
2.13k
                    return LABEL;
4800
2.13k
                }
4801
5.32k
                while (run != cp) {
4802
4.01k
                    ch = *run++;
4803
4.01k
                    if ('0' <= ch && ch <= '9')
4804
629
                        val = val * 16 + ch - '0';
4805
3.38k
                    else if ('a' <= ch && ch <= 'f')
4806
1.72k
                        val = val * 16 + ch - 'a' + 10;
4807
1.66k
                    else if ('A' <= ch && ch <= 'F')
4808
1.66k
                        val = val * 16 + ch - 'A' + 10;
4809
4.01k
                }
4810
1.31k
                break;
4811
267k
            default:
4812
267k
                *cp++ = '\'';
4813
267k
                *cp = 0;
4814
267k
                return LABEL;
4815
273k
            }
4816
1.89k
            sprintf(token, "%ld", val);
4817
1.89k
            return NUMBER;
4818
273k
        } else
4819
1.34k
            return LABEL;
4820
32.8k
    case '(':
4821
32.8k
        return LEFTPAREN;
4822
29.5k
    case ')':
4823
29.5k
        return RIGHTPAREN;
4824
1.08M
    case '{':
4825
1.08M
        return LEFTBRACKET;
4826
1.32M
    case '}':
4827
1.32M
        return RIGHTBRACKET;
4828
9.84k
    case '[':
4829
9.84k
        return LEFTSQBRACK;
4830
13.5k
    case ']':
4831
13.5k
        return RIGHTSQBRACK;
4832
12.8k
    case ';':
4833
12.8k
        return SEMI;
4834
27.1k
    case ',':
4835
27.1k
        return COMMA;
4836
14.6k
    case '|':
4837
14.6k
        return BAR;
4838
214k
    case '.':
4839
214k
        ch_next = netsnmp_getc(fp);
4840
214k
        if (ch_next == '.')
4841
204k
            return RANGE;
4842
10.4k
        ungetc(ch_next, fp);
4843
10.4k
        return LABEL;
4844
456k
    case ':':
4845
456k
        ch_next = netsnmp_getc(fp);
4846
456k
        if (ch_next != ':') {
4847
20.5k
            ungetc(ch_next, fp);
4848
20.5k
            return LABEL;
4849
20.5k
        }
4850
435k
        ch_next = netsnmp_getc(fp);
4851
435k
        if (ch_next != '=') {
4852
345k
            ungetc(ch_next, fp);
4853
345k
            return LABEL;
4854
345k
        }
4855
90.0k
        return EQUALS;
4856
711k
    case '-':
4857
711k
        ch_next = netsnmp_getc(fp);
4858
711k
        if (ch_next == '-') {
4859
649k
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
4860
649k
               NETSNMP_DS_LIB_MIB_COMMENT_TERM)) {
4861
                /*
4862
                 * Treat the rest of this line as a comment. 
4863
                 */
4864
46.5k
                while ((ch_next != EOF) && (ch_next != '\n'))
4865
45.5k
                    ch_next = netsnmp_getc(fp);
4866
648k
            } else {
4867
                /*
4868
                 * Treat the rest of the line or until another '--' as a comment 
4869
                 */
4870
                /*
4871
                 * (this is the "technically" correct way to parse comments) 
4872
                 */
4873
648k
                ch = ' ';
4874
648k
                ch_next = netsnmp_getc(fp);
4875
3.20M
                while (ch_next != EOF && ch_next != '\n' &&
4876
3.00M
                       (ch != '-' || ch_next != '-')) {
4877
2.56M
                    ch = ch_next;
4878
2.56M
                    ch_next = netsnmp_getc(fp);
4879
2.56M
                }
4880
648k
            }
4881
649k
            if (ch_next == EOF)
4882
181
                return ENDOFFILE;
4883
649k
            if (ch_next == '\n')
4884
208k
                mibLine++;
4885
649k
            goto fetch_next_token;
4886
649k
        }
4887
62.0k
        ungetc(ch_next, fp);
4888
62.0k
  NETSNMP_FALLTHROUGH;
4889
6.61M
    default:
4890
        /*
4891
         * Accumulate characters until end of token is found.  Then attempt to
4892
         * match this token as a reserved word.  If a match is found, return the
4893
         * type.  Else it is a label.
4894
         */
4895
6.61M
        if (!is_labelchar(ch))
4896
5.55M
            return LABEL;
4897
1.06M
        hash += tolower(ch);
4898
1.06M
      more:
4899
11.0M
        while (is_labelchar(ch_next = netsnmp_getc(fp))) {
4900
9.96M
            hash += tolower(ch_next);
4901
9.96M
            if (cp - token < maxtlen - 1)
4902
7.34M
                *cp++ = ch_next;
4903
2.62M
            else
4904
2.62M
                too_long = 1;
4905
9.96M
        }
4906
1.06M
        ungetc(ch_next, fp);
4907
1.06M
        *cp = '\0';
4908
4909
1.06M
        if (too_long)
4910
1.82k
            print_error("Warning: token too long", token, CONTINUE);
4911
3.49M
        for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
4912
2.84M
            if ((tp->hash == hash) && (!label_compare(tp->name, token)))
4913
410k
                break;
4914
2.84M
        }
4915
1.06M
        if (tp) {
4916
410k
            if (tp->token != CONTINUE)
4917
404k
                return (tp->token);
4918
5.82k
            while (isspace((ch_next = netsnmp_getc(fp))))
4919
857k
                if (ch_next == '\n')
4920
1.44k
                    mibLine++;
4921
5.82k
            if (ch_next == EOF)
4922
17
                return ENDOFFILE;
4923
5.81k
            if (isalnum(ch_next)) {
4924
5.08k
                *cp++ = ch_next;
4925
5.08k
                hash += tolower(ch_next);
4926
5.08k
                goto more;
4927
5.08k
            }
4928
5.81k
        }
4929
658k
        if (token[0] == '-' || isdigit((unsigned char)(token[0]))) {
4930
621k
            for (cp = token + 1; *cp; cp++)
4931
468k
                if (!isdigit((unsigned char)(*cp)))
4932
42.2k
                    return LABEL;
4933
153k
            return NUMBER;
4934
195k
        }
4935
462k
        return LABEL;
4936
10.9M
    }
4937
10.9M
}
4938
4939
netsnmp_feature_child_of(parse_get_token, netsnmp_unused);
4940
#ifndef NETSNMP_FEATURE_REMOVE_PARSE_GET_TOKEN
4941
int
4942
snmp_get_token(FILE * fp, char *token, int maxtlen)
4943
0
{
4944
0
    return get_token(fp, token, maxtlen);
4945
0
}
4946
#endif /* NETSNMP_FEATURE_REMOVE_PARSE_GET_TOKEN */
4947
4948
int
4949
add_mibfile(const char* tmpstr, const char* d_name)
4950
26.7k
{
4951
26.7k
    FILE           *fp;
4952
26.7k
    char            token[MAXTOKEN], token2[MAXTOKEN];
4953
4954
    /*
4955
     * which module is this 
4956
     */
4957
26.7k
    if ((fp = fopen(tmpstr, "r")) == NULL) {
4958
15
        snmp_log_perror(tmpstr);
4959
15
        return 1;
4960
15
    }
4961
26.6k
    DEBUGMSGTL(("parse-mibs", "Checking file: %s...\n",
4962
26.6k
                tmpstr));
4963
26.6k
    mibLine = 1;
4964
26.6k
    File = tmpstr;
4965
26.6k
    if (get_token(fp, token, MAXTOKEN) != LABEL) {
4966
15.5k
      fclose(fp);
4967
15.5k
      return 1;
4968
15.5k
    }
4969
    /*
4970
     * simple test for this being a MIB 
4971
     */
4972
11.1k
    if (get_token(fp, token2, MAXTOKEN) == DEFINITIONS) {
4973
4.93k
        new_module(token, tmpstr);
4974
4.93k
        fclose(fp);
4975
4.93k
        return 0;
4976
6.18k
    } else {
4977
6.18k
        fclose(fp);
4978
6.18k
        return 1;
4979
6.18k
    }
4980
11.1k
}
4981
4982
static int elemcmp(const void *a, const void *b)
4983
41.9k
{
4984
41.9k
    const char *const *s1 = a, *const *s2 = b;
4985
4986
41.9k
    return strcmp(*s1, *s2);
4987
41.9k
}
4988
4989
/*
4990
 * Scan a directory and return all filenames found as an array of pointers to
4991
 * directory entries (@result).
4992
 */
4993
static int scan_directory(char ***result, const char *dirname)
4994
3.48k
{
4995
3.48k
    DIR            *dir, *dir2;
4996
3.48k
    struct dirent  *file;
4997
3.48k
    char          **filenames = NULL;
4998
3.48k
    int             fname_len, i, filename_count = 0, array_size = 0;
4999
3.48k
    char           *tmpstr;
5000
5001
3.48k
    *result = NULL;
5002
5003
3.48k
    dir = opendir(dirname);
5004
3.48k
    if (!dir)
5005
77
        return -1;
5006
5007
40.3k
    while ((file = readdir(dir))) {
5008
        /*
5009
         * Only parse file names that don't begin with a '.'
5010
         * Also skip files ending in '~', or starting/ending
5011
         * with '#' which are typically editor backup files.
5012
         */
5013
36.9k
        fname_len = strlen(file->d_name);
5014
36.9k
        if (fname_len > 0 && file->d_name[0] != '.'
5015
30.1k
            && file->d_name[0] != '#'
5016
30.1k
            && file->d_name[fname_len-1] != '#'
5017
30.1k
            && file->d_name[fname_len-1] != '~') {
5018
30.1k
            if (asprintf(&tmpstr, "%s/%s", dirname, file->d_name) < 0)
5019
0
                continue;
5020
30.1k
            dir2 = opendir(tmpstr);
5021
30.1k
            if (dir2) {
5022
                /* file is a directory, don't read it */
5023
6.81k
                closedir(dir2);
5024
23.3k
            } else {
5025
23.3k
                if (filename_count >= array_size) {
5026
3.40k
                    char **new_filenames;
5027
5028
3.40k
                    array_size = (array_size + 16) * 2;
5029
3.40k
                    new_filenames = realloc(filenames,
5030
3.40k
                                        array_size * sizeof(filenames[0]));
5031
3.40k
                    if (!new_filenames) {
5032
0
                        free(tmpstr);
5033
0
                        for (i = 0; i < filename_count; i++)
5034
0
                            free(filenames[i]);
5035
0
                        free(filenames);
5036
0
                        closedir(dir);
5037
0
                        return -1;
5038
0
                    }
5039
3.40k
                    filenames = new_filenames;
5040
3.40k
                }
5041
23.3k
                filenames[filename_count++] = tmpstr;
5042
23.3k
                tmpstr = NULL;
5043
23.3k
            }
5044
30.1k
            free(tmpstr);
5045
30.1k
        }
5046
36.9k
    }
5047
3.40k
    closedir(dir);
5048
5049
3.40k
    if (filenames)
5050
3.40k
        qsort(filenames, filename_count, sizeof(filenames[0]), elemcmp);
5051
3.40k
    *result = filenames;
5052
5053
3.40k
    return filename_count;
5054
3.40k
}
5055
5056
/* For Win32 platforms, the directory does not maintain a last modification
5057
 * date that we can compare with the modification date of the .index file.
5058
 * Therefore there is no way to know whether any .index file is valid.
5059
 * This is the reason for the #if !(defined(WIN32) || defined(cygwin))
5060
 * in the add_mibdir function
5061
 */
5062
int
5063
add_mibdir(const char *dirname)
5064
3.48k
{
5065
3.48k
    const char     *oldFile = File;
5066
3.48k
    char          **filenames;
5067
3.48k
    int             count = 0;
5068
3.48k
    int             filename_count, i;
5069
5070
3.48k
    DEBUGMSGTL(("parse-mibs", "Scanning directory %s\n", dirname));
5071
5072
3.48k
    filename_count = scan_directory(&filenames, dirname);
5073
5074
3.48k
    if (filename_count >= 0) {
5075
26.7k
        for (i = 0; i < filename_count; i++) {
5076
23.3k
            if (add_mibfile(filenames[i], strrchr(filenames[i], '/')) == 0)
5077
2.49k
                count++;
5078
23.3k
      free(filenames[i]);
5079
23.3k
        }
5080
3.40k
        File = oldFile;
5081
3.40k
        free(filenames);
5082
3.40k
        return (count);
5083
3.40k
    }
5084
77
    else
5085
77
        DEBUGMSGTL(("parse-mibs","cannot open MIB directory %s\n", dirname));
5086
5087
77
    return (-1);
5088
3.48k
}
5089
5090
5091
/*
5092
 * Returns the root of the whole tree
5093
 *   (for backwards compatability)
5094
 */
5095
struct tree    *
5096
read_mib(const char *filename)
5097
11.4k
{
5098
11.4k
    FILE           *fp;
5099
11.4k
    char            token[MAXTOKEN];
5100
5101
11.4k
    fp = fopen(filename, "r");
5102
11.4k
    if (fp == NULL) {
5103
373
        snmp_log_perror(filename);
5104
373
        return NULL;
5105
373
    }
5106
11.1k
    mibLine = 1;
5107
11.1k
    File = filename;
5108
11.1k
    DEBUGMSGTL(("parse-mibs", "Parsing file: %s...\n", filename));
5109
11.1k
    if (get_token(fp, token, MAXTOKEN) != LABEL) {
5110
614
      snmp_log(LOG_ERR, "Failed to parse MIB file %s\n", filename);
5111
614
      fclose(fp);
5112
614
      return NULL;
5113
614
    }
5114
10.5k
    fclose(fp);
5115
10.5k
    new_module(token, filename);
5116
10.5k
    (void) netsnmp_read_module(token);
5117
5118
10.5k
    return tree_head;
5119
11.1k
}
5120
5121
5122
struct tree    *
5123
read_all_mibs(void)
5124
0
{
5125
0
    struct module  *mp;
5126
5127
0
    for (mp = module_head; mp; mp = mp->next)
5128
0
        if (mp->no_imports == -1)
5129
0
            netsnmp_read_module(mp->name);
5130
0
    adopt_orphans();
5131
5132
    /* If entered the syntax error loop in "read_module()" */
5133
0
    if (gLoop == 1) {
5134
0
        gLoop = 0;
5135
0
        free(gpMibErrorString);
5136
0
        gpMibErrorString = NULL;
5137
0
        if (asprintf(&gpMibErrorString, "Error in parsing MIB module(s): %s !"
5138
0
                     " Unable to load corresponding MIB(s)", gMibNames) < 0) {
5139
0
            snmp_log(LOG_CRIT,
5140
0
                     "failed to allocated memory for gpMibErrorString\n");
5141
0
        }
5142
0
    }
5143
5144
    /* Caller's responsibility to free this memory */
5145
0
    tree_head->parseErrorString = gpMibErrorString;
5146
  
5147
0
    return tree_head;
5148
0
}
5149
5150
5151
#ifdef TEST
5152
int main(int argc, char *argv[])
5153
{
5154
    int             i;
5155
    struct tree    *tp;
5156
    netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_WARNINGS, 2);
5157
5158
    netsnmp_init_mib();
5159
5160
    if (argc == 1)
5161
        (void) read_all_mibs();
5162
    else
5163
        for (i = 1; i < argc; i++)
5164
            read_mib(argv[i]);
5165
5166
    for (tp = tree_head; tp; tp = tp->next_peer)
5167
        print_subtree(stdout, tp, 0);
5168
    free_tree(tree_head);
5169
5170
    return 0;
5171
}
5172
#endif                          /* TEST */
5173
5174
static int
5175
parseQuoteString(FILE * fp, char *token, int maxtlen)
5176
183k
{
5177
183k
    register int    ch;
5178
183k
    int             count = 0;
5179
183k
    int             too_long = 0;
5180
183k
    char           *token_start = token;
5181
5182
12.8M
    for (ch = netsnmp_getc(fp); ch != EOF; ch = netsnmp_getc(fp)) {
5183
12.8M
        if (ch == '\r')
5184
2.66k
            continue;
5185
12.8M
        if (ch == '\n') {
5186
101k
            mibLine++;
5187
12.7M
        } else if (ch == '"') {
5188
182k
            netsnmp_assert(token - token_start < maxtlen);
5189
182k
            *token = '\0';
5190
182k
            if (too_long && netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
5191
1.34k
             NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
5192
                /*
5193
                 * show short form for brevity sake 
5194
                 */
5195
0
                int             truncate_at = SNMP_MIN(50, maxtlen - 1);
5196
0
                char            ch_save = *(token_start + truncate_at);
5197
5198
0
                *(token_start + truncate_at) = '\0';
5199
0
                print_error("Warning: string too long",
5200
0
                            token_start, QUOTESTRING);
5201
0
                *(token_start + truncate_at) = ch_save;
5202
0
            }
5203
182k
            return QUOTESTRING;
5204
182k
        }
5205
        /*
5206
         * maximum description length check.  If greater, keep parsing
5207
         * but truncate the string 
5208
         */
5209
12.6M
        if (++count < maxtlen)
5210
5.10M
            *token++ = ch;
5211
7.52M
        else
5212
7.52M
            too_long = 1;
5213
12.6M
    }
5214
5215
635
    return 0;
5216
183k
}
5217
5218
/*
5219
 * struct index_list *
5220
 * getIndexes(FILE *fp):
5221
 *   This routine parses a string like  { blah blah blah } and returns a
5222
 *   list of the strings enclosed within it.
5223
 *
5224
 */
5225
static struct index_list *
5226
getIndexes(FILE * fp, struct index_list **retp)
5227
3.50k
{
5228
3.50k
    int             type;
5229
3.50k
    char            token[MAXTOKEN];
5230
3.50k
    char            nextIsImplied = 0;
5231
5232
3.50k
    struct index_list *mylist = NULL;
5233
3.50k
    struct index_list **mypp = &mylist;
5234
5235
3.50k
    free_indexes(retp);
5236
5237
3.50k
    type = get_token(fp, token, MAXTOKEN);
5238
5239
3.50k
    if (type != LEFTBRACKET) {
5240
16
        return NULL;
5241
16
    }
5242
5243
3.48k
    type = get_token(fp, token, MAXTOKEN);
5244
207k
    while (type != RIGHTBRACKET && type != ENDOFFILE) {
5245
204k
        if ((type == LABEL) || (type & SYNTAX_MASK)) {
5246
172k
            *mypp = calloc(1, sizeof(struct index_list));
5247
172k
            if (*mypp) {
5248
172k
                (*mypp)->ilabel = strdup(token);
5249
172k
                (*mypp)->isimplied = nextIsImplied;
5250
172k
                mypp = &(*mypp)->next;
5251
172k
                nextIsImplied = 0;
5252
172k
            }
5253
172k
        } else if (type == IMPLIED) {
5254
2.80k
            nextIsImplied = 1;
5255
2.80k
        }
5256
204k
        type = get_token(fp, token, MAXTOKEN);
5257
204k
    }
5258
5259
3.48k
    *retp = mylist;
5260
3.48k
    return mylist;
5261
3.50k
}
5262
5263
static struct varbind_list *
5264
getVarbinds(FILE * fp, struct varbind_list **retp)
5265
1.44k
{
5266
1.44k
    int             type;
5267
1.44k
    char            token[MAXTOKEN];
5268
5269
1.44k
    struct varbind_list *mylist = NULL;
5270
1.44k
    struct varbind_list **mypp = &mylist;
5271
5272
1.44k
    free_varbinds(retp);
5273
5274
1.44k
    type = get_token(fp, token, MAXTOKEN);
5275
5276
1.44k
    if (type != LEFTBRACKET) {
5277
29
        return NULL;
5278
29
    }
5279
5280
1.41k
    type = get_token(fp, token, MAXTOKEN);
5281
210k
    while (type != RIGHTBRACKET && type != ENDOFFILE) {
5282
209k
        if ((type == LABEL) || (type & SYNTAX_MASK)) {
5283
50.9k
            *mypp = calloc(1, sizeof(struct varbind_list));
5284
50.9k
            if (*mypp) {
5285
50.9k
                (*mypp)->vblabel = strdup(token);
5286
50.9k
                mypp = &(*mypp)->next;
5287
50.9k
            }
5288
50.9k
        }
5289
209k
        type = get_token(fp, token, MAXTOKEN);
5290
209k
    }
5291
5292
1.41k
    *retp = mylist;
5293
1.41k
    return mylist;
5294
1.44k
}
5295
5296
static void
5297
free_indexes(struct index_list **spp)
5298
435k
{
5299
435k
    if (spp && *spp) {
5300
2.74k
        struct index_list *pp, *npp;
5301
5302
2.74k
        pp = *spp;
5303
2.74k
        *spp = NULL;
5304
5305
98.3k
        while (pp) {
5306
95.6k
            npp = pp->next;
5307
95.6k
            if (pp->ilabel)
5308
95.6k
                free(pp->ilabel);
5309
95.6k
            free(pp);
5310
95.6k
            pp = npp;
5311
95.6k
        }
5312
2.74k
    }
5313
435k
}
5314
5315
static void
5316
free_varbinds(struct varbind_list **spp)
5317
432k
{
5318
432k
    if (spp && *spp) {
5319
1.36k
        struct varbind_list *pp, *npp;
5320
5321
1.36k
        pp = *spp;
5322
1.36k
        *spp = NULL;
5323
5324
47.4k
        while (pp) {
5325
46.0k
            npp = pp->next;
5326
46.0k
            if (pp->vblabel)
5327
46.0k
                free(pp->vblabel);
5328
46.0k
            free(pp);
5329
46.0k
            pp = npp;
5330
46.0k
        }
5331
1.36k
    }
5332
432k
}
5333
5334
static void
5335
free_ranges(struct range_list **spp)
5336
436k
{
5337
436k
    if (spp && *spp) {
5338
3.34k
        struct range_list *pp, *npp;
5339
5340
3.34k
        pp = *spp;
5341
3.34k
        *spp = NULL;
5342
5343
9.49k
        while (pp) {
5344
6.15k
            npp = pp->next;
5345
6.15k
            free(pp);
5346
6.15k
            pp = npp;
5347
6.15k
        }
5348
3.34k
    }
5349
436k
}
5350
5351
static void
5352
free_enums(struct enum_list **spp)
5353
435k
{
5354
435k
    if (spp && *spp) {
5355
2.51k
        struct enum_list *pp, *npp;
5356
5357
2.51k
        pp = *spp;
5358
2.51k
        *spp = NULL;
5359
5360
10.2k
        while (pp) {
5361
7.70k
            npp = pp->next;
5362
7.70k
            if (pp->label)
5363
7.70k
                free(pp->label);
5364
7.70k
            free(pp);
5365
7.70k
            pp = npp;
5366
7.70k
        }
5367
2.51k
    }
5368
435k
}
5369
5370
static struct enum_list *
5371
copy_enums(struct enum_list *sp)
5372
362
{
5373
362
    struct enum_list *xp = NULL, **spp = &xp;
5374
5375
848
    while (sp) {
5376
486
        *spp = calloc(1, sizeof(struct enum_list));
5377
486
        if (!*spp)
5378
0
            break;
5379
486
        (*spp)->label = strdup(sp->label);
5380
486
        (*spp)->value = sp->value;
5381
486
        spp = &(*spp)->next;
5382
486
        sp = sp->next;
5383
486
    }
5384
362
    return (xp);
5385
362
}
5386
5387
static struct range_list *
5388
copy_ranges(struct range_list *sp)
5389
362
{
5390
362
    struct range_list *xp = NULL, **spp = &xp;
5391
5392
877
    while (sp) {
5393
515
        *spp = calloc(1, sizeof(struct range_list));
5394
515
        if (!*spp)
5395
0
            break;
5396
515
        (*spp)->low = sp->low;
5397
515
        (*spp)->high = sp->high;
5398
515
        spp = &(*spp)->next;
5399
515
        sp = sp->next;
5400
515
    }
5401
362
    return (xp);
5402
362
}
5403
5404
/*
5405
 * This routine parses a string like  { blah blah blah } and returns OBJID if
5406
 * it is well formed, and NULL if not.
5407
 */
5408
static int
5409
tossObjectIdentifier(FILE * fp)
5410
52
{
5411
52
    int             type;
5412
52
    char            token[MAXTOKEN];
5413
52
    int             bracketcount = 1;
5414
5415
52
    type = get_token(fp, token, MAXTOKEN);
5416
5417
52
    if (type != LEFTBRACKET)
5418
5
        return 0;
5419
535k
    while ((type != RIGHTBRACKET || bracketcount > 0) && type != ENDOFFILE) {
5420
535k
        type = get_token(fp, token, MAXTOKEN);
5421
535k
        if (type == LEFTBRACKET)
5422
525k
            bracketcount++;
5423
10.2k
        else if (type == RIGHTBRACKET)
5424
279
            bracketcount--;
5425
535k
    }
5426
5427
47
    if (type == RIGHTBRACKET)
5428
15
        return OBJID;
5429
32
    else
5430
32
        return 0;
5431
47
}
5432
5433
/* Find node in any MIB module
5434
   Used by Perl modules   */
5435
struct tree    *
5436
find_node(const char *name, struct tree *subtree)
5437
0
{                               /* Unused */
5438
0
    return (find_tree_node(name, -1));
5439
0
}
5440
5441
netsnmp_feature_child_of(parse_find_node2, netsnmp_unused);
5442
#ifndef NETSNMP_FEATURE_REMOVE_PARSE_FIND_NODE2
5443
struct tree    *
5444
find_node2(const char *name, const char *module)
5445
0
{                               
5446
0
  int modid = -1;
5447
0
  if (module) {
5448
0
    modid = which_module(module);
5449
0
  }
5450
0
  if (modid == -1)
5451
0
  {
5452
0
    return (NULL);
5453
0
  }
5454
0
  return (find_tree_node(name, modid));
5455
0
}
5456
#endif /* NETSNMP_FEATURE_REMOVE_PARSE_FIND_NODE2 */
5457
5458
#ifndef NETSNMP_FEATURE_REMOVE_FIND_MODULE
5459
/* Used in the perl module */
5460
struct module  *
5461
find_module(int mid)
5462
0
{
5463
0
    struct module  *mp;
5464
5465
0
    for (mp = module_head; mp != NULL; mp = mp->next) {
5466
0
        if (mp->modid == mid)
5467
0
            break;
5468
0
    }
5469
0
    return mp;
5470
0
}
5471
#endif /* NETSNMP_FEATURE_REMOVE_FIND_MODULE */
5472
5473
5474
static char     leave_indent[256];
5475
static int      leave_was_simple;
5476
5477
static void
5478
print_mib_leaves(FILE * f, struct tree *tp, int width)
5479
0
{
5480
0
    struct tree    *ntp;
5481
0
    char           *ip = leave_indent + strlen(leave_indent) - 1;
5482
0
    char            last_ipch = *ip;
5483
5484
0
    *ip = '+';
5485
0
    if (tp->type == TYPE_OTHER || tp->type > TYPE_SIMPLE_LAST) {
5486
0
        fprintf(f, "%s--%s(%ld)\n", leave_indent, tp->label, tp->subid);
5487
0
        if (tp->indexes) {
5488
0
            struct index_list *xp = tp->indexes;
5489
0
            int             first = 1, cpos = 0, len, cmax =
5490
0
                width - strlen(leave_indent) - 12;
5491
0
            *ip = last_ipch;
5492
0
            fprintf(f, "%s  |  Index: ", leave_indent);
5493
0
            while (xp) {
5494
0
                if (first)
5495
0
                    first = 0;
5496
0
                else
5497
0
                    fprintf(f, ", ");
5498
0
                cpos += (len = strlen(xp->ilabel) + 2);
5499
0
                if (cpos > cmax) {
5500
0
                    fprintf(f, "\n");
5501
0
                    fprintf(f, "%s  |         ", leave_indent);
5502
0
                    cpos = len;
5503
0
                }
5504
0
                fprintf(f, "%s", xp->ilabel);
5505
0
                xp = xp->next;
5506
0
            }
5507
0
            fprintf(f, "\n");
5508
0
            *ip = '+';
5509
0
        }
5510
0
    } else {
5511
0
        const char     *acc, *typ;
5512
0
        int             size = 0;
5513
0
        switch (tp->access) {
5514
0
        case MIB_ACCESS_NOACCESS:
5515
0
            acc = "----";
5516
0
            break;
5517
0
        case MIB_ACCESS_READONLY:
5518
0
            acc = "-R--";
5519
0
            break;
5520
0
        case MIB_ACCESS_WRITEONLY:
5521
0
            acc = "--W-";
5522
0
            break;
5523
0
        case MIB_ACCESS_READWRITE:
5524
0
            acc = "-RW-";
5525
0
            break;
5526
0
        case MIB_ACCESS_NOTIFY:
5527
0
            acc = "---N";
5528
0
            break;
5529
0
        case MIB_ACCESS_CREATE:
5530
0
            acc = "CR--";
5531
0
            break;
5532
0
        default:
5533
0
            acc = "    ";
5534
0
            break;
5535
0
        }
5536
0
        switch (tp->type) {
5537
0
        case TYPE_OBJID:
5538
0
            typ = "ObjID    ";
5539
0
            break;
5540
0
        case TYPE_OCTETSTR:
5541
0
            typ = "String   ";
5542
0
            size = 1;
5543
0
            break;
5544
0
        case TYPE_INTEGER:
5545
0
            if (tp->enums)
5546
0
                typ = "EnumVal  ";
5547
0
            else
5548
0
                typ = "INTEGER  ";
5549
0
            break;
5550
0
        case TYPE_NETADDR:
5551
0
            typ = "NetAddr  ";
5552
0
            break;
5553
0
        case TYPE_IPADDR:
5554
0
            typ = "IpAddr   ";
5555
0
            break;
5556
0
        case TYPE_COUNTER:
5557
0
            typ = "Counter  ";
5558
0
            break;
5559
0
        case TYPE_GAUGE:
5560
0
            typ = "Gauge    ";
5561
0
            break;
5562
0
        case TYPE_TIMETICKS:
5563
0
            typ = "TimeTicks";
5564
0
            break;
5565
0
        case TYPE_OPAQUE:
5566
0
            typ = "Opaque   ";
5567
0
            size = 1;
5568
0
            break;
5569
0
        case TYPE_NULL:
5570
0
            typ = "Null     ";
5571
0
            break;
5572
0
        case TYPE_COUNTER64:
5573
0
            typ = "Counter64";
5574
0
            break;
5575
0
        case TYPE_BITSTRING:
5576
0
            typ = "BitString";
5577
0
            break;
5578
0
        case TYPE_NSAPADDRESS:
5579
0
            typ = "NsapAddr ";
5580
0
            break;
5581
0
        case TYPE_UNSIGNED32:
5582
0
            typ = "Unsigned ";
5583
0
            break;
5584
0
        case TYPE_UINTEGER:
5585
0
            typ = "UInteger ";
5586
0
            break;
5587
0
        case TYPE_INTEGER32:
5588
0
            typ = "Integer32";
5589
0
            break;
5590
0
        default:
5591
0
            typ = "         ";
5592
0
            break;
5593
0
        }
5594
0
        fprintf(f, "%s-- %s %s %s(%ld)\n", leave_indent, acc, typ,
5595
0
                tp->label, tp->subid);
5596
0
        *ip = last_ipch;
5597
0
        if (tp->tc_index >= 0)
5598
0
            fprintf(f, "%s        Textual Convention: %s\n", leave_indent,
5599
0
                    tclist[tp->tc_index].descriptor);
5600
0
        if (tp->enums) {
5601
0
            struct enum_list *ep = tp->enums;
5602
0
            int             cpos = 0, cmax =
5603
0
                width - strlen(leave_indent) - 16;
5604
0
            fprintf(f, "%s        Values: ", leave_indent);
5605
0
            while (ep) {
5606
0
                char            buf[80];
5607
0
                int             bufw;
5608
0
                if (ep != tp->enums)
5609
0
                    fprintf(f, ", ");
5610
0
                snprintf(buf, sizeof(buf), "%s(%d)", ep->label, ep->value);
5611
0
                buf[ sizeof(buf)-1 ] = 0;
5612
0
                cpos += (bufw = strlen(buf) + 2);
5613
0
                if (cpos >= cmax) {
5614
0
                    fprintf(f, "\n%s                ", leave_indent);
5615
0
                    cpos = bufw;
5616
0
                }
5617
0
                fprintf(f, "%s", buf);
5618
0
                ep = ep->next;
5619
0
            }
5620
0
            fprintf(f, "\n");
5621
0
        }
5622
0
        if (tp->ranges) {
5623
0
            struct range_list *rp = tp->ranges;
5624
0
            if (size)
5625
0
                fprintf(f, "%s        Size: ", leave_indent);
5626
0
            else
5627
0
                fprintf(f, "%s        Range: ", leave_indent);
5628
0
            while (rp) {
5629
0
                if (rp != tp->ranges)
5630
0
                    fprintf(f, " | ");
5631
0
                print_range_value(f, tp->type, rp);
5632
0
                rp = rp->next;
5633
0
            }
5634
0
            fprintf(f, "\n");
5635
0
        }
5636
0
    }
5637
0
    *ip = last_ipch;
5638
0
    strcat(leave_indent, "  |");
5639
0
    leave_was_simple = tp->type != TYPE_OTHER;
5640
5641
0
    {
5642
0
        int             i, j, count = 0;
5643
0
        struct leave {
5644
0
            oid             id;
5645
0
            struct tree    *tp;
5646
0
        }              *leaves, *lp;
5647
5648
0
        for (ntp = tp->child_list; ntp; ntp = ntp->next_peer)
5649
0
            count++;
5650
0
        if (count) {
5651
0
            leaves = calloc(count, sizeof(struct leave));
5652
0
            if (!leaves)
5653
0
                return;
5654
0
            for (ntp = tp->child_list, count = 0; ntp;
5655
0
                 ntp = ntp->next_peer) {
5656
0
                for (i = 0, lp = leaves; i < count; i++, lp++)
5657
0
                    if (lp->id >= ntp->subid)
5658
0
                        break;
5659
0
                for (j = count; j > i; j--)
5660
0
                    leaves[j] = leaves[j - 1];
5661
0
                lp->id = ntp->subid;
5662
0
                lp->tp = ntp;
5663
0
                count++;
5664
0
            }
5665
0
            for (i = 1, lp = leaves; i <= count; i++, lp++) {
5666
0
                if (!leave_was_simple || lp->tp->type == 0)
5667
0
                    fprintf(f, "%s\n", leave_indent);
5668
0
                if (i == count)
5669
0
                    ip[3] = ' ';
5670
0
                print_mib_leaves(f, lp->tp, width);
5671
0
            }
5672
0
            free(leaves);
5673
0
            leave_was_simple = 0;
5674
0
        }
5675
0
    }
5676
0
    ip[1] = 0;
5677
0
}
5678
5679
void
5680
print_mib_tree(FILE * f, struct tree *tp, int width)
5681
0
{
5682
0
    leave_indent[0] = ' ';
5683
0
    leave_indent[1] = 0;
5684
0
    leave_was_simple = 1;
5685
0
    print_mib_leaves(f, tp, width);
5686
0
}
5687
5688
5689
/*
5690
 * Merge the parsed object identifier with the existing node.
5691
 * If there is a problem with the identifier, release the existing node.
5692
 */
5693
static struct node *
5694
merge_parse_objectid(struct node *np, FILE * fp, char *name)
5695
38.4k
{
5696
38.4k
    struct node    *nnp;
5697
    /*
5698
     * printf("merge defval --> %s\n",np->defaultValue); 
5699
     */
5700
38.4k
    nnp = parse_objectid(fp, name);
5701
38.4k
    if (nnp) {
5702
5703
        /*
5704
         * apply last OID sub-identifier data to the information 
5705
         */
5706
        /*
5707
         * already collected for this node. 
5708
         */
5709
36.8k
        struct node    *headp, *nextp;
5710
36.8k
        int             ncount = 0;
5711
36.8k
        nextp = headp = nnp;
5712
128k
        while (nnp->next) {
5713
92.0k
            nextp = nnp;
5714
92.0k
            ncount++;
5715
92.0k
            nnp = nnp->next;
5716
92.0k
        }
5717
5718
36.8k
        np->label = nnp->label;
5719
36.8k
        np->subid = nnp->subid;
5720
36.8k
        np->modid = nnp->modid;
5721
36.8k
        np->parent = nnp->parent;
5722
36.8k
  if (nnp->filename != NULL) {
5723
36.8k
    free(nnp->filename);
5724
36.8k
  }
5725
36.8k
        free(nnp);
5726
5727
36.8k
        if (ncount) {
5728
13.7k
            nextp->next = np;
5729
13.7k
            np = headp;
5730
13.7k
        }
5731
36.8k
    } else {
5732
1.66k
        free_node(np);
5733
1.66k
        np = NULL;
5734
1.66k
    }
5735
5736
38.4k
    return np;
5737
38.4k
}
5738
5739
/*
5740
 * transfer data to tree from node
5741
 *
5742
 * move pointers for alloc'd data from np to tp.
5743
 * this prevents them from being freed when np is released.
5744
 * parent member is not moved.
5745
 *
5746
 * CAUTION: nodes may be repeats of existing tree nodes.
5747
 * This can happen especially when resolving IMPORT clauses.
5748
 *
5749
 */
5750
static void
5751
tree_from_node(struct tree *tp, struct node *np)
5752
116k
{
5753
116k
    free_partial_tree(tp, FALSE);
5754
5755
116k
    tp->label = np->label;
5756
116k
    np->label = NULL;
5757
116k
    tp->enums = np->enums;
5758
116k
    np->enums = NULL;
5759
116k
    tp->ranges = np->ranges;
5760
116k
    np->ranges = NULL;
5761
116k
    tp->indexes = np->indexes;
5762
116k
    np->indexes = NULL;
5763
116k
    tp->augments = np->augments;
5764
116k
    np->augments = NULL;
5765
116k
    tp->varbinds = np->varbinds;
5766
116k
    np->varbinds = NULL;
5767
116k
    tp->hint = np->hint;
5768
116k
    np->hint = NULL;
5769
116k
    tp->units = np->units;
5770
116k
    np->units = NULL;
5771
116k
    tp->description = np->description;
5772
116k
    np->description = NULL;
5773
116k
    tp->reference = np->reference;
5774
116k
    np->reference = NULL;
5775
116k
    tp->defaultValue = np->defaultValue;
5776
116k
    np->defaultValue = NULL;
5777
116k
    tp->subid = np->subid;
5778
116k
    tp->tc_index = np->tc_index;
5779
116k
    tp->type = translation_table[np->type];
5780
116k
    tp->access = np->access;
5781
116k
    tp->status = np->status;
5782
5783
116k
    set_function(tp);
5784
116k
}
5785
5786
#endif /* NETSNMP_DISABLE_MIB_LOADING */