Coverage Report

Created: 2025-07-23 06:49

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