Coverage Report

Created: 2025-12-08 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/parse.c
Line
Count
Source
1
/*
2
 * parse.c
3
 *
4
 */
5
/* Portions of this file are subject to the following copyrights.  See
6
 * the Net-SNMP's COPYING file for more details and other copyrights
7
 * that may apply:
8
 */
9
/******************************************************************
10
        Copyright 1989, 1991, 1992 by Carnegie Mellon University
11
12
                      All Rights Reserved
13
14
Permission to use, copy, modify, and distribute this software and its
15
documentation for any purpose and without fee is hereby granted,
16
provided that the above copyright notice appear in all copies and that
17
both that copyright notice and this permission notice appear in
18
supporting documentation, and that the name of CMU not be
19
used in advertising or publicity pertaining to distribution of the
20
software without specific, written prior permission.
21
22
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
24
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
25
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
26
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
27
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28
SOFTWARE.
29
******************************************************************/
30
/*
31
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
32
 * Use is subject to license terms specified in the COPYING file
33
 * distributed with the Net-SNMP package.
34
 */
35
#include <net-snmp/net-snmp-config.h>
36
#include <net-snmp/net-snmp-features.h>
37
38
#ifndef NETSNMP_DISABLE_MIB_LOADING
39
40
#ifdef HAVE_LIMITS_H
41
#include <limits.h>
42
#endif
43
#include <stdio.h>
44
#ifdef HAVE_STDLIB_H
45
#include <stdlib.h>
46
#endif
47
#ifdef HAVE_STRING_H
48
#include <string.h>
49
#else
50
#include <strings.h>
51
#endif
52
#include <ctype.h>
53
#include <sys/types.h>
54
#ifdef HAVE_SYS_STAT_H
55
#include <sys/stat.h>
56
#endif
57
58
#ifdef HAVE_DIRENT_H
59
#include <dirent.h>
60
#endif
61
#ifdef TIME_WITH_SYS_TIME
62
# include <sys/time.h>
63
# include <time.h>
64
#else
65
# ifdef HAVE_SYS_TIME_H
66
#  include <sys/time.h>
67
# else
68
#  include <time.h>
69
# endif
70
#endif
71
#ifdef HAVE_NETINET_IN_H
72
#include <netinet/in.h>
73
#endif
74
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
75
#include <regex.h>
76
#endif
77
#ifdef HAVE_UNISTD_H
78
#include <unistd.h>
79
#endif
80
81
#include <errno.h>
82
83
#include <net-snmp/types.h>
84
#include <net-snmp/output_api.h>
85
#include <net-snmp/config_api.h>
86
#include <net-snmp/utilities.h>
87
88
#include <net-snmp/library/parse.h>
89
#include <net-snmp/library/mib.h>
90
#include <net-snmp/library/snmp_api.h>
91
#include <net-snmp/library/tools.h>
92
93
netsnmp_feature_child_of(find_module, mib_api);
94
netsnmp_feature_child_of(get_tc_description, mib_api);
95
96
/*
97
 * A linked list of nodes.
98
 */
99
struct node {
100
    struct node    *next;
101
    char           *label;  /* This node's (unique) textual name */
102
    u_long          subid;  /* This node's integer subidentifier */
103
    int             modid;  /* The module containing this node */
104
    char           *parent; /* The parent's textual name */
105
    int             tc_index; /* index into tclist (-1 if NA) */
106
    int             type;   /* The type of object this represents */
107
    int             access;
108
    int             status;
109
    struct enum_list *enums; /* (optional) list of enumerated integers */
110
    struct range_list *ranges;
111
    struct index_list *indexes;
112
    char           *augments;
113
    struct varbind_list *varbinds;
114
    char           *hint;
115
    char           *units;
116
    char           *description; /* description (a quoted string) */
117
    char           *reference; /* references (a quoted string) */
118
    char           *defaultValue;
119
    char           *filename;
120
    int             lineno;
121
};
122
123
/*
124
 * This is one element of an object identifier with either an integer
125
 * subidentifier, or a textual string label, or both.
126
 * The subid is -1 if not present, and label is NULL if not present.
127
 */
128
struct subid_s {
129
    int             subid;
130
    int             modid;
131
    char           *label;
132
};
133
134
3.44k
#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.57M
#define SYNTAX_MASK     0x80
158
/*
159
 * types of tokens
160
 * Tokens with the SYNTAX_MASK bit set are syntax tokens 
161
 */
162
873k
#define CONTINUE    -1
163
6.33M
#define ENDOFFILE   0
164
5.37M
#define LABEL       1
165
#define SUBTREE     2
166
79.6k
#define SYNTAX      3
167
5.28k
#define OBJID       (4 | SYNTAX_MASK)
168
5.94k
#define OCTETSTR    (5 | SYNTAX_MASK)
169
89.4k
#define INTEGER     (6 | SYNTAX_MASK)
170
88.4k
#define NETADDR     (7 | SYNTAX_MASK)
171
88.6k
#define IPADDR      (8 | SYNTAX_MASK)
172
93.0k
#define COUNTER     (9 | SYNTAX_MASK)
173
93.7k
#define GAUGE       (10 | SYNTAX_MASK)
174
91.9k
#define TIMETICKS   (11 | SYNTAX_MASK)
175
91.6k
#define KW_OPAQUE   (12 | SYNTAX_MASK)
176
5.43k
#define NUL         (13 | SYNTAX_MASK)
177
66.7k
#define SEQUENCE    14
178
540
#define OF          15          /* SEQUENCE OF */
179
11.8k
#define OBJTYPE     16
180
11.7k
#define ACCESS      17
181
27.0k
#define READONLY    18
182
17.4k
#define READWRITE   19
183
18.1k
#define WRITEONLY   20
184
#ifdef NOACCESS
185
#undef NOACCESS                 /* agent 'NOACCESS' token */
186
#endif
187
19.5k
#define NOACCESS    21
188
27.4k
#define STATUS      22
189
23.1k
#define MANDATORY   23
190
12.3k
#define KW_OPTIONAL    24
191
14.2k
#define OBSOLETE    25
192
/*
193
 * #define RECOMMENDED 26 
194
 */
195
#define PUNCT       27
196
3.77M
#define EQUALS      28
197
225k
#define NUMBER      29
198
3.42M
#define LEFTBRACKET 30
199
7.36M
#define RIGHTBRACKET 31
200
286k
#define LEFTPAREN   32
201
58.3k
#define RIGHTPAREN  33
202
72.5k
#define COMMA       34
203
93.4k
#define DESCRIPTION 35
204
381k
#define QUOTESTRING 36
205
2.10k
#define INDEX       37
206
1.86k
#define DEFVAL      38
207
21.0k
#define DEPRECATED  39
208
7.70k
#define SIZE        40
209
10.5k
#define BITSTRING   (41 | SYNTAX_MASK)
210
89.9k
#define NSAPADDRESS (42 | SYNTAX_MASK)
211
89.3k
#define COUNTER64   (43 | SYNTAX_MASK)
212
5.96k
#define OBJGROUP    44
213
5.01k
#define NOTIFTYPE   45
214
246
#define AUGMENTS    46
215
14.6k
#define COMPLIANCE  47
216
15.5k
#define READCREATE  48
217
11.7k
#define UNITS       49
218
10.0k
#define REFERENCE   50
219
45
#define NUM_ENTRIES 51
220
9.41k
#define MODULEIDENTITY 52
221
6.11k
#define LASTUPDATED 53
222
5.01k
#define ORGANIZATION 54
223
3.23k
#define CONTACTINFO 55
224
89.1k
#define UINTEGER32 (56 | SYNTAX_MASK)
225
49.6k
#define CURRENT     57
226
21.0k
#define DEFINITIONS 58
227
44.0k
#define END         59
228
873k
#define SEMI        60
229
3.88k
#define TRAPTYPE    61
230
670
#define ENTERPRISE  62
231
/*
232
 * #define DISPLAYSTR (63 | SYNTAX_MASK) 
233
 */
234
262k
#define BEGIN       64
235
2.88k
#define IMPORTS     65
236
54
#define EXPORTS     66
237
3.95k
#define ACCNOTIFY   67
238
30.4k
#define BAR         68
239
175k
#define RANGE       69
240
13.1k
#define CONVENTION  70
241
30.0k
#define DISPLAYHINT 71
242
156k
#define FROM        72
243
6.72k
#define AGENTCAP    73
244
28.5k
#define MACRO       74
245
12.8k
#define IMPLIED     75
246
1.16k
#define SUPPORTS    76
247
875
#define INCLUDES    77
248
2
#define VARIATION   78
249
2.68k
#define REVISION    79
250
0
#define NOTIMPL     80
251
4.96k
#define OBJECTS     81
252
294
#define NOTIFICATIONS 82
253
16.9k
#define MODULE      83
254
6.84k
#define MINACCESS   84
255
3.41k
#define PRODREL     85
256
6.84k
#define WRSYNTAX    86
257
0
#define CREATEREQ   87
258
3.59k
#define NOTIFGROUP  88
259
8.14k
#define MANDATORYGROUPS 89
260
30.8k
#define GROUP     90
261
35.9k
#define OBJECT      91
262
2.68k
#define IDENTIFIER  92
263
32.0k
#define CHOICE      93
264
28.9k
#define LEFTSQBRACK 95
265
153k
#define RIGHTSQBRACK  96
266
5.09k
#define IMPLICIT    97
267
85.3k
#define APPSYNTAX (98 | SYNTAX_MASK)
268
84.9k
#define OBJSYNTAX (99 | SYNTAX_MASK)
269
85.3k
#define SIMPLESYNTAX  (100 | SYNTAX_MASK)
270
85.5k
#define OBJNAME   (101 | SYNTAX_MASK)
271
86.3k
#define NOTIFNAME (102 | SYNTAX_MASK)
272
166
#define VARIABLES 103
273
90.7k
#define UNSIGNED32  (104 | SYNTAX_MASK)
274
88.9k
#define INTEGER32 (105 | SYNTAX_MASK)
275
3.98k
#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
383k
#define MODULE_NOT_FOUND  0
514
21.0k
#define MODULE_LOADED_OK  1
515
6.61k
#define MODULE_ALREADY_LOADED 2
516
/*
517
 * #define MODULE_LOAD_FAILED   3       
518
 */
519
0
#define MODULE_LOAD_FAILED  MODULE_NOT_FOUND
520
30.3k
#define MODULE_SYNTAX_ERROR     4
521
522
int gMibError = 0,gLoop = 0;
523
static char *gpMibErrorString;
524
char gMibNames[STRINGMAX];
525
526
1.32M
#define HASHSIZE        32
527
1.32M
#define BUCKET(x)       (x & (HASHSIZE-1))
528
529
6.41M
#define NHASHSIZE    128
530
3.27M
#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
918
#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
47
{
634
47
    if (options) {
635
1.73k
        while (*options) {
636
1.70k
            switch (*options) {
637
343
            case 'u':
638
343
                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL,
639
343
                               !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
640
343
                                               NETSNMP_DS_LIB_MIB_PARSE_LABEL));
641
343
                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
238
            case 'e':
649
238
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
650
238
            NETSNMP_DS_LIB_MIB_ERRORS);
651
238
                break;
652
653
88
            case 'w':
654
88
                netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
655
88
           NETSNMP_DS_LIB_MIB_WARNINGS, 1);
656
88
                break;
657
658
307
            case 'W':
659
307
                netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
660
307
           NETSNMP_DS_LIB_MIB_WARNINGS, 2);
661
307
                break;
662
663
262
            case 'd':
664
262
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 
665
262
            NETSNMP_DS_LIB_SAVE_MIB_DESCRS);
666
262
                break;
667
668
100
            case 'R':
669
100
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 
670
100
            NETSNMP_DS_LIB_MIB_REPLACE);
671
100
                break;
672
673
25
            default:
674
                /*
675
                 * return at the unknown option 
676
                 */
677
25
                return options;
678
1.70k
            }
679
1.68k
            options++;
680
1.68k
        }
681
47
    }
682
22
    return NULL;
683
47
}
684
685
static int
686
name_hash(const char *name)
687
3.58M
{
688
3.58M
    int             hash = 0;
689
3.58M
    const char     *cp;
690
691
3.58M
    if (!name)
692
0
        return 0;
693
21.3M
    for (cp = name; *cp; cp++)
694
17.8M
        hash += tolower((unsigned char)(*cp));
695
3.58M
    return (hash);
696
3.58M
}
697
698
void
699
netsnmp_init_mib_internals(void)
700
209k
{
701
209k
    register struct tok *tp;
702
209k
    register int    b, i;
703
209k
    int             max_modc;
704
705
209k
    if (tree_head)
706
206k
        return;
707
708
    /*
709
     * Set up hash list of pre-defined tokens
710
     */
711
3.30k
    memset(buckets, 0, sizeof(buckets));
712
307k
    for (tp = tokens; tp->name; tp++) {
713
304k
        tp->hash = name_hash(tp->name);
714
304k
        b = BUCKET(tp->hash);
715
304k
        if (buckets[b])
716
198k
            tp->next = buckets[b];      /* BUG ??? */
717
304k
        buckets[b] = tp;
718
304k
    }
719
720
    /*
721
     * Initialise other internal structures
722
     */
723
724
3.30k
    max_modc = sizeof(module_map) / sizeof(module_map[0]) - 1;
725
72.7k
    for (i = 0; i < max_modc; ++i)
726
69.4k
        module_map[i].next = &(module_map[i + 1]);
727
3.30k
    module_map[max_modc].next = NULL;
728
3.30k
    module_map_head = module_map;
729
730
3.30k
    memset(nbuckets, 0, sizeof(nbuckets));
731
3.30k
    memset(tbuckets, 0, sizeof(tbuckets));
732
3.30k
    tc_alloc = TC_INCR;
733
3.30k
    tclist = calloc(tc_alloc, sizeof(struct tc));
734
3.30k
    build_translation_table();
735
3.30k
    init_tree_roots();          /* Set up initial roots */
736
    /*
737
     * Relies on 'add_mibdir' having set up the modules 
738
     */
739
3.30k
}
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
12.1k
{
752
12.1k
    struct node    *np, *nextp;
753
12.1k
    int             hash;
754
755
12.1k
    memset(nbuckets, 0, sizeof(nbuckets));
756
264k
    for (np = nodes; np;) {
757
252k
        nextp = np->next;
758
252k
        hash = NBUCKET(name_hash(np->parent));
759
252k
        np->next = nbuckets[hash];
760
252k
        nbuckets[hash] = np;
761
252k
        np = nextp;
762
252k
    }
763
12.1k
}
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
400k
{
780
400k
    erroneousMibs++;
781
400k
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
782
400k
                                NETSNMP_DS_LIB_MIB_ERRORS))
783
227k
  return;
784
173k
    DEBUGMSGTL(("parse-mibs", "\n"));
785
173k
    if (type == ENDOFFILE)
786
415
        snmp_log(LOG_ERR, "%s (EOF): At line %d in %s\n", str, mibLine,
787
415
                 File);
788
172k
    else if (token && *token)
789
172k
        snmp_log(LOG_ERR, "%s (%s): At line %d in %s\n", str, token,
790
172k
                 mibLine, File);
791
472
    else
792
472
        snmp_log(LOG_ERR, "%s: At line %d in %s\n", str, mibLine, File);
793
173k
}
794
795
static void
796
print_module_not_found(const char *cp)
797
184k
{
798
184k
    if (first_err_module) {
799
11
        snmp_log(LOG_ERR, "MIB search path: %s\n",
800
11
                           netsnmp_get_mib_directory());
801
11
        first_err_module = 0;
802
11
    }
803
184k
    if (!last_err_module || strcmp(cp, last_err_module))
804
157k
        print_error("Cannot find module", cp, CONTINUE);
805
184k
    if (last_err_module)
806
177k
        free(last_err_module);
807
184k
    last_err_module = strdup(cp);
808
184k
}
809
810
static struct node *
811
alloc_node(int modid)
812
251k
{
813
251k
    struct node    *np;
814
815
251k
    np = calloc(1, sizeof(struct node));
816
251k
    if (!np)
817
0
        return NULL;
818
819
251k
    np->tc_index = -1;
820
251k
    np->modid = modid;
821
251k
    np->filename = strdup(File);
822
251k
    np->lineno = mibLine;
823
824
251k
    return np;
825
251k
}
826
827
static void
828
unlink_tbucket(struct tree *tp)
829
40.2k
{
830
40.2k
    int             hash = NBUCKET(name_hash(tp->label));
831
40.2k
    struct tree    *otp = NULL, *ntp = tbuckets[hash];
832
833
56.4k
    while (ntp && ntp != tp) {
834
16.2k
        otp = ntp;
835
16.2k
        ntp = ntp->next;
836
16.2k
    }
837
40.2k
    if (!ntp)
838
0
        snmp_log(LOG_EMERG, "Can't find %s in tbuckets\n", tp->label);
839
40.2k
    else if (otp)
840
7.34k
        otp->next = ntp->next;
841
32.9k
    else
842
32.9k
        tbuckets[hash] = tp->next;
843
40.2k
}
844
845
static void
846
unlink_tree(struct tree *tp)
847
29.9k
{
848
29.9k
    struct tree    *otp = NULL, *ntp = tp->parent;
849
850
29.9k
    if (!ntp) {                 /* this tree has no parent */
851
9.88k
        DEBUGMSGTL(("unlink_tree", "Tree node %s has no parent\n",
852
9.88k
                    tp->label));
853
20.0k
    } else {
854
20.0k
        ntp = ntp->child_list;
855
856
728k
        while (ntp && ntp != tp) {
857
708k
            otp = ntp;
858
708k
            ntp = ntp->next_peer;
859
708k
        }
860
20.0k
        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
20.0k
        else if (otp)
864
2.92k
            otp->next_peer = ntp->next_peer;
865
17.1k
        else
866
17.1k
            tp->parent->child_list = tp->next_peer;
867
20.0k
    }
868
869
29.9k
    if (tree_head == tp)
870
9.88k
        tree_head = tp->next_peer;
871
29.9k
}
872
873
static void
874
free_partial_tree(struct tree *tp, int keep_label)
875
112k
{
876
112k
    if (!tp)
877
0
        return;
878
879
    /*
880
     * remove the data from this tree node 
881
     */
882
112k
    free_enums(&tp->enums);
883
112k
    free_ranges(&tp->ranges);
884
112k
    free_indexes(&tp->indexes);
885
112k
    free_varbinds(&tp->varbinds);
886
112k
    if (!keep_label)
887
112k
        SNMP_FREE(tp->label);
888
112k
    SNMP_FREE(tp->hint);
889
112k
    SNMP_FREE(tp->units);
890
112k
    SNMP_FREE(tp->description);
891
112k
    SNMP_FREE(tp->reference);
892
112k
    SNMP_FREE(tp->augments);
893
112k
    SNMP_FREE(tp->defaultValue);
894
112k
}
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
33.1k
{
903
33.1k
    if (!Tree)
904
0
        return;
905
906
33.1k
    unlink_tbucket(Tree);
907
33.1k
    free_partial_tree(Tree, FALSE);
908
33.1k
    if (Tree->module_list != &Tree->modid)
909
471
        free(Tree->module_list);
910
33.1k
    free(Tree);
911
33.1k
}
912
913
static void
914
free_node(struct node *np)
915
197k
{
916
197k
    if (!np)
917
91
        return;
918
919
197k
    free_enums(&np->enums);
920
197k
    free_ranges(&np->ranges);
921
197k
    free_indexes(&np->indexes);
922
197k
    free_varbinds(&np->varbinds);
923
197k
    free(np->label);
924
197k
    free(np->hint);
925
197k
    free(np->units);
926
197k
    free(np->description);
927
197k
    free(np->reference);
928
197k
    free(np->defaultValue);
929
197k
    free(np->parent);
930
197k
    free(np->augments);
931
197k
    free(np->filename);
932
197k
    free(np);
933
197k
}
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.30k
{
1071
3.30k
    int             count;
1072
1073
849k
    for (count = 0; count < 256; count++) {
1074
846k
        switch (count) {
1075
3.30k
        case OBJID:
1076
3.30k
            translation_table[count] = TYPE_OBJID;
1077
3.30k
            break;
1078
3.30k
        case OCTETSTR:
1079
3.30k
            translation_table[count] = TYPE_OCTETSTR;
1080
3.30k
            break;
1081
3.30k
        case INTEGER:
1082
3.30k
            translation_table[count] = TYPE_INTEGER;
1083
3.30k
            break;
1084
3.30k
        case NETADDR:
1085
3.30k
            translation_table[count] = TYPE_NETADDR;
1086
3.30k
            break;
1087
3.30k
        case IPADDR:
1088
3.30k
            translation_table[count] = TYPE_IPADDR;
1089
3.30k
            break;
1090
3.30k
        case COUNTER:
1091
3.30k
            translation_table[count] = TYPE_COUNTER;
1092
3.30k
            break;
1093
3.30k
        case GAUGE:
1094
3.30k
            translation_table[count] = TYPE_GAUGE;
1095
3.30k
            break;
1096
3.30k
        case TIMETICKS:
1097
3.30k
            translation_table[count] = TYPE_TIMETICKS;
1098
3.30k
            break;
1099
3.30k
        case KW_OPAQUE:
1100
3.30k
            translation_table[count] = TYPE_OPAQUE;
1101
3.30k
            break;
1102
3.30k
        case NUL:
1103
3.30k
            translation_table[count] = TYPE_NULL;
1104
3.30k
            break;
1105
3.30k
        case COUNTER64:
1106
3.30k
            translation_table[count] = TYPE_COUNTER64;
1107
3.30k
            break;
1108
3.30k
        case BITSTRING:
1109
3.30k
            translation_table[count] = TYPE_BITSTRING;
1110
3.30k
            break;
1111
3.30k
        case NSAPADDRESS:
1112
3.30k
            translation_table[count] = TYPE_NSAPADDRESS;
1113
3.30k
            break;
1114
3.30k
        case INTEGER32:
1115
3.30k
            translation_table[count] = TYPE_INTEGER32;
1116
3.30k
            break;
1117
3.30k
        case UINTEGER32:
1118
3.30k
            translation_table[count] = TYPE_UINTEGER;
1119
3.30k
            break;
1120
3.30k
        case UNSIGNED32:
1121
3.30k
            translation_table[count] = TYPE_UNSIGNED32;
1122
3.30k
            break;
1123
3.30k
        case TRAPTYPE:
1124
3.30k
            translation_table[count] = TYPE_TRAPTYPE;
1125
3.30k
            break;
1126
3.30k
        case NOTIFTYPE:
1127
3.30k
            translation_table[count] = TYPE_NOTIFTYPE;
1128
3.30k
            break;
1129
3.30k
        case NOTIFGROUP:
1130
3.30k
            translation_table[count] = TYPE_NOTIFGROUP;
1131
3.30k
            break;
1132
3.30k
        case OBJGROUP:
1133
3.30k
            translation_table[count] = TYPE_OBJGROUP;
1134
3.30k
            break;
1135
3.30k
        case MODULEIDENTITY:
1136
3.30k
            translation_table[count] = TYPE_MODID;
1137
3.30k
            break;
1138
3.30k
        case OBJIDENTITY:
1139
3.30k
            translation_table[count] = TYPE_OBJIDENTITY;
1140
3.30k
            break;
1141
3.30k
        case AGENTCAP:
1142
3.30k
            translation_table[count] = TYPE_AGENTCAP;
1143
3.30k
            break;
1144
3.30k
        case COMPLIANCE:
1145
3.30k
            translation_table[count] = TYPE_MODCOMP;
1146
3.30k
            break;
1147
766k
        default:
1148
766k
            translation_table[count] = TYPE_OTHER;
1149
766k
            break;
1150
846k
        }
1151
846k
    }
1152
3.30k
}
1153
1154
static void
1155
init_tree_roots(void)
1156
3.30k
{
1157
3.30k
    struct tree    *tp, *lasttp;
1158
3.30k
    int             base_modid;
1159
3.30k
    int             hash;
1160
1161
3.30k
    base_modid = which_module("SNMPv2-SMI");
1162
3.30k
    if (base_modid == -1)
1163
3.30k
        base_modid = which_module("RFC1155-SMI");
1164
3.30k
    if (base_modid == -1)
1165
3.30k
        base_modid = which_module("RFC1213-MIB");
1166
1167
    /*
1168
     * build root node 
1169
     */
1170
3.30k
    tp = calloc(1, sizeof(struct tree));
1171
3.30k
    if (tp == NULL)
1172
0
        return;
1173
3.30k
    tp->label = strdup("joint-iso-ccitt");
1174
3.30k
    tp->modid = base_modid;
1175
3.30k
    tp->number_modules = 1;
1176
3.30k
    tp->module_list = &(tp->modid);
1177
3.30k
    tp->subid = 2;
1178
3.30k
    tp->tc_index = -1;
1179
3.30k
    set_function(tp);           /* from mib.c */
1180
3.30k
    hash = NBUCKET(name_hash(tp->label));
1181
3.30k
    tp->next = tbuckets[hash];
1182
3.30k
    tbuckets[hash] = tp;
1183
3.30k
    lasttp = tp;
1184
3.30k
    root_imports[0].label = strdup(tp->label);
1185
3.30k
    root_imports[0].modid = base_modid;
1186
1187
    /*
1188
     * build root node 
1189
     */
1190
3.30k
    tp = calloc(1, sizeof(struct tree));
1191
3.30k
    if (tp == NULL)
1192
0
        return;
1193
3.30k
    tp->next_peer = lasttp;
1194
3.30k
    tp->label = strdup("ccitt");
1195
3.30k
    tp->modid = base_modid;
1196
3.30k
    tp->number_modules = 1;
1197
3.30k
    tp->module_list = &(tp->modid);
1198
3.30k
    tp->subid = 0;
1199
3.30k
    tp->tc_index = -1;
1200
3.30k
    set_function(tp);           /* from mib.c */
1201
3.30k
    hash = NBUCKET(name_hash(tp->label));
1202
3.30k
    tp->next = tbuckets[hash];
1203
3.30k
    tbuckets[hash] = tp;
1204
3.30k
    lasttp = tp;
1205
3.30k
    root_imports[1].label = strdup(tp->label);
1206
3.30k
    root_imports[1].modid = base_modid;
1207
1208
    /*
1209
     * build root node 
1210
     */
1211
3.30k
    tp = calloc(1, sizeof(struct tree));
1212
3.30k
    if (tp == NULL)
1213
0
        return;
1214
3.30k
    tp->next_peer = lasttp;
1215
3.30k
    tp->label = strdup("iso");
1216
3.30k
    tp->modid = base_modid;
1217
3.30k
    tp->number_modules = 1;
1218
3.30k
    tp->module_list = &(tp->modid);
1219
3.30k
    tp->subid = 1;
1220
3.30k
    tp->tc_index = -1;
1221
3.30k
    set_function(tp);           /* from mib.c */
1222
3.30k
    hash = NBUCKET(name_hash(tp->label));
1223
3.30k
    tp->next = tbuckets[hash];
1224
3.30k
    tbuckets[hash] = tp;
1225
3.30k
    lasttp = tp;
1226
3.30k
    root_imports[2].label = strdup(tp->label);
1227
3.30k
    root_imports[2].modid = base_modid;
1228
1229
3.30k
    tree_head = tp;
1230
3.30k
}
1231
1232
#ifdef STRICT_MIB_PARSEING
1233
#define label_compare strcasecmp
1234
#else
1235
2.02G
#define label_compare strcmp
1236
#endif
1237
1238
1239
struct tree    *
1240
find_tree_node(const char *name, int modid)
1241
539k
{
1242
539k
    struct tree    *tp, *headtp;
1243
539k
    int             count, *int_p;
1244
1245
539k
    if (!name || !*name)
1246
26.4k
        return (NULL);
1247
1248
513k
    headtp = tbuckets[NBUCKET(name_hash(name))];
1249
92.9M
    for (tp = headtp; tp; tp = tp->next) {
1250
92.6M
        if (tp->label && !label_compare(tp->label, name)) {
1251
1252
2.65M
            if (modid == -1)    /* Any module */
1253
156k
                return (tp);
1254
1255
2.49M
            for (int_p = tp->module_list, count = 0;
1256
7.99M
                 count < tp->number_modules; ++count, ++int_p)
1257
5.55M
                if (*int_p == modid)
1258
56.7k
                    return (tp);
1259
2.49M
        }
1260
92.6M
    }
1261
1262
300k
    return (NULL);
1263
513k
}
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.44k
#define MAX_BAD 0xffffff
1271
1272
static          u_int
1273
compute_match(const char *search_base, const char *key)
1274
1.49k
{
1275
1.49k
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
1276
1.49k
    int             rc;
1277
1.49k
    regex_t         parsetree;
1278
1.49k
    regmatch_t      pmatch;
1279
1.49k
    rc = regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED);
1280
1.49k
    if (rc == 0)
1281
1.39k
        rc = regexec(&parsetree, search_base, 1, &pmatch, 0);
1282
1.49k
    regfree(&parsetree);
1283
1.49k
    if (rc == 0) {
1284
        /*
1285
         * found 
1286
         */
1287
83
        return pmatch.rm_so;
1288
83
    }
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.41k
    return MAX_BAD;
1324
1.49k
}
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
516
{
1342
516
    struct tree    *tp, *best_so_far = NULL, *retptr;
1343
516
    u_int           old_match = MAX_BAD, new_match = MAX_BAD;
1344
1345
516
    if (!pattrn || !*pattrn)
1346
4
        return (NULL);
1347
1348
512
    if (!tree_top)
1349
3
        tree_top = get_tree_head();
1350
1351
1.98k
    for (tp = tree_top; tp; tp = tp->next_peer) {
1352
1.49k
        if (!tp->reported && tp->label)
1353
1.49k
            new_match = compute_match(tp->label, pattrn);
1354
1.49k
        tp->reported = 1;
1355
1356
1.49k
        if (new_match < old_match) {
1357
68
            best_so_far = tp;
1358
68
            old_match = new_match;
1359
68
        }
1360
1.49k
        if (new_match == 0)
1361
27
            break;              /* this is the best result we can get */
1362
1.47k
        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.47k
    }
1373
512
    if (match)
1374
0
        *match = old_match;
1375
512
    return (best_so_far);
1376
516
}
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
9.61k
{
1385
9.61k
    struct tree    *child1, *child2, *previous;
1386
1387
20.8k
    for (child1 = tp1->child_list; child1;) {
1388
1389
11.2k
        for (child2 = tp2->child_list, previous = NULL;
1390
18.5k
             child2; previous = child2, child2 = child2->next_peer) {
1391
1392
14.0k
            if (child1->subid == child2->subid) {
1393
                /*
1394
                 * Found 'matching' children,
1395
                 *  so merge them
1396
                 */
1397
12.0k
                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
12.0k
                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
12.0k
                } else if (!label_compare(child1->label, child2->label)) {
1425
5.29k
                    if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1426
5.29k
             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
5.29k
                    continue;
1433
6.79k
                } else {
1434
                    /*
1435
                     * Two copies of the same node.
1436
                     * 'child2' adopts the children of 'child1'
1437
                     */
1438
1439
6.79k
                    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
6.79k
                        child2->child_list = child1->child_list;
1444
6.79k
                    for (previous = child1->child_list;
1445
11.9k
                         previous; previous = previous->next_peer)
1446
5.13k
                        previous->parent = child2;
1447
6.79k
                    child1->child_list = NULL;
1448
1449
6.79k
                    previous = child1;  /* Finished with 'child1' */
1450
6.79k
                    child1 = child1->next_peer;
1451
6.79k
                    free_tree(previous);
1452
6.79k
                    goto next;
1453
6.79k
                }
1454
12.0k
            }
1455
14.0k
        }
1456
        /*
1457
         * If no match, move 'child1' to 'tp2' child_list
1458
         */
1459
4.48k
        if (child1) {
1460
4.48k
            previous = child1;
1461
4.48k
            child1 = child1->next_peer;
1462
4.48k
            previous->parent = tp2;
1463
4.48k
            previous->next_peer = tp2->child_list;
1464
4.48k
            tp2->child_list = previous;
1465
4.48k
        }
1466
11.2k
      next:;
1467
11.2k
    }
1468
9.61k
}
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
344k
{
1478
344k
    struct tree    *tp, *anon_tp = NULL;
1479
344k
    struct tree    *xroot = root;
1480
344k
    struct node    *np, **headp;
1481
344k
    struct node    *oldnp = NULL, *child_list = NULL, *childp = NULL;
1482
344k
    int             hash;
1483
344k
    int            *int_p;
1484
1485
33.0M
    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
32.6M
        xroot = xroot->next_peer;
1491
32.6M
    }
1492
1493
344k
    tp = root;
1494
344k
    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
530k
    for (np = *headp; np; np = np->next) {
1500
186k
        if (!label_compare(tp->label, np->parent)) {
1501
            /*
1502
             * take this node out of the node list 
1503
             */
1504
107k
            if (oldnp == NULL) {
1505
90.5k
                *headp = np->next;      /* fix root of node list */
1506
90.5k
            } else {
1507
17.0k
                oldnp->next = np->next; /* link around this node */
1508
17.0k
            }
1509
107k
            if (child_list)
1510
34.8k
                childp->next = np;
1511
72.7k
            else
1512
72.7k
                child_list = np;
1513
107k
            childp = np;
1514
107k
        } else {
1515
78.5k
            oldnp = np;
1516
78.5k
        }
1517
1518
186k
    }
1519
344k
    if (childp)
1520
72.7k
        childp->next = NULL;
1521
    /*
1522
     * Take each element in the child list and place it into the tree.
1523
     */
1524
452k
    for (np = child_list; np; np = np->next) {
1525
107k
        struct tree    *otp = NULL;
1526
107k
        struct tree    *xxroot = xroot;
1527
107k
        anon_tp = NULL;
1528
107k
        tp = xroot->child_list;
1529
1530
107k
        if (np->subid == -1) {
1531
            /*
1532
             * name ::= { parent } 
1533
             */
1534
1.15k
            np->subid = xroot->subid;
1535
1.15k
            tp = xroot;
1536
1.15k
            xxroot = xroot->parent;
1537
1.15k
        }
1538
1539
943k
        while (tp) {
1540
910k
            if (tp->subid == np->subid)
1541
75.2k
                break;
1542
835k
            else {
1543
835k
                otp = tp;
1544
835k
                tp = tp->next_peer;
1545
835k
            }
1546
910k
        }
1547
107k
        if (tp) {
1548
75.2k
            if (!label_compare(tp->label, np->label)) {
1549
                /*
1550
                 * Update list of modules 
1551
                 */
1552
32.2k
                int_p = malloc((tp->number_modules + 1) * sizeof(int));
1553
32.2k
                if (int_p == NULL)
1554
0
                    return;
1555
32.2k
                memcpy(int_p, tp->module_list,
1556
32.2k
                       tp->number_modules * sizeof(int));
1557
32.2k
                int_p[tp->number_modules] = np->modid;
1558
32.2k
                if (tp->module_list != &tp->modid)
1559
24.5k
                    free(tp->module_list);
1560
32.2k
                ++tp->number_modules;
1561
32.2k
                tp->module_list = int_p;
1562
1563
32.2k
                if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
1564
32.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
32.2k
                do_subtree(tp, nodes);
1574
32.2k
                continue;
1575
32.2k
            }
1576
42.9k
            if (!strncmp(np->label, ANON, ANON_LEN) ||
1577
36.8k
                !strncmp(tp->label, ANON, ANON_LEN)) {
1578
9.84k
                anon_tp = tp;   /* Need to merge these two trees later */
1579
33.1k
            } else if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1580
33.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
42.9k
        }
1587
1588
75.3k
        tp = calloc(1, sizeof(struct tree));
1589
75.3k
        if (tp == NULL)
1590
0
            return;
1591
75.3k
        tp->parent = xxroot;
1592
75.3k
        tp->modid = np->modid;
1593
75.3k
        tp->number_modules = 1;
1594
75.3k
        tp->module_list = &(tp->modid);
1595
75.3k
        tree_from_node(tp, np);
1596
75.3k
        if (!otp && !xxroot) {
1597
284
          free(tp);
1598
284
          return;
1599
284
        }
1600
75.0k
        tp->next_peer = otp ? otp->next_peer : xxroot->child_list;
1601
75.0k
        if (otp)
1602
10.9k
            otp->next_peer = tp;
1603
64.1k
        else
1604
64.1k
            xxroot->child_list = tp;
1605
75.0k
        hash = NBUCKET(name_hash(tp->label));
1606
75.0k
        tp->next = tbuckets[hash];
1607
75.0k
        tbuckets[hash] = tp;
1608
75.0k
        do_subtree(tp, nodes);
1609
1610
75.0k
        if (anon_tp) {
1611
9.84k
            if (!strncmp(tp->label, ANON, ANON_LEN)) {
1612
                /*
1613
                 * The new node is anonymous,
1614
                 *  so merge it with the existing one.
1615
                 */
1616
6.08k
                merge_anon_children(tp, anon_tp);
1617
1618
                /*
1619
                 * unlink and destroy tp 
1620
                 */
1621
6.08k
                unlink_tree(tp);
1622
6.08k
                free_tree(tp);
1623
6.08k
            } else if (!strncmp(anon_tp->label, ANON, ANON_LEN)) {
1624
3.53k
                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.53k
                merge_anon_children(anon_tp, tp);
1631
1632
                /*
1633
                 * unlink anon_tp from the hash 
1634
                 */
1635
3.53k
                unlink_tbucket(anon_tp);
1636
1637
                /*
1638
                 * get rid of old contents of anon_tp 
1639
                 */
1640
3.53k
                free_partial_tree(anon_tp, FALSE);
1641
1642
                /*
1643
                 * put in the current information 
1644
                 */
1645
3.53k
                anon_tp->label = tp->label;
1646
3.53k
                anon_tp->child_list = tp->child_list;
1647
3.53k
                anon_tp->modid = tp->modid;
1648
3.53k
                anon_tp->tc_index = tp->tc_index;
1649
3.53k
                anon_tp->type = tp->type;
1650
3.53k
                anon_tp->enums = tp->enums;
1651
3.53k
                anon_tp->indexes = tp->indexes;
1652
3.53k
                anon_tp->augments = tp->augments;
1653
3.53k
                anon_tp->varbinds = tp->varbinds;
1654
3.53k
                anon_tp->ranges = tp->ranges;
1655
3.53k
                anon_tp->hint = tp->hint;
1656
3.53k
                anon_tp->units = tp->units;
1657
3.53k
                anon_tp->description = tp->description;
1658
3.53k
                anon_tp->reference = tp->reference;
1659
3.53k
                anon_tp->defaultValue = tp->defaultValue;
1660
3.53k
                anon_tp->parent = tp->parent;
1661
1662
3.53k
                set_function(anon_tp);
1663
1664
                /*
1665
                 * update parent pointer in moved children 
1666
                 */
1667
3.53k
                ntp = anon_tp->child_list;
1668
8.01k
                while (ntp) {
1669
4.48k
                    ntp->parent = anon_tp;
1670
4.48k
                    ntp = ntp->next_peer;
1671
4.48k
                }
1672
1673
                /*
1674
                 * hash in anon_tp in its new place 
1675
                 */
1676
3.53k
                hash = NBUCKET(name_hash(anon_tp->label));
1677
3.53k
                anon_tp->next = tbuckets[hash];
1678
3.53k
                tbuckets[hash] = anon_tp;
1679
1680
                /*
1681
                 * unlink and destroy tp 
1682
                 */
1683
3.53k
                unlink_tbucket(tp);
1684
3.53k
                unlink_tree(tp);
1685
3.53k
                free(tp);
1686
3.53k
            } else {
1687
                /*
1688
                 * Uh?  One of these two should have been anonymous! 
1689
                 */
1690
237
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1691
237
               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
237
            }
1697
9.84k
            anon_tp = NULL;
1698
9.84k
        }
1699
75.0k
    }
1700
    /*
1701
     * free all nodes that were copied into tree 
1702
     */
1703
344k
    oldnp = NULL;
1704
451k
    for (np = child_list; np; np = np->next) {
1705
107k
        if (oldnp)
1706
34.8k
            free_node(oldnp);
1707
107k
        oldnp = np;
1708
107k
    }
1709
344k
    if (oldnp)
1710
72.4k
        free_node(oldnp);
1711
344k
}
1712
1713
static void
1714
do_linkup(struct module *mp, struct node *np)
1715
8.94k
{
1716
8.94k
    struct module_import *mip;
1717
8.94k
    struct node    *onp, *oldp, *newp;
1718
8.94k
    struct tree    *tp;
1719
8.94k
    int             i, more;
1720
    /*
1721
     * All modules implicitly import
1722
     *   the roots of the tree
1723
     */
1724
8.94k
    if (snmp_get_do_debugging() > 1)
1725
0
        dump_module_list();
1726
8.94k
    DEBUGMSGTL(("parse-mibs", "Processing IMPORTS for module %d %s\n",
1727
8.94k
                mp->modid, mp->name));
1728
8.94k
    if (mp->no_imports == 0) {
1729
918
        mp->no_imports = NUMBER_OF_ROOT_NODES;
1730
918
        mp->imports = root_imports;
1731
918
    }
1732
1733
    /*
1734
     * Build the tree
1735
     */
1736
8.94k
    init_node_hash(np);
1737
660k
    for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
1738
651k
        char            modbuf[256];
1739
651k
        DEBUGMSGTL(("parse-mibs", "  Processing import: %s\n",
1740
651k
                    mip->label));
1741
651k
        if (get_tc_index(mip->label, mip->modid) != -1)
1742
245k
            continue;
1743
405k
        tp = find_tree_node(mip->label, mip->modid);
1744
405k
        if (!tp) {
1745
193k
      if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS))
1746
398
                snmp_log(LOG_WARNING,
1747
398
                         "Did not find '%s' in module %s (%s)\n",
1748
398
                         mip->label, module_name(mip->modid, modbuf),
1749
398
                         File);
1750
193k
            continue;
1751
193k
        }
1752
211k
        do_subtree(tp, &np);
1753
211k
    }
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
8.94k
    if (!np)
1762
566
        return;
1763
33.5k
    for (tp = tree_head; tp; tp = tp->next_peer)
1764
25.1k
        do_subtree(tp, &np);
1765
8.37k
    if (!np)
1766
0
        return;
1767
1768
    /*
1769
     * quietly move all internal references to the orphan list 
1770
     */
1771
8.37k
    oldp = orphan_nodes;
1772
9.29k
    do {
1773
1.19M
        for (i = 0; i < NHASHSIZE; i++)
1774
3.21M
            for (onp = nbuckets[i]; onp; onp = onp->next) {
1775
2.02M
                struct node    *op = NULL;
1776
2.02M
                int             hash = NBUCKET(name_hash(onp->label));
1777
2.02M
                np = nbuckets[hash];
1778
2.12M
                while (np) {
1779
99.2k
                    if (label_compare(onp->label, np->parent)) {
1780
87.7k
                        op = np;
1781
87.7k
                        np = np->next;
1782
87.7k
                    } else {
1783
11.5k
                        if (op)
1784
859
                            op->next = np->next;
1785
10.6k
                        else
1786
10.6k
                            nbuckets[hash] = np->next;
1787
11.5k
      DEBUGMSGTL(("parse-mibs", "Moving %s to orphanage", np->label));
1788
11.5k
                        np->next = orphan_nodes;
1789
11.5k
                        orphan_nodes = np;
1790
11.5k
                        op = NULL;
1791
11.5k
                        np = nbuckets[hash];
1792
11.5k
                    }
1793
99.2k
                }
1794
2.02M
            }
1795
9.29k
        newp = orphan_nodes;
1796
9.29k
        more = 0;
1797
24.3k
        for (onp = orphan_nodes; onp != oldp; onp = onp->next) {
1798
15.0k
            struct node    *op = NULL;
1799
15.0k
            int             hash = NBUCKET(name_hash(onp->label));
1800
15.0k
            np = nbuckets[hash];
1801
21.0k
            while (np) {
1802
6.02k
                if (label_compare(onp->label, np->parent)) {
1803
2.52k
                    op = np;
1804
2.52k
                    np = np->next;
1805
3.49k
                } else {
1806
3.49k
                    if (op)
1807
238
                        op->next = np->next;
1808
3.25k
                    else
1809
3.25k
                        nbuckets[hash] = np->next;
1810
3.49k
                    np->next = orphan_nodes;
1811
3.49k
                    orphan_nodes = np;
1812
3.49k
                    op = NULL;
1813
3.49k
                    np = nbuckets[hash];
1814
3.49k
                    more = 1;
1815
3.49k
                }
1816
6.02k
            }
1817
15.0k
        }
1818
9.29k
        oldp = newp;
1819
9.29k
    } while (more);
1820
1821
    /*
1822
     * complain about left over nodes 
1823
     */
1824
87.3M
    for (np = orphan_nodes; np && np->next; np = np->next);     /* find the end of the orphan list */
1825
1.08M
    for (i = 0; i < NHASHSIZE; i++)
1826
1.07M
        if (nbuckets[i]) {
1827
4.56k
            if (orphan_nodes)
1828
4.55k
                onp = np->next = nbuckets[i];
1829
1
            else
1830
1
                onp = orphan_nodes = nbuckets[i];
1831
4.56k
            nbuckets[i] = NULL;
1832
11.1k
            while (onp) {
1833
6.57k
                snmp_log(LOG_WARNING,
1834
6.57k
                         "Cannot resolve OID in %s: %s ::= { %s %ld } at line %d in %s\n",
1835
6.57k
                         (mp->name ? mp->name : "<no module>"),
1836
6.57k
                         (onp->label ? onp->label : "<no label>"),
1837
6.57k
                         (onp->parent ? onp->parent : "<no parent>"),
1838
6.57k
                         onp->subid, onp->lineno, onp->filename);
1839
6.57k
                np = onp;
1840
6.57k
                onp = onp->next;
1841
6.57k
            }
1842
4.56k
        }
1843
8.37k
    return;
1844
8.37k
}
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
51.2k
{
1861
51.2k
    struct subid_s *id = id_arg;
1862
51.2k
    int             i, count, type;
1863
51.2k
    char            token[MAXTOKEN];
1864
1865
51.2k
    if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET) {
1866
1.52k
        print_error("Expected \"{\"", token, type);
1867
1.52k
        return 0;
1868
1.52k
    }
1869
49.7k
    type = get_token(fp, token, MAXTOKEN);
1870
314k
    for (count = 0; count < length; count++, id++) {
1871
314k
        id->label = NULL;
1872
314k
        id->modid = current_module;
1873
314k
        id->subid = -1;
1874
314k
        if (type == RIGHTBRACKET)
1875
48.4k
            return count;
1876
265k
        if (type == LABEL) {
1877
            /*
1878
             * this entry has a label 
1879
             */
1880
210k
            id->label = strdup(token);
1881
210k
            type = get_token(fp, token, MAXTOKEN);
1882
210k
            if (type == LEFTPAREN) {
1883
341
                type = get_token(fp, token, MAXTOKEN);
1884
341
                if (type == NUMBER) {
1885
229
                    id->subid = strtoul(token, NULL, 10);
1886
229
                    if ((type =
1887
229
                         get_token(fp, token, MAXTOKEN)) != RIGHTPAREN) {
1888
150
                        print_error("Expected a closing parenthesis",
1889
150
                                    token, type);
1890
150
                        goto free_labels;
1891
150
                    }
1892
229
                } else {
1893
112
                    print_error("Expected a number", token, type);
1894
112
                    goto free_labels;
1895
112
                }
1896
209k
            } else {
1897
209k
                continue;
1898
209k
            }
1899
210k
        } else if (type == NUMBER) {
1900
            /*
1901
             * this entry  has just an integer sub-identifier 
1902
             */
1903
54.8k
            id->subid = strtoul(token, NULL, 10);
1904
54.8k
        } else {
1905
850
            print_error("Expected label or number", token, type);
1906
850
            goto free_labels;
1907
850
        }
1908
54.8k
        type = get_token(fp, token, MAXTOKEN);
1909
54.8k
    }
1910
216
    print_error("Too long OID", token, type);
1911
216
    --count;
1912
1913
1.32k
free_labels:
1914
12.8k
    for (i = 0; i <= count; i++) {
1915
11.5k
        free(id_arg[i].label);
1916
11.5k
        id_arg[i].label = NULL;
1917
11.5k
    }
1918
1919
1.32k
    return 0;
1920
216
}
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
51.2k
{
1947
51.2k
    register int    count;
1948
51.2k
    register struct subid_s *op, *nop;
1949
51.2k
    int             length;
1950
51.2k
    struct subid_s  loid[32];
1951
51.2k
    struct node    *np, *root = NULL, *oldnp = NULL;
1952
51.2k
    struct tree    *tp;
1953
1954
51.2k
    if ((length = getoid(fp, loid, 32)) == 0) {
1955
2.86k
        print_error("Bad object identifier", NULL, CONTINUE);
1956
2.86k
        return NULL;
1957
2.86k
    }
1958
1959
    /*
1960
     * Handle numeric-only object identifiers,
1961
     *  by labeling the first sub-identifier
1962
     */
1963
48.3k
    op = loid;
1964
48.3k
    if (!op->label) {
1965
6.65k
        if (length == 1) {
1966
162
            print_error("Attempt to define a root oid", name, OBJECT);
1967
162
            return NULL;
1968
162
        }
1969
14.3k
        for (tp = tree_head; tp; tp = tp->next_peer)
1970
13.6k
            if ((int) tp->subid == op->subid) {
1971
5.79k
                op->label = strdup(tp->label);
1972
5.79k
                break;
1973
5.79k
            }
1974
6.49k
    }
1975
1976
    /*
1977
     * Handle  "label OBJECT-IDENTIFIER ::= { subid }"
1978
     */
1979
48.2k
    if (length == 1) {
1980
8.27k
        op = loid;
1981
8.27k
        np = alloc_node(op->modid);
1982
8.27k
        if (np == NULL)
1983
0
            return (NULL);
1984
8.27k
        np->subid = op->subid;
1985
8.27k
        np->label = strdup(name);
1986
8.27k
        np->parent = op->label;
1987
8.27k
        return np;
1988
8.27k
    }
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
245k
    for (count = 0, op = loid, nop = loid + 1; count < (length - 1);
1995
205k
         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
205k
        if (op->label && (nop->label || (nop->subid != -1))) {
2003
199k
            np = alloc_node(nop->modid);
2004
199k
            if (np == NULL)
2005
0
                goto err;
2006
199k
            if (root == NULL) {
2007
39.6k
                root = np;
2008
159k
            } else {
2009
159k
                netsnmp_assert(oldnp);
2010
159k
                oldnp->next = np;
2011
159k
            }
2012
199k
            oldnp = np;
2013
2014
199k
            np->parent = strdup(op->label);
2015
199k
            if (count == (length - 2)) {
2016
                /*
2017
                 * The name for this node is the label for this entry 
2018
                 */
2019
36.7k
                np->label = strdup(name);
2020
36.7k
                if (np->label == NULL)
2021
0
                    goto err;
2022
162k
            } else {
2023
162k
                if (!nop->label) {
2024
19.9k
                    if (asprintf(&nop->label, "%s%d", ANON, anonymous++) < 0)
2025
0
                        goto err;
2026
19.9k
                }
2027
162k
                np->label = strdup(nop->label);
2028
162k
            }
2029
199k
            if (nop->subid != -1)
2030
43.9k
                np->subid = nop->subid;
2031
155k
            else
2032
155k
                print_error("Warning: This entry is pretty silly",
2033
155k
                            np->label, CONTINUE);
2034
199k
        }                       /* end if(op->label... */
2035
205k
    }
2036
2037
39.9k
out:
2038
    /*
2039
     * free the loid array 
2040
     */
2041
285k
    for (count = 0, op = loid; count < length; count++, op++) {
2042
245k
        free(op->label);
2043
245k
        op->label = NULL;
2044
245k
    }
2045
2046
39.9k
    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
39.9k
}
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
11.0k
{
2062
11.0k
    int             i;
2063
11.0k
    struct tc      *tcp;
2064
2065
11.0k
    i = get_tc_index(descriptor, modid);
2066
11.0k
    if (tc_index)
2067
3.90k
        *tc_index = i;
2068
11.0k
    if (i != -1) {
2069
694
        tcp = &tclist[i];
2070
694
        if (ep) {
2071
426
            free_enums(ep);
2072
426
            *ep = copy_enums(tcp->enums);
2073
426
        }
2074
694
        if (rp) {
2075
426
            free_ranges(rp);
2076
426
            *rp = copy_ranges(tcp->ranges);
2077
426
        }
2078
694
        if (hint) {
2079
426
            if (*hint)
2080
0
                free(*hint);
2081
426
            *hint = (tcp->hint ? strdup(tcp->hint) : NULL);
2082
426
        }
2083
694
        return tcp->type;
2084
694
    }
2085
10.3k
    return LABEL;
2086
11.0k
}
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
662k
{
2095
662k
    int             i;
2096
662k
    struct tc      *tcp;
2097
662k
    struct module  *mp;
2098
662k
    struct module_import *mip;
2099
2100
    /*
2101
     * Check that the descriptor isn't imported
2102
     *  by searching the import list
2103
     */
2104
2105
4.54G
    for (mp = module_head; mp; mp = mp->next)
2106
4.54G
        if (mp->modid == modid)
2107
188k
            break;
2108
662k
    if (mp)
2109
18.2M
        for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
2110
18.2M
            if (!label_compare(mip->label, descriptor)) {
2111
                /*
2112
                 * Found it - so amend the module ID 
2113
                 */
2114
175k
                modid = mip->modid;
2115
175k
                break;
2116
175k
            }
2117
18.2M
        }
2118
2119
2120
1.58G
    for (i = 0, tcp = tclist; i < tc_alloc; i++, tcp++) {
2121
1.58G
        if (tcp->type == 0)
2122
415k
            break;
2123
1.58G
        if (!label_compare(descriptor, tcp->descriptor) &&
2124
8.05M
            ((modid == tcp->modid) || (modid == -1))) {
2125
246k
            return i;
2126
246k
        }
2127
1.58G
    }
2128
415k
    return -1;
2129
662k
}
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
2.53k
{
2166
2.53k
    register int    type;
2167
2.53k
    char            token[MAXTOKEN];
2168
2.53k
    struct enum_list *ep = NULL, **epp = &ep;
2169
2170
2.53k
    free_enums(retp);
2171
2172
19.0k
    while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
2173
18.9k
        if (type == RIGHTBRACKET)
2174
1.70k
            break;
2175
        /* some enums use "deprecated" to indicate a no longer value label */
2176
        /* (EG: IP-MIB's IpAddressStatusTC) */
2177
17.2k
        if (type == LABEL || type == DEPRECATED) {
2178
            /*
2179
             * this is an enumerated label 
2180
             */
2181
10.0k
            *epp = calloc(1, sizeof(struct enum_list));
2182
10.0k
            if (*epp == NULL)
2183
0
                return (NULL);
2184
            /*
2185
             * a reasonable approximation for the length 
2186
             */
2187
10.0k
            (*epp)->label = strdup(token);
2188
10.0k
            type = get_token(fp, token, MAXTOKEN);
2189
10.0k
            if (type != LEFTPAREN) {
2190
593
                print_error("Expected \"(\"", token, type);
2191
593
                goto err;
2192
593
            }
2193
9.43k
            type = get_token(fp, token, MAXTOKEN);
2194
9.43k
            if (type != NUMBER) {
2195
98
                print_error("Expected integer", token, type);
2196
98
                goto err;
2197
98
            }
2198
9.33k
            (*epp)->value = strtol(token, NULL, 10);
2199
9.33k
            (*epp)->lineno = mibLine;
2200
9.33k
            type = get_token(fp, token, MAXTOKEN);
2201
9.33k
            if (type != RIGHTPAREN) {
2202
83
                print_error("Expected \")\"", token, type);
2203
83
                goto err;
2204
9.25k
            } else {
2205
9.25k
                struct enum_list *op = ep;
2206
141k
                while (op != *epp) {
2207
133k
                    if (strcmp((*epp)->label, op->label) == 0) {
2208
666
                        snmp_log(LOG_ERR,
2209
666
                            "Duplicate enum label '%s' at line %d in %s. First at line %d\n",
2210
666
                            (*epp)->label, mibLine, File, op->lineno);
2211
666
                        erroneousMibs++;
2212
666
                        break;
2213
666
                    }
2214
132k
                    else if ((*epp)->value == op->value) {
2215
666
                        snmp_log(LOG_ERR,
2216
666
                            "Duplicate enum value '%d' at line %d in %s. First at line %d\n",
2217
666
                            (*epp)->value, mibLine, File, op->lineno);
2218
666
                        erroneousMibs++;
2219
666
                        break;
2220
666
                    }
2221
132k
                    op = op->next;
2222
132k
                }
2223
9.25k
            }
2224
9.25k
            epp = &(*epp)->next;
2225
9.25k
        }
2226
17.2k
    }
2227
1.75k
    if (type == ENDOFFILE) {
2228
58
        print_error("Expected \"}\"", token, type);
2229
58
        goto err;
2230
58
    }
2231
1.70k
    *retp = ep;
2232
1.70k
    return ep;
2233
2234
832
err:
2235
832
    free_enums(&ep);
2236
832
    return NULL;
2237
1.75k
}
2238
2239
static struct range_list *
2240
parse_ranges(FILE * fp, struct range_list **retp)
2241
5.54k
{
2242
5.54k
    int             low, high;
2243
5.54k
    char            nexttoken[MAXTOKEN];
2244
5.54k
    int             nexttype;
2245
5.54k
    struct range_list *rp = NULL, **rpp = &rp;
2246
5.54k
    int             size = 0, taken = 1;
2247
2248
5.54k
    free_ranges(retp);
2249
2250
5.54k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
2251
5.54k
    if (nexttype == SIZE) {
2252
2.28k
        size = 1;
2253
2.28k
        taken = 0;
2254
2.28k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2255
2.28k
        if (nexttype != LEFTPAREN)
2256
161
            print_error("Expected \"(\" after SIZE", nexttoken, nexttype);
2257
2.28k
    }
2258
2259
7.90k
    do {
2260
7.90k
        if (!taken)
2261
4.65k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2262
3.25k
        else
2263
3.25k
            taken = 0;
2264
7.90k
        high = low = strtoul(nexttoken, NULL, 10);
2265
7.90k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2266
7.90k
        if (nexttype == RANGE) {
2267
3.40k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2268
3.40k
            errno = 0;
2269
3.40k
            high = strtoul(nexttoken, NULL, 10);
2270
3.40k
            if ( errno == ERANGE ) {
2271
817
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
2272
817
                                       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
817
            }
2277
3.40k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2278
3.40k
        }
2279
7.90k
        *rpp = (struct range_list *) calloc(1, sizeof(struct range_list));
2280
7.90k
        if (*rpp == NULL)
2281
0
            break;
2282
7.90k
        (*rpp)->low = low;
2283
7.90k
        (*rpp)->high = high;
2284
7.90k
        rpp = &(*rpp)->next;
2285
2286
7.90k
    } while (nexttype == BAR);
2287
5.54k
    if (size) {
2288
2.28k
        if (nexttype != RIGHTPAREN)
2289
203
            print_error("Expected \")\" after SIZE", nexttoken, nexttype);
2290
2.28k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2291
2.28k
    }
2292
5.54k
    if (nexttype != RIGHTPAREN)
2293
611
        print_error("Expected \")\"", nexttoken, nexttype);
2294
2295
5.54k
    *retp = rp;
2296
5.54k
    return rp;
2297
5.54k
}
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
33.1k
{
2306
33.1k
    int             type, i;
2307
33.1k
    char            token[MAXTOKEN];
2308
33.1k
    char            quoted_string_buffer[MAXQUOTESTR];
2309
33.1k
    char           *hint = NULL;
2310
33.1k
    char           *descr = NULL;
2311
33.1k
    struct tc      *tcp;
2312
33.1k
    int             level;
2313
2314
33.1k
    type = get_token(fp, token, MAXTOKEN);
2315
33.1k
    if (type == SEQUENCE || type == CHOICE) {
2316
1.97k
        level = 0;
2317
806k
        while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
2318
806k
            if (type == LEFTBRACKET) {
2319
55.6k
                level++;
2320
751k
            } else if (type == RIGHTBRACKET && --level == 0) {
2321
1.89k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2322
1.89k
                return NULL;
2323
1.89k
            }
2324
806k
        }
2325
77
        print_error("Expected \"}\"", token, type);
2326
77
        return NULL;
2327
31.1k
    } else if (type == LEFTBRACKET) {
2328
12.8k
        struct node    *np;
2329
12.8k
        int             ch_next = '{';
2330
12.8k
        ungetc(ch_next, fp);
2331
12.8k
        np = parse_objectid(fp, name);
2332
12.8k
        if (np != NULL) {
2333
11.1k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2334
11.1k
            return np;
2335
11.1k
        }
2336
1.68k
        return NULL;
2337
18.3k
    } else if (type == LEFTSQBRACK) {
2338
5.14k
        int             size = 0;
2339
133k
        do {
2340
133k
            type = get_token(fp, token, MAXTOKEN);
2341
133k
        } while (type != ENDOFFILE && type != RIGHTSQBRACK);
2342
5.14k
        if (type != RIGHTSQBRACK) {
2343
52
            print_error("Expected \"]\"", token, type);
2344
52
            return NULL;
2345
52
        }
2346
5.09k
        type = get_token(fp, token, MAXTOKEN);
2347
5.09k
        if (type == IMPLICIT)
2348
2.45k
            type = get_token(fp, token, MAXTOKEN);
2349
5.09k
        *ntype = get_token(fp, ntoken, MAXTOKEN);
2350
5.09k
        if (*ntype == LEFTPAREN) {
2351
3.62k
            switch (type) {
2352
1.44k
            case OCTETSTR:
2353
1.44k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2354
1.44k
                if (*ntype != SIZE) {
2355
86
                    print_error("Expected SIZE", ntoken, *ntype);
2356
86
                    return NULL;
2357
86
                }
2358
1.36k
                size = 1;
2359
1.36k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2360
1.36k
                if (*ntype != LEFTPAREN) {
2361
669
                    print_error("Expected \"(\" after SIZE", ntoken,
2362
669
                                *ntype);
2363
669
                    return NULL;
2364
669
                }
2365
693
                NETSNMP_FALLTHROUGH;
2366
2.52k
            case INTEGER:
2367
2.52k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2368
5.60k
                do {
2369
5.60k
                    if (*ntype != NUMBER)
2370
3.17k
                        print_error("Expected NUMBER", ntoken, *ntype);
2371
5.60k
                    *ntype = get_token(fp, ntoken, MAXTOKEN);
2372
5.60k
                    if (*ntype == RANGE) {
2373
2.25k
                        *ntype = get_token(fp, ntoken, MAXTOKEN);
2374
2.25k
                        if (*ntype != NUMBER)
2375
821
                            print_error("Expected NUMBER", ntoken, *ntype);
2376
2.25k
                        *ntype = get_token(fp, ntoken, MAXTOKEN);
2377
2.25k
                    }
2378
5.60k
                } while (*ntype == BAR);
2379
2.52k
                if (*ntype != RIGHTPAREN) {
2380
365
                    print_error("Expected \")\"", ntoken, *ntype);
2381
365
                    return NULL;
2382
365
                }
2383
2.16k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2384
2.16k
                if (size) {
2385
689
                    if (*ntype != RIGHTPAREN) {
2386
298
                        print_error("Expected \")\" to terminate SIZE",
2387
298
                                    ntoken, *ntype);
2388
298
                        return NULL;
2389
298
                    }
2390
391
                    *ntype = get_token(fp, ntoken, MAXTOKEN);
2391
391
                }
2392
3.62k
            }
2393
3.62k
        }
2394
3.67k
        return NULL;
2395
13.1k
    } else {
2396
13.1k
        if (type == CONVENTION) {
2397
30.4k
            while (type != SYNTAX && type != ENDOFFILE) {
2398
30.0k
                if (type == DISPLAYHINT) {
2399
915
                    type = get_token(fp, token, MAXTOKEN);
2400
915
                    if (type != QUOTESTRING) {
2401
567
                        print_error("DISPLAY-HINT must be string", token,
2402
567
                                    type);
2403
567
                    } else {
2404
348
                        free(hint);
2405
348
                        hint = strdup(token);
2406
348
                    }
2407
29.1k
                } else if (type == DESCRIPTION &&
2408
332
                           netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2409
332
                                                  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
29.1k
                    type =
2420
29.1k
                        get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2421
30.0k
            }
2422
433
            type = get_token(fp, token, MAXTOKEN);
2423
433
            if (type == OBJECT) {
2424
133
                type = get_token(fp, token, MAXTOKEN);
2425
133
                if (type != IDENTIFIER) {
2426
92
                    print_error("Expected IDENTIFIER", token, type);
2427
92
                    goto err;
2428
92
                }
2429
41
                type = OBJID;
2430
41
            }
2431
12.7k
        } else if (type == OBJECT) {
2432
951
            type = get_token(fp, token, MAXTOKEN);
2433
951
            if (type != IDENTIFIER) {
2434
85
                print_error("Expected IDENTIFIER", token, type);
2435
85
                goto err;
2436
85
            }
2437
866
            type = OBJID;
2438
866
        }
2439
2440
13.0k
        if (type == LABEL) {
2441
7.13k
            type = get_tc(token, current_module, NULL, NULL, NULL, NULL);
2442
7.13k
        }
2443
2444
        /*
2445
         * textual convention 
2446
         */
2447
13.0k
        tcp = NULL;
2448
19.8M
        for (i = 0; i < tc_alloc; i++) {
2449
19.8M
            if (tclist[i].type == 0) {
2450
741k
                if (tcp == NULL)
2451
12.9k
                    tcp = &tclist[i];
2452
19.1M
            } else if (strcmp(name, tclist[i].descriptor) == 0 &&
2453
1.18M
                       tclist[i].modid == current_module) {
2454
371k
                snmp_log(LOG_ERR,
2455
371k
                         "Duplicate TEXTUAL-CONVENTION '%s' at line %d in %s. First at line %d\n",
2456
371k
                         name, mibLine, File, tclist[i].lineno);
2457
371k
                erroneousMibs++;
2458
371k
            }
2459
19.8M
        }
2460
2461
13.0k
        if (tcp == NULL) {
2462
47
            tclist = realloc(tclist, (tc_alloc + TC_INCR)*sizeof(struct tc));
2463
47
            memset(tclist+tc_alloc, 0, TC_INCR*sizeof(struct tc));
2464
47
            tcp = tclist + tc_alloc;
2465
47
            tc_alloc += TC_INCR;
2466
47
        }
2467
13.0k
        if (!(type & SYNTAX_MASK)) {
2468
7.79k
            print_error("Textual convention doesn't map to real type",
2469
7.79k
                        token, type);
2470
7.79k
            goto err;
2471
7.79k
        }
2472
5.21k
        tcp->modid = current_module;
2473
5.21k
        tcp->descriptor = strdup(name);
2474
5.21k
        tcp->hint = hint;
2475
5.21k
        tcp->description = descr;
2476
5.21k
        tcp->lineno = mibLine;
2477
5.21k
        tcp->type = type;
2478
5.21k
        *ntype = get_token(fp, ntoken, MAXTOKEN);
2479
5.21k
        if (*ntype == LEFTPAREN) {
2480
2.58k
            tcp->ranges = parse_ranges(fp, &tcp->ranges);
2481
2.58k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2482
2.63k
        } else if (*ntype == LEFTBRACKET) {
2483
            /*
2484
             * if there is an enumeration list, parse it 
2485
             */
2486
877
            tcp->enums = parse_enumlist(fp, &tcp->enums);
2487
877
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2488
877
        }
2489
5.21k
        return NULL;
2490
13.0k
    }
2491
2492
7.96k
err:
2493
7.96k
    SNMP_FREE(descr);
2494
7.96k
    SNMP_FREE(hint);
2495
7.96k
    return NULL;
2496
33.1k
}
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
11.8k
{
2506
11.8k
    register int    type;
2507
11.8k
    char            token[MAXTOKEN];
2508
11.8k
    char            nexttoken[MAXTOKEN];
2509
11.8k
    char            quoted_string_buffer[MAXQUOTESTR];
2510
11.8k
    int             nexttype, tctype;
2511
11.8k
    register struct node *np;
2512
2513
11.8k
    type = get_token(fp, token, MAXTOKEN);
2514
11.8k
    if (type != SYNTAX) {
2515
29
        print_error("Bad format for OBJECT-TYPE", token, type);
2516
29
        return NULL;
2517
29
    }
2518
11.8k
    np = alloc_node(current_module);
2519
11.8k
    if (np == NULL)
2520
0
        return (NULL);
2521
11.8k
    type = get_token(fp, token, MAXTOKEN);
2522
11.8k
    if (type == OBJECT) {
2523
511
        type = get_token(fp, token, MAXTOKEN);
2524
511
        if (type != IDENTIFIER) {
2525
8
            print_error("Expected IDENTIFIER", token, type);
2526
8
            free_node(np);
2527
8
            return NULL;
2528
8
        }
2529
503
        type = OBJID;
2530
503
    }
2531
11.8k
    if (type == LABEL) {
2532
3.90k
        int             tmp_index;
2533
3.90k
        tctype = get_tc(token, current_module, &tmp_index,
2534
3.90k
                        &np->enums, &np->ranges, &np->hint);
2535
3.90k
        if (tctype == LABEL &&
2536
3.48k
            netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
2537
3.48k
             NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
2538
0
            print_error("Warning: No known translation for type", token,
2539
0
                        type);
2540
0
        }
2541
3.90k
        type = tctype;
2542
3.90k
        np->tc_index = tmp_index;       /* store TC for later reference */
2543
3.90k
    }
2544
11.8k
    np->type = type;
2545
11.8k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
2546
11.8k
    switch (type) {
2547
540
    case SEQUENCE:
2548
540
        if (nexttype == OF) {
2549
521
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2550
521
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2551
2552
521
        }
2553
540
        break;
2554
1.45k
    case INTEGER:
2555
2.46k
    case INTEGER32:
2556
2.46k
    case UINTEGER32:
2557
3.43k
    case UNSIGNED32:
2558
4.69k
    case COUNTER:
2559
4.82k
    case GAUGE:
2560
4.96k
    case BITSTRING:
2561
8.44k
    case LABEL:
2562
8.44k
        if (nexttype == LEFTBRACKET) {
2563
            /*
2564
             * if there is an enumeration list, parse it 
2565
             */
2566
924
            np->enums = parse_enumlist(fp, &np->enums);
2567
924
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2568
7.51k
        } else if (nexttype == LEFTPAREN) {
2569
            /*
2570
             * if there is a range list, parse it 
2571
             */
2572
1.53k
            np->ranges = parse_ranges(fp, &np->ranges);
2573
1.53k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2574
1.53k
        }
2575
8.44k
        break;
2576
582
    case OCTETSTR:
2577
737
    case KW_OPAQUE:
2578
        /*
2579
         * parse any SIZE specification 
2580
         */
2581
737
        if (nexttype == LEFTPAREN) {
2582
142
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2583
142
            if (nexttype == SIZE) {
2584
133
                nexttype = get_token(fp, nexttoken, MAXTOKEN);
2585
133
                if (nexttype == LEFTPAREN) {
2586
128
                    np->ranges = parse_ranges(fp, &np->ranges);
2587
128
                    nexttype = get_token(fp, nexttoken, MAXTOKEN);      /* ) */
2588
128
                    if (nexttype == RIGHTPAREN) {
2589
118
                        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2590
118
                        break;
2591
118
                    }
2592
128
                }
2593
133
            }
2594
24
            print_error("Bad SIZE syntax", token, type);
2595
24
            free_node(np);
2596
24
            return NULL;
2597
142
        }
2598
595
        break;
2599
595
    case OBJID:
2600
958
    case NETADDR:
2601
1.16k
    case IPADDR:
2602
1.40k
    case TIMETICKS:
2603
1.89k
    case NUL:
2604
1.89k
    case NSAPADDRESS:
2605
2.07k
    case COUNTER64:
2606
2.07k
        break;
2607
10
    default:
2608
10
        print_error("Bad syntax", token, type);
2609
10
        free_node(np);
2610
10
        return NULL;
2611
11.8k
    }
2612
11.7k
    if (nexttype == UNITS) {
2613
1.01k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2614
1.01k
        if (type != QUOTESTRING) {
2615
10
            print_error("Bad UNITS", quoted_string_buffer, type);
2616
10
            free_node(np);
2617
10
            return NULL;
2618
10
        }
2619
1.00k
        np->units = strdup(quoted_string_buffer);
2620
1.00k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2621
1.00k
    }
2622
11.7k
    if (nexttype != ACCESS) {
2623
127
        print_error("Should be ACCESS", nexttoken, nexttype);
2624
127
        free_node(np);
2625
127
        return NULL;
2626
127
    }
2627
11.6k
    type = get_token(fp, token, MAXTOKEN);
2628
11.6k
    if (type != READONLY && type != READWRITE && type != WRITEONLY
2629
4.08k
        && type != NOACCESS && type != READCREATE && type != ACCNOTIFY) {
2630
32
        print_error("Bad ACCESS type", token, type);
2631
32
        free_node(np);
2632
32
        return NULL;
2633
32
    }
2634
11.6k
    np->access = type;
2635
11.6k
    type = get_token(fp, token, MAXTOKEN);
2636
11.6k
    if (type != STATUS) {
2637
29
        print_error("Should be STATUS", token, type);
2638
29
        free_node(np);
2639
29
        return NULL;
2640
29
    }
2641
11.5k
    type = get_token(fp, token, MAXTOKEN);
2642
11.5k
    if (type != MANDATORY && type != CURRENT && type != KW_OPTIONAL &&
2643
755
        type != OBSOLETE && type != DEPRECATED) {
2644
30
        print_error("Bad STATUS", token, type);
2645
30
        free_node(np);
2646
30
        return NULL;
2647
30
    }
2648
11.5k
    np->status = type;
2649
    /*
2650
     * Optional parts of the OBJECT-TYPE macro
2651
     */
2652
11.5k
    type = get_token(fp, token, MAXTOKEN);
2653
26.1k
    while (type != EQUALS && type != ENDOFFILE) {
2654
14.8k
        switch (type) {
2655
10.3k
        case DESCRIPTION:
2656
10.3k
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2657
2658
10.3k
            if (type != QUOTESTRING) {
2659
25
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2660
25
                free_node(np);
2661
25
                return NULL;
2662
25
            }
2663
10.3k
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2664
10.3k
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2665
0
                np->description = strdup(quoted_string_buffer);
2666
0
            }
2667
10.3k
            break;
2668
2669
172
        case REFERENCE:
2670
172
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2671
172
            if (type != QUOTESTRING) {
2672
7
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2673
7
                free_node(np);
2674
7
                return NULL;
2675
7
            }
2676
165
            np->reference = strdup(quoted_string_buffer);
2677
165
            break;
2678
2.10k
        case INDEX:
2679
2.10k
            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.10k
            np->indexes = getIndexes(fp, &np->indexes);
2686
2.10k
            if (np->indexes == NULL) {
2687
11
                print_error("Bad INDEX list", token, type);
2688
11
                free_node(np);
2689
11
                return NULL;
2690
11
            }
2691
2.09k
            break;
2692
2.09k
        case AUGMENTS:
2693
246
            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
245
            np->indexes = getIndexes(fp, &np->indexes);
2700
245
            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
244
            np->augments = strdup(np->indexes->ilabel);
2706
244
            free_indexes(&np->indexes);
2707
244
            break;
2708
1.86k
        case DEFVAL:
2709
            /*
2710
             * Mark's defVal section 
2711
             */
2712
1.86k
            type = get_token(fp, quoted_string_buffer,
2713
1.86k
                             sizeof(quoted_string_buffer));
2714
1.86k
            if (type != LEFTBRACKET) {
2715
10
                print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2716
10
                            type);
2717
10
                free_node(np);
2718
10
                return NULL;
2719
10
            }
2720
2721
1.85k
            {
2722
1.85k
                int             level = 1;
2723
1.85k
                char            defbuf[512];
2724
2725
1.85k
                defbuf[0] = 0;
2726
76.4k
                while (1) {
2727
76.4k
                    type = get_token(fp, quoted_string_buffer,
2728
76.4k
                                     sizeof(quoted_string_buffer));
2729
76.4k
                    if ((type == RIGHTBRACKET && --level == 0)
2730
74.6k
                        || type == ENDOFFILE)
2731
1.85k
                        break;
2732
74.5k
                    else if (type == LEFTBRACKET)
2733
47.3k
                        level++;
2734
74.5k
                    if (type == QUOTESTRING)
2735
236
                        strlcat(defbuf, "\\\"", sizeof(defbuf));
2736
74.5k
                    strlcat(defbuf, quoted_string_buffer, sizeof(defbuf));
2737
74.5k
                    if (type == QUOTESTRING)
2738
236
                        strlcat(defbuf, "\\\"", sizeof(defbuf));
2739
74.5k
                    strlcat(defbuf, " ", sizeof(defbuf));
2740
74.5k
                }
2741
2742
1.85k
                if (type != RIGHTBRACKET) {
2743
67
                    print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2744
67
                                type);
2745
67
                    free_node(np);
2746
67
                    return NULL;
2747
67
                }
2748
2749
                /*
2750
                 * Ensure strlen(defbuf) is above zero
2751
                 */
2752
1.78k
                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
1.78k
                defbuf[strlen(defbuf) - 1] = 0;
2759
1.78k
                np->defaultValue = strdup(defbuf);
2760
1.78k
            }
2761
2762
0
            break;
2763
2764
45
        case NUM_ENTRIES:
2765
45
            if (tossObjectIdentifier(fp) != OBJID) {
2766
38
                print_error("Bad Object Identifier", token, type);
2767
38
                free_node(np);
2768
38
                return NULL;
2769
38
            }
2770
7
            break;
2771
2772
62
        default:
2773
62
            print_error("Bad format of optional clauses", token, type);
2774
62
            free_node(np);
2775
62
            return NULL;
2776
2777
14.8k
        }
2778
14.5k
        type = get_token(fp, token, MAXTOKEN);
2779
14.5k
    }
2780
11.3k
    if (type != EQUALS) {
2781
65
        print_error("Bad format", token, type);
2782
65
        free_node(np);
2783
65
        return NULL;
2784
65
    }
2785
11.2k
    return merge_parse_objectid(np, fp, name);
2786
11.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
3.62k
{
2798
3.62k
    int             type;
2799
3.62k
    char            token[MAXTOKEN];
2800
3.62k
    char            quoted_string_buffer[MAXQUOTESTR];
2801
3.62k
    struct node    *np;
2802
2803
3.62k
    np = alloc_node(current_module);
2804
3.62k
    if (np == NULL)
2805
0
        return (NULL);
2806
3.62k
    type = get_token(fp, token, MAXTOKEN);
2807
3.62k
    if (type == what) {
2808
2.10k
        type = get_token(fp, token, MAXTOKEN);
2809
2.10k
        if (type != LEFTBRACKET) {
2810
563
            print_error("Expected \"{\"", token, type);
2811
563
            goto skip;
2812
563
        }
2813
18.3k
        do {
2814
18.3k
            struct objgroup *o;
2815
18.3k
            type = get_token(fp, token, MAXTOKEN);
2816
18.3k
            if (type != LABEL) {
2817
104
                print_error("Bad identifier", token, type);
2818
104
                goto skip;
2819
104
            }
2820
18.2k
            o = (struct objgroup *) malloc(sizeof(struct objgroup));
2821
18.2k
            if (!o) {
2822
0
                print_error("Resource failure", token, type);
2823
0
                goto skip;
2824
0
            }
2825
18.2k
            o->line = mibLine;
2826
18.2k
            o->name = strdup(token);
2827
18.2k
            o->next = *ol;
2828
18.2k
            *ol = o;
2829
18.2k
            type = get_token(fp, token, MAXTOKEN);
2830
18.2k
        } while (type == COMMA);
2831
1.43k
        if (type != RIGHTBRACKET) {
2832
1.20k
            print_error("Expected \"}\" after list", token, type);
2833
1.20k
            goto skip;
2834
1.20k
        }
2835
230
        type = get_token(fp, token, type);
2836
230
    }
2837
1.75k
    if (type != STATUS) {
2838
524
        print_error("Expected STATUS", token, type);
2839
524
        goto skip;
2840
524
    }
2841
1.23k
    type = get_token(fp, token, MAXTOKEN);
2842
1.23k
    if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
2843
246
        print_error("Bad STATUS value", token, type);
2844
246
        goto skip;
2845
246
    }
2846
984
    type = get_token(fp, token, MAXTOKEN);
2847
984
    if (type != DESCRIPTION) {
2848
407
        print_error("Expected DESCRIPTION", token, type);
2849
407
        goto skip;
2850
407
    }
2851
577
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2852
577
    if (type != QUOTESTRING) {
2853
7
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2854
7
        free_node(np);
2855
7
        return NULL;
2856
7
    }
2857
570
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2858
570
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2859
0
        np->description = strdup(quoted_string_buffer);
2860
0
    }
2861
570
    type = get_token(fp, token, MAXTOKEN);
2862
570
    if (type == REFERENCE) {
2863
202
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2864
202
        if (type != QUOTESTRING) {
2865
1
            print_error("Bad REFERENCE", quoted_string_buffer, type);
2866
1
            free_node(np);
2867
1
            return NULL;
2868
1
        }
2869
201
        np->reference = strdup(quoted_string_buffer);
2870
201
        type = get_token(fp, token, MAXTOKEN);
2871
201
    }
2872
569
    if (type != EQUALS)
2873
245
        print_error("Expected \"::=\"", token, type);
2874
3.61k
  skip:
2875
100k
    while (type != EQUALS && type != ENDOFFILE)
2876
96.6k
        type = get_token(fp, token, MAXTOKEN);
2877
2878
3.61k
    return merge_parse_objectid(np, fp, name);
2879
569
}
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
1.70k
{
2888
1.70k
    register int    type;
2889
1.70k
    char            token[MAXTOKEN];
2890
1.70k
    char            quoted_string_buffer[MAXQUOTESTR];
2891
1.70k
    register struct node *np;
2892
2893
1.70k
    np = alloc_node(current_module);
2894
1.70k
    if (np == NULL)
2895
0
        return (NULL);
2896
1.70k
    type = get_token(fp, token, MAXTOKEN);
2897
132k
    while (type != EQUALS && type != ENDOFFILE) {
2898
130k
        switch (type) {
2899
282
        case DESCRIPTION:
2900
282
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2901
282
            if (type != QUOTESTRING) {
2902
9
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2903
9
                goto free_node;
2904
9
            }
2905
273
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2906
273
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2907
0
                np->description = strdup(quoted_string_buffer);
2908
0
            }
2909
273
            break;
2910
269
        case REFERENCE:
2911
269
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2912
269
            if (type != QUOTESTRING) {
2913
18
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2914
18
                goto free_node;
2915
18
            }
2916
251
            free(np->reference);
2917
251
            np->reference = strdup(quoted_string_buffer);
2918
251
            break;
2919
1.62k
        case OBJECTS:
2920
1.62k
            np->varbinds = getVarbinds(fp, &np->varbinds);
2921
1.62k
            if (!np->varbinds) {
2922
14
                print_error("Bad OBJECTS list", token, type);
2923
14
                goto free_node;
2924
14
            }
2925
1.61k
            break;
2926
128k
        default:
2927
            /*
2928
             * NOTHING 
2929
             */
2930
128k
            break;
2931
130k
        }
2932
130k
        type = get_token(fp, token, MAXTOKEN);
2933
130k
    }
2934
1.66k
    return merge_parse_objectid(np, fp, name);
2935
2936
41
free_node:
2937
41
    free_node(np);
2938
41
    return NULL;
2939
1.70k
}
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
577
{
2948
577
    register int    type;
2949
577
    char            token[MAXTOKEN];
2950
577
    char            quoted_string_buffer[MAXQUOTESTR];
2951
577
    register struct node *np;
2952
2953
577
    np = alloc_node(current_module);
2954
577
    if (np == NULL)
2955
0
        return (NULL);
2956
577
    type = get_token(fp, token, MAXTOKEN);
2957
13.2k
    while (type != EQUALS && type != ENDOFFILE) {
2958
12.7k
        switch (type) {
2959
223
        case DESCRIPTION:
2960
223
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2961
223
            if (type != QUOTESTRING) {
2962
12
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2963
12
                goto free_node;
2964
12
            }
2965
211
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2966
211
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2967
0
                np->description = strdup(quoted_string_buffer);
2968
0
            }
2969
211
            break;
2970
219
        case REFERENCE:
2971
            /* I'm not sure REFERENCEs are legal in smiv1 traps??? */
2972
219
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2973
219
            if (type != QUOTESTRING) {
2974
14
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2975
14
                goto free_node;
2976
14
            }
2977
205
            np->reference = strdup(quoted_string_buffer);
2978
205
            break;
2979
670
        case ENTERPRISE:
2980
670
            type = get_token(fp, token, MAXTOKEN);
2981
670
            if (type == LEFTBRACKET) {
2982
197
                type = get_token(fp, token, MAXTOKEN);
2983
197
                if (type != LABEL) {
2984
2
                    print_error("Bad Trap Format", token, type);
2985
2
                    goto free_node;
2986
2
                }
2987
195
                np->parent = strdup(token);
2988
                /*
2989
                 * Get right bracket 
2990
                 */
2991
195
                type = get_token(fp, token, MAXTOKEN);
2992
473
            } else if (type == LABEL) {
2993
463
                np->parent = strdup(token);
2994
463
            } else {
2995
10
                goto free_node;
2996
10
            }
2997
658
            break;
2998
658
        case VARIABLES:
2999
166
            np->varbinds = getVarbinds(fp, &np->varbinds);
3000
166
            if (!np->varbinds) {
3001
11
                print_error("Bad VARIABLES list", token, type);
3002
11
                goto free_node;
3003
11
            }
3004
155
            break;
3005
11.4k
        default:
3006
            /*
3007
             * NOTHING 
3008
             */
3009
11.4k
            break;
3010
12.7k
        }
3011
12.6k
        type = get_token(fp, token, MAXTOKEN);
3012
12.6k
    }
3013
528
    type = get_token(fp, token, MAXTOKEN);
3014
3015
528
    np->label = strdup(name);
3016
3017
528
    if (type != NUMBER) {
3018
117
        print_error("Expected a Number", token, type);
3019
117
        goto free_node;
3020
117
    }
3021
411
    np->subid = strtoul(token, NULL, 10);
3022
411
    np->next = alloc_node(current_module);
3023
411
    if (np->next == NULL)
3024
0
        goto free_node;
3025
3026
    /* Catch the syntax error */
3027
411
    if (np->parent == NULL) {
3028
5
        gMibError = MODULE_SYNTAX_ERROR;
3029
5
        goto free_next_node;
3030
5
    }
3031
3032
406
    np->next->parent = np->parent;
3033
406
    np->parent = NULL;
3034
406
    if (asprintf(&np->parent, "%s#", np->next->parent) < 0)
3035
0
        goto free_next_node;
3036
406
    np->next->label = strdup(np->parent);
3037
406
    return np;
3038
3039
5
free_next_node:
3040
5
    free_node(np->next);
3041
3042
171
free_node:
3043
171
    free_node(np);
3044
171
    return NULL;
3045
5
}
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
4.30k
{
3055
4.30k
    int             type, nexttype;
3056
4.30k
    struct node    *np = alloc_node(current_module);
3057
4.30k
    char            nexttoken[MAXTOKEN];
3058
3059
4.30k
    if (!np)
3060
0
  return 0;
3061
3062
4.30k
    type = get_token(fp, token, maxtoken);
3063
4.30k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
3064
4.30k
    switch (type) {
3065
722
    case INTEGER:
3066
1.46k
    case INTEGER32:
3067
1.52k
    case UINTEGER32:
3068
1.85k
    case UNSIGNED32:
3069
2.05k
    case COUNTER:
3070
2.12k
    case GAUGE:
3071
2.28k
    case BITSTRING:
3072
2.67k
    case LABEL:
3073
2.67k
        if (nexttype == LEFTBRACKET) {
3074
            /*
3075
             * if there is an enumeration list, parse it 
3076
             */
3077
731
            np->enums = parse_enumlist(fp, &np->enums);
3078
731
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3079
1.94k
        } else if (nexttype == LEFTPAREN) {
3080
            /*
3081
             * if there is a range list, parse it 
3082
             */
3083
1.20k
            np->ranges = parse_ranges(fp, &np->ranges);
3084
1.20k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3085
1.20k
        }
3086
2.67k
        break;
3087
613
    case OCTETSTR:
3088
698
    case KW_OPAQUE:
3089
        /*
3090
         * parse any SIZE specification 
3091
         */
3092
698
        if (nexttype == LEFTPAREN) {
3093
572
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3094
572
            if (nexttype == SIZE) {
3095
512
                nexttype = get_token(fp, nexttoken, MAXTOKEN);
3096
512
                if (nexttype == LEFTPAREN) {
3097
90
                    np->ranges = parse_ranges(fp, &np->ranges);
3098
90
                    nexttype = get_token(fp, nexttoken, MAXTOKEN);      /* ) */
3099
90
                    if (nexttype == RIGHTPAREN) {
3100
73
                        nexttype = get_token(fp, nexttoken, MAXTOKEN);
3101
73
                        break;
3102
73
                    }
3103
90
                }
3104
512
            }
3105
499
            print_error("Bad SIZE syntax", token, type);
3106
499
            free_node(np);
3107
499
            return nexttype;
3108
572
        }
3109
126
        break;
3110
126
    case OBJID:
3111
85
    case NETADDR:
3112
151
    case IPADDR:
3113
161
    case TIMETICKS:
3114
239
    case NUL:
3115
612
    case NSAPADDRESS:
3116
833
    case COUNTER64:
3117
833
        break;
3118
97
    default:
3119
97
        print_error("Bad syntax", token, type);
3120
97
        free_node(np);
3121
97
        return nexttype;
3122
4.30k
    }
3123
3.70k
    free_node(np);
3124
3.70k
    return nexttype;
3125
4.30k
}
3126
3127
static int
3128
compliance_lookup(const char *name, int modid)
3129
15.5k
{
3130
15.5k
    struct objgroup *op;
3131
3132
15.5k
    if (modid != -1)
3133
1.55k
        return find_tree_node(name, modid) != NULL;
3134
3135
13.9k
    op = malloc(sizeof(struct objgroup));
3136
13.9k
    if (!op)
3137
0
        return 0;
3138
3139
13.9k
    op->next = objgroups;
3140
13.9k
    op->name = strdup(name);
3141
13.9k
    if (!op->name) {
3142
0
        free(op);
3143
0
        return 0;
3144
0
    }
3145
13.9k
    op->line = mibLine;
3146
13.9k
    objgroups = op;
3147
13.9k
    return 1;
3148
13.9k
}
3149
3150
static struct node *
3151
parse_compliance(FILE * fp, char *name)
3152
11.3k
{
3153
11.3k
    int             type;
3154
11.3k
    char            token[MAXTOKEN];
3155
11.3k
    char            quoted_string_buffer[MAXQUOTESTR];
3156
11.3k
    struct node    *np;
3157
3158
11.3k
    np = alloc_node(current_module);
3159
11.3k
    if (np == NULL)
3160
0
        return (NULL);
3161
11.3k
    type = get_token(fp, token, MAXTOKEN);
3162
11.3k
    if (type != STATUS) {
3163
1.05k
        print_error("Expected STATUS", token, type);
3164
1.05k
        goto skip;
3165
1.05k
    }
3166
10.2k
    type = get_token(fp, token, MAXTOKEN);
3167
10.2k
    if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
3168
821
        print_error("Bad STATUS", token, type);
3169
821
        goto skip;
3170
821
    }
3171
9.43k
    type = get_token(fp, token, MAXTOKEN);
3172
9.43k
    if (type != DESCRIPTION) {
3173
1.21k
        print_error("Expected DESCRIPTION", token, type);
3174
1.21k
        goto skip;
3175
1.21k
    }
3176
8.22k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3177
8.22k
    if (type != QUOTESTRING) {
3178
607
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3179
607
        goto skip;
3180
607
    }
3181
7.61k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3182
7.61k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS))
3183
0
        np->description = strdup(quoted_string_buffer);
3184
7.61k
    type = get_token(fp, token, MAXTOKEN);
3185
7.61k
    if (type == REFERENCE) {
3186
341
        type = get_token(fp, quoted_string_buffer,
3187
341
                         sizeof(quoted_string_buffer));
3188
341
        if (type != QUOTESTRING) {
3189
266
            print_error("Bad REFERENCE", quoted_string_buffer, type);
3190
266
            goto skip;
3191
266
        }
3192
75
        np->reference = strdup(quoted_string_buffer);
3193
75
        type = get_token(fp, token, MAXTOKEN);
3194
75
    }
3195
7.35k
    if (type != MODULE) {
3196
444
        print_error("Expected MODULE", token, type);
3197
444
        goto skip;
3198
444
    }
3199
9.56k
    while (type == MODULE) {
3200
8.40k
        int             modid = -1;
3201
8.40k
        char            modname[MAXTOKEN];
3202
8.40k
        type = get_token(fp, token, MAXTOKEN);
3203
8.40k
        if (type == LABEL
3204
2.10k
            && strcmp(token, module_name(current_module, modname))) {
3205
1.89k
            modid = read_module_internal(token);
3206
1.89k
            if (modid != MODULE_LOADED_OK
3207
1.89k
                && modid != MODULE_ALREADY_LOADED) {
3208
268
                print_error("Unknown module", token, type);
3209
268
                goto skip;
3210
268
            }
3211
1.62k
            modid = which_module(token);
3212
1.62k
            type = get_token(fp, token, MAXTOKEN);
3213
1.62k
        }
3214
8.14k
        if (type == MANDATORYGROUPS) {
3215
3.35k
            type = get_token(fp, token, MAXTOKEN);
3216
3.35k
            if (type != LEFTBRACKET) {
3217
79
                print_error("Expected \"{\"", token, type);
3218
79
                goto skip;
3219
79
            }
3220
7.55k
            do {
3221
7.55k
                type = get_token(fp, token, MAXTOKEN);
3222
7.55k
                if (type != LABEL) {
3223
112
                    print_error("Bad group name", token, type);
3224
112
                    goto skip;
3225
112
                }
3226
7.44k
                if (!compliance_lookup(token, modid))
3227
280
                    print_error("Unknown group", token, type);
3228
7.44k
                type = get_token(fp, token, MAXTOKEN);
3229
7.44k
            } while (type == COMMA);
3230
3.16k
            if (type != RIGHTBRACKET) {
3231
422
                print_error("Expected \"}\"", token, type);
3232
422
                goto skip;
3233
422
            }
3234
2.74k
            type = get_token(fp, token, MAXTOKEN);
3235
2.74k
        }
3236
11.1k
        while (type == GROUP || type == OBJECT) {
3237
8.49k
            if (type == GROUP) {
3238
1.46k
                type = get_token(fp, token, MAXTOKEN);
3239
1.46k
                if (type != LABEL) {
3240
205
                    print_error("Bad group name", token, type);
3241
205
                    goto skip;
3242
205
                }
3243
1.26k
                if (!compliance_lookup(token, modid))
3244
506
                    print_error("Unknown group", token, type);
3245
1.26k
                type = get_token(fp, token, MAXTOKEN);
3246
7.02k
            } else {
3247
7.02k
                type = get_token(fp, token, MAXTOKEN);
3248
7.02k
                if (type != LABEL) {
3249
184
                    print_error("Bad object name", token, type);
3250
184
                    goto skip;
3251
184
                }
3252
6.84k
                if (!compliance_lookup(token, modid))
3253
105
                    print_error("Unknown group", token, type);
3254
6.84k
                type = get_token(fp, token, MAXTOKEN);
3255
6.84k
                if (type == SYNTAX)
3256
3.45k
                    type = eat_syntax(fp, token, MAXTOKEN);
3257
6.84k
                if (type == WRSYNTAX)
3258
847
                    type = eat_syntax(fp, token, MAXTOKEN);
3259
6.84k
                if (type == MINACCESS) {
3260
1.91k
                    type = get_token(fp, token, MAXTOKEN);
3261
1.91k
                    if (type != NOACCESS && type != ACCNOTIFY
3262
1.83k
                        && type != READONLY && type != WRITEONLY
3263
338
                        && type != READCREATE && type != READWRITE) {
3264
82
                        print_error("Bad MIN-ACCESS spec", token, type);
3265
82
                        goto skip;
3266
82
                    }
3267
1.83k
                    type = get_token(fp, token, MAXTOKEN);
3268
1.83k
                }
3269
6.84k
            }
3270
8.02k
            if (type != DESCRIPTION) {
3271
4.01k
                print_error("Expected DESCRIPTION", token, type);
3272
4.01k
                goto skip;
3273
4.01k
            }
3274
4.00k
            type = get_token(fp, token, MAXTOKEN);
3275
4.00k
            if (type != QUOTESTRING) {
3276
376
                print_error("Bad DESCRIPTION", token, type);
3277
376
                goto skip;
3278
376
            }
3279
3.62k
            type = get_token(fp, token, MAXTOKEN);
3280
3.62k
        }
3281
7.52k
    }
3282
11.3k
  skip:
3283
802k
    while (type != EQUALS && type != ENDOFFILE)
3284
791k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3285
3286
11.3k
    return merge_parse_objectid(np, fp, name);
3287
6.90k
}
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
3.41k
{
3297
3.41k
    int             type;
3298
3.41k
    char            token[MAXTOKEN];
3299
3.41k
    char            quoted_string_buffer[MAXQUOTESTR];
3300
3.41k
    struct node    *np;
3301
3302
3.41k
    np = alloc_node(current_module);
3303
3.41k
    if (np == NULL)
3304
0
        return (NULL);
3305
3.41k
    type = get_token(fp, token, MAXTOKEN);
3306
3.41k
    if (type != PRODREL) {
3307
534
        print_error("Expected PRODUCT-RELEASE", token, type);
3308
534
        goto skip;
3309
534
    }
3310
2.88k
    type = get_token(fp, token, MAXTOKEN);
3311
2.88k
    if (type != QUOTESTRING) {
3312
75
        print_error("Expected STRING after PRODUCT-RELEASE", token, type);
3313
75
        goto skip;
3314
75
    }
3315
2.80k
    type = get_token(fp, token, MAXTOKEN);
3316
2.80k
    if (type != STATUS) {
3317
316
        print_error("Expected STATUS", token, type);
3318
316
        goto skip;
3319
316
    }
3320
2.49k
    type = get_token(fp, token, MAXTOKEN);
3321
2.49k
    if (type != CURRENT && type != OBSOLETE) {
3322
287
        print_error("STATUS should be current or obsolete", token, type);
3323
287
        goto skip;
3324
287
    }
3325
2.20k
    type = get_token(fp, token, MAXTOKEN);
3326
2.20k
    if (type != DESCRIPTION) {
3327
626
        print_error("Expected DESCRIPTION", token, type);
3328
626
        goto skip;
3329
626
    }
3330
1.57k
    type = get_token(fp, quoted_string_buffer, sizeof(quoted_string_buffer));
3331
1.57k
    if (type != QUOTESTRING) {
3332
403
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3333
403
        goto skip;
3334
403
    }
3335
1.17k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3336
1.17k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
3337
0
        np->description = strdup(quoted_string_buffer);
3338
0
    }
3339
1.17k
    type = get_token(fp, token, MAXTOKEN);
3340
1.17k
    if (type == REFERENCE) {
3341
28
        type = get_token(fp, quoted_string_buffer,
3342
28
                         sizeof(quoted_string_buffer));
3343
28
        if (type != QUOTESTRING) {
3344
18
            print_error("Bad REFERENCE", quoted_string_buffer, type);
3345
18
            goto skip;
3346
18
        }
3347
10
        np->reference = strdup(quoted_string_buffer);
3348
10
        type = get_token(fp, token, type);
3349
10
    }
3350
1.16k
    while (type == SUPPORTS) {
3351
953
        int             modid;
3352
953
        struct tree    *tp;
3353
3354
953
        type = get_token(fp, token, MAXTOKEN);
3355
953
        if (type != LABEL) {
3356
41
            print_error("Bad module name", token, type);
3357
41
            goto skip;
3358
41
        }
3359
912
        modid = read_module_internal(token);
3360
912
        if (modid != MODULE_LOADED_OK && modid != MODULE_ALREADY_LOADED) {
3361
37
            print_error("Module not found", token, type);
3362
37
            goto skip;
3363
37
        }
3364
875
        modid = which_module(token);
3365
875
        type = get_token(fp, token, MAXTOKEN);
3366
875
        if (type != INCLUDES) {
3367
33
            print_error("Expected INCLUDES", token, type);
3368
33
            goto skip;
3369
33
        }
3370
842
        type = get_token(fp, token, MAXTOKEN);
3371
842
        if (type != LEFTBRACKET) {
3372
23
            print_error("Expected \"{\"", token, type);
3373
23
            goto skip;
3374
23
        }
3375
841
        do {
3376
841
            type = get_token(fp, token, MAXTOKEN);
3377
841
            if (type != LABEL) {
3378
718
                print_error("Expected group name", token, type);
3379
718
                goto skip;
3380
718
            }
3381
123
            tp = find_tree_node(token, modid);
3382
123
            if (!tp)
3383
123
                print_error("Group not found in module", token, type);
3384
123
            type = get_token(fp, token, MAXTOKEN);
3385
123
        } while (type == COMMA);
3386
101
        if (type != RIGHTBRACKET) {
3387
99
            print_error("Expected \"}\" after group list", token, type);
3388
99
            goto skip;
3389
99
        }
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
207
    if (type != EQUALS)
3474
109
        print_error("Expected \"::=\"", token, type);
3475
3.41k
  skip:
3476
385k
    while (type != EQUALS && type != ENDOFFILE) {
3477
381k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3478
381k
    }
3479
3.41k
    return merge_parse_objectid(np, fp, name);
3480
207
}
3481
3482
/*
3483
 * Parses a module identity macro
3484
 * Returns 0 on error.
3485
 */
3486
static void
3487
check_utc(const char *utc)
3488
6.16k
{
3489
6.16k
    int             len, year, month, day, hour, minute;
3490
3491
6.16k
    len = strlen(utc);
3492
6.16k
    if (len == 0) {
3493
247
        print_error("Timestamp has zero length", utc, QUOTESTRING);
3494
247
        return;
3495
247
    }
3496
5.92k
    if (utc[len - 1] != 'Z' && utc[len - 1] != 'z') {
3497
1.21k
        print_error("Timestamp should end with Z", utc, QUOTESTRING);
3498
1.21k
        return;
3499
1.21k
    }
3500
4.71k
    if (len == 11) {
3501
562
        len = sscanf(utc, "%2d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
3502
562
                     &minute);
3503
562
        year += 1900;
3504
4.14k
    } else if (len == 13)
3505
505
        len = sscanf(utc, "%4d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
3506
505
                     &minute);
3507
3.64k
    else {
3508
3.64k
        print_error("Bad timestamp format (11 or 13 characters)",
3509
3.64k
                    utc, QUOTESTRING);
3510
3.64k
        return;
3511
3.64k
    }
3512
1.06k
    if (len != 5) {
3513
244
        print_error("Bad timestamp format", utc, QUOTESTRING);
3514
244
        return;
3515
244
    }
3516
823
    if (month < 1 || month > 12)
3517
333
        print_error("Bad month in timestamp", utc, QUOTESTRING);
3518
823
    if (day < 1 || day > 31)
3519
318
        print_error("Bad day in timestamp", utc, QUOTESTRING);
3520
823
    if (hour < 0 || hour > 23)
3521
401
        print_error("Bad hour in timestamp", utc, QUOTESTRING);
3522
823
    if (minute < 0 || minute > 59)
3523
280
        print_error("Bad minute in timestamp", utc, QUOTESTRING);
3524
823
}
3525
3526
static struct node *
3527
parse_moduleIdentity(FILE * fp, char *name)
3528
6.11k
{
3529
6.11k
    register int    type;
3530
6.11k
    char            token[MAXTOKEN];
3531
6.11k
    char            quoted_string_buffer[MAXQUOTESTR];
3532
6.11k
    register struct node *np;
3533
3534
6.11k
    np = alloc_node(current_module);
3535
6.11k
    if (np == NULL)
3536
0
        return (NULL);
3537
6.11k
    type = get_token(fp, token, MAXTOKEN);
3538
6.11k
    if (type != LASTUPDATED) {
3539
995
        print_error("Expected LAST-UPDATED", token, type);
3540
995
        goto skip;
3541
995
    }
3542
5.11k
    type = get_token(fp, token, MAXTOKEN);
3543
5.11k
    if (type != QUOTESTRING) {
3544
101
        print_error("Need STRING for LAST-UPDATED", token, type);
3545
101
        goto skip;
3546
101
    }
3547
5.01k
    check_utc(token);
3548
5.01k
    type = get_token(fp, token, MAXTOKEN);
3549
5.01k
    if (type != ORGANIZATION) {
3550
1.46k
        print_error("Expected ORGANIZATION", token, type);
3551
1.46k
        goto skip;
3552
1.46k
    }
3553
3.54k
    type = get_token(fp, token, MAXTOKEN);
3554
3.54k
    if (type != QUOTESTRING) {
3555
317
        print_error("Bad ORGANIZATION", token, type);
3556
317
        goto skip;
3557
317
    }
3558
3.23k
    type = get_token(fp, token, MAXTOKEN);
3559
3.23k
    if (type != CONTACTINFO) {
3560
412
        print_error("Expected CONTACT-INFO", token, type);
3561
412
        goto skip;
3562
412
    }
3563
2.81k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3564
2.81k
    if (type != QUOTESTRING) {
3565
258
        print_error("Bad CONTACT-INFO", quoted_string_buffer, type);
3566
258
        goto skip;
3567
258
    }
3568
2.56k
    type = get_token(fp, token, MAXTOKEN);
3569
2.56k
    if (type != DESCRIPTION) {
3570
325
        print_error("Expected DESCRIPTION", token, type);
3571
325
        goto skip;
3572
325
    }
3573
2.23k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3574
2.23k
    if (type != QUOTESTRING) {
3575
359
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3576
359
        goto skip;
3577
359
    }
3578
1.87k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3579
1.87k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
3580
0
        np->description = strdup(quoted_string_buffer);
3581
0
    }
3582
1.87k
    type = get_token(fp, token, MAXTOKEN);
3583
2.68k
    while (type == REVISION) {
3584
1.59k
        type = get_token(fp, token, MAXTOKEN);
3585
1.59k
        if (type != QUOTESTRING) {
3586
444
            print_error("Bad REVISION", token, type);
3587
444
            goto skip;
3588
444
        }
3589
1.15k
        check_utc(token);
3590
1.15k
        type = get_token(fp, token, MAXTOKEN);
3591
1.15k
        if (type != DESCRIPTION) {
3592
129
            print_error("Expected DESCRIPTION", token, type);
3593
129
            goto skip;
3594
129
        }
3595
1.02k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3596
1.02k
        if (type != QUOTESTRING) {
3597
216
            print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3598
216
            goto skip;
3599
216
        }
3600
806
        type = get_token(fp, token, MAXTOKEN);
3601
806
    }
3602
1.08k
    if (type != EQUALS)
3603
827
        print_error("Expected \"::=\"", token, type);
3604
6.11k
  skip:
3605
324k
    while (type != EQUALS && type != ENDOFFILE) {
3606
318k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3607
318k
    }
3608
6.11k
    return merge_parse_objectid(np, fp, name);
3609
1.08k
}
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
883
{
3620
883
    register int    type;
3621
883
    char            token[MAXTOKEN];
3622
883
    struct node    *np;
3623
883
    int             iLine = mibLine;
3624
3625
883
    np = alloc_node(current_module);
3626
883
    if (np == NULL)
3627
0
        return (NULL);
3628
883
    type = get_token(fp, token, sizeof(token));
3629
36.3k
    while (type != EQUALS && type != ENDOFFILE) {
3630
35.5k
        type = get_token(fp, token, sizeof(token));
3631
35.5k
    }
3632
883
    if (type != EQUALS) {
3633
34
        if (np)
3634
34
            free_node(np);
3635
34
        return NULL;
3636
34
    }
3637
2.95k
    while (type != BEGIN && type != ENDOFFILE) {
3638
2.10k
        type = get_token(fp, token, sizeof(token));
3639
2.10k
    }
3640
849
    if (type != BEGIN) {
3641
29
        if (np)
3642
29
            free_node(np);
3643
29
        return NULL;
3644
29
    }
3645
17.1k
    while (type != END && type != ENDOFFILE) {
3646
16.3k
        type = get_token(fp, token, sizeof(token));
3647
16.3k
    }
3648
820
    if (type != END) {
3649
28
        if (np)
3650
28
            free_node(np);
3651
28
        return NULL;
3652
28
    }
3653
3654
792
    if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3655
792
         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
792
    return np;
3662
820
}
3663
3664
/*
3665
 * Parses a module import clause
3666
 *   loading any modules referenced
3667
 */
3668
static void
3669
parse_imports(FILE * fp)
3670
2.88k
{
3671
2.88k
    register int    type;
3672
2.88k
    char            token[MAXTOKEN];
3673
2.88k
    char            modbuf[256];
3674
157k
#define MAX_IMPORTS 512
3675
2.88k
    struct module_import *import_list;
3676
2.88k
    int             this_module;
3677
2.88k
    struct module  *mp;
3678
3679
2.88k
    int             import_count = 0;   /* Total number of imported descriptors */
3680
2.88k
    int             i = 0, old_i;       /* index of first import from each module */
3681
3682
2.88k
    import_list = malloc(MAX_IMPORTS * sizeof(*import_list));
3683
3684
2.88k
    type = get_token(fp, token, MAXTOKEN);
3685
3686
    /*
3687
     * Parse the IMPORTS clause
3688
     */
3689
314k
    while (type != SEMI && type != ENDOFFILE) {
3690
311k
        if (type == LABEL) {
3691
154k
            if (import_count == MAX_IMPORTS) {
3692
143
                print_error("Too many imported symbols", token, type);
3693
116k
                do {
3694
116k
                    type = get_token(fp, token, MAXTOKEN);
3695
116k
                } while (type != SEMI && type != ENDOFFILE);
3696
143
                goto out;
3697
143
            }
3698
154k
            import_list[import_count++].label = strdup(token);
3699
156k
        } else if (type == FROM) {
3700
3.09k
            type = get_token(fp, token, MAXTOKEN);
3701
3.09k
            if (import_count == i) {    /* All imports are handled internally */
3702
571
                type = get_token(fp, token, MAXTOKEN);
3703
571
                continue;
3704
571
            }
3705
2.52k
            this_module = which_module(token);
3706
3707
54.1k
            for (old_i = i; i < import_count; ++i)
3708
51.6k
                import_list[i].modid = this_module;
3709
3710
            /*
3711
             * Recursively read any pre-requisite modules
3712
             */
3713
2.52k
            if (read_module_internal(token) == MODULE_NOT_FOUND) {
3714
1.88k
    int found = 0;
3715
45.0k
                for (; old_i < import_count; ++old_i) {
3716
43.2k
                    found += read_import_replacements(token, &import_list[old_i]);
3717
43.2k
                }
3718
1.88k
    if (!found)
3719
1.51k
        print_module_not_found(token);
3720
1.88k
            }
3721
2.52k
        }
3722
311k
        type = get_token(fp, token, MAXTOKEN);
3723
311k
    }
3724
3725
    /* Initialize modid in case the module name was missing. */
3726
34.9k
    for (; i < import_count; ++i)
3727
32.1k
        import_list[i].modid = -1;
3728
3729
    /*
3730
     * Save the import information
3731
     *   in the global module table
3732
     */
3733
3.45M
    for (mp = module_head; mp; mp = mp->next) {
3734
3.45M
        if (mp->modid == current_module) {
3735
2.74k
            if (import_count == 0)
3736
311
                goto out;
3737
2.43k
            if (mp->imports && (mp->imports != root_imports)) {
3738
                /*
3739
                 * this can happen if all modules are in one source file. 
3740
                 */
3741
54.2k
                for (i = 0; i < mp->no_imports; ++i) {
3742
53.0k
                    DEBUGMSGTL(("parse-mibs",
3743
53.0k
                                "#### freeing Module %d '%s' %d\n",
3744
53.0k
                                mp->modid, mp->imports[i].label,
3745
53.0k
                                mp->imports[i].modid));
3746
53.0k
                    free(mp->imports[i].label);
3747
53.0k
                }
3748
1.26k
                free(mp->imports);
3749
1.26k
            }
3750
2.43k
            mp->imports = (struct module_import *)
3751
2.43k
                calloc(import_count, sizeof(struct module_import));
3752
2.43k
            if (mp->imports == NULL)
3753
0
                goto out;
3754
84.0k
            for (i = 0; i < import_count; ++i) {
3755
81.6k
                mp->imports[i].label = import_list[i].label;
3756
81.6k
                import_list[i].label = NULL;
3757
81.6k
                mp->imports[i].modid = import_list[i].modid;
3758
81.6k
                DEBUGMSGTL(("parse-mibs",
3759
81.6k
                            "#### adding Module %d '%s' %d\n", mp->modid,
3760
81.6k
                            mp->imports[i].label, mp->imports[i].modid));
3761
81.6k
            }
3762
2.43k
            mp->no_imports = import_count;
3763
2.43k
            goto out;
3764
2.43k
        }
3765
3.45M
    }
3766
3767
    /*
3768
     * Shouldn't get this far
3769
     */
3770
0
    print_module_not_found(module_name(current_module, modbuf));
3771
3772
2.88k
out:
3773
157k
    for (i = 0; i < import_count; ++i)
3774
154k
        free(import_list[i].label);
3775
2.88k
    free(import_list);
3776
2.88k
    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
29.6k
{
3801
29.6k
    struct module  *mp;
3802
3803
86.7M
    for (mp = module_head; mp; mp = mp->next)
3804
86.7M
        if (!label_compare(mp->name, name))
3805
13.8k
            return (mp->modid);
3806
3807
15.8k
    DEBUGMSGTL(("parse-mibs", "Module %s not found\n", name));
3808
15.8k
    return (-1);
3809
29.6k
}
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
126k
{
3817
126k
    struct module  *mp;
3818
3819
2.01M
    for (mp = module_head; mp; mp = mp->next)
3820
1.95M
        if (mp->modid == modid) {
3821
69.4k
            strcpy(cp, mp->name);
3822
69.4k
            return (cp);
3823
69.4k
        }
3824
3825
57.1k
    if (modid != -1) DEBUGMSGTL(("parse-mibs", "Module %d not found\n", modid));
3826
57.1k
    sprintf(cp, "#%d", modid);
3827
57.1k
    return (cp);
3828
126k
}
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
223k
{
3865
223k
    struct module_compatability *mcp;
3866
3867
4.68M
    for (mcp = module_map_head; mcp; mcp = mcp->next) {
3868
4.49M
        if (!label_compare(mcp->old_module, name)) {
3869
27.1k
            if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3870
27.1k
           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
27.1k
            (void) netsnmp_read_module(mcp->new_module);
3876
27.1k
            return 1;
3877
27.1k
        }
3878
4.49M
    }
3879
196k
    return 0;
3880
223k
}
3881
3882
static int
3883
read_import_replacements(const char *old_module_name,
3884
                         struct module_import *identifier)
3885
43.2k
{
3886
43.2k
    struct module_compatability *mcp;
3887
3888
    /*
3889
     * Look for matches first
3890
     */
3891
953k
    for (mcp = module_map_head; mcp; mcp = mcp->next) {
3892
913k
        if (!label_compare(mcp->old_module, old_module_name)) {
3893
3894
240k
            if (                /* exact match */
3895
240k
                   (mcp->tag_len == 0 &&
3896
54.9k
                    (mcp->tag == NULL ||
3897
53.5k
                     !label_compare(mcp->tag, identifier->label))) ||
3898
                   /*
3899
                    * prefix match 
3900
                    */
3901
238k
                   (mcp->tag_len != 0 &&
3902
185k
                    !strncmp(mcp->tag, identifier->label, mcp->tag_len))
3903
240k
                ) {
3904
3905
3.00k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3906
3.00k
               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
3.00k
                (void) netsnmp_read_module(mcp->new_module);
3913
3.00k
                identifier->modid = which_module(mcp->new_module);
3914
3.00k
                return 1;         /* finished! */
3915
3.00k
            }
3916
240k
        }
3917
913k
    }
3918
3919
    /*
3920
     * If no exact match, load everything relevant
3921
     */
3922
40.2k
    return read_module_replacements(old_module_name);
3923
43.2k
}
3924
3925
static int
3926
read_from_file(struct module *mp, const char *name)
3927
13.9k
{
3928
13.9k
    const char     *oldFile = File;
3929
13.9k
    int             oldLine = mibLine;
3930
13.9k
    int             oldModule = current_module;
3931
13.9k
    FILE           *fp;
3932
13.9k
    struct node    *np;
3933
13.9k
    int             res;
3934
3935
13.9k
    if (mp->no_imports != -1) {
3936
3.81k
        DEBUGMSGTL(("parse-mibs", "Module %s already loaded\n",
3937
3.81k
                    name));
3938
3.81k
        return MODULE_ALREADY_LOADED;
3939
3.81k
    }
3940
10.1k
    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.1k
#ifdef HAVE_FLOCKFILE
3950
10.1k
    flockfile(fp);
3951
10.1k
#endif
3952
10.1k
    mp->no_imports = 0; /* Note that we've read the file */
3953
10.1k
    File = mp->file;
3954
10.1k
    mibLine = 1;
3955
10.1k
    current_module = mp->modid;
3956
    /*
3957
     * Parse the file
3958
     */
3959
10.1k
    np = parse(fp);
3960
10.1k
#ifdef HAVE_FUNLOCKFILE
3961
10.1k
    funlockfile(fp);
3962
10.1k
#endif
3963
10.1k
    fclose(fp);
3964
10.1k
    File = oldFile;
3965
10.1k
    mibLine = oldLine;
3966
10.1k
    current_module = oldModule;
3967
10.1k
    res = !np && gMibError == MODULE_SYNTAX_ERROR ?
3968
5.31k
        MODULE_SYNTAX_ERROR : MODULE_LOADED_OK;
3969
16.2k
    while (np) {
3970
6.09k
        struct node *nnp = np->next;
3971
6.09k
        free_node(np);
3972
6.09k
        np = nnp;
3973
6.09k
    }
3974
10.1k
    return res;
3975
10.1k
}
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
199k
{
3985
199k
    struct module  *mp;
3986
3987
199k
    netsnmp_init_mib_internals();
3988
3989
216M
    for (mp = module_head; mp; mp = mp->next)
3990
216M
        if (!label_compare(mp->name, name))
3991
13.9k
            return read_from_file(mp, name);
3992
3993
185k
    return MODULE_NOT_FOUND;
3994
199k
}
3995
3996
void
3997
adopt_orphans(void)
3998
3.30k
{
3999
3.30k
    struct node    *np = NULL, *onp;
4000
3.30k
    struct tree    *tp;
4001
3.30k
    int             i, adopted = 1;
4002
4003
3.30k
    if (!orphan_nodes)
4004
75
        return;
4005
3.22k
    init_node_hash(orphan_nodes);
4006
3.22k
    orphan_nodes = NULL;
4007
4008
6.65k
    while (adopted) {
4009
3.43k
        adopted = 0;
4010
442k
        for (i = 0; i < NHASHSIZE; i++)
4011
439k
            if (nbuckets[i]) {
4012
212k
                for (np = nbuckets[i]; np != NULL; np = np->next) {
4013
131k
                    tp = find_tree_node(np->parent, -1);
4014
131k
        if (tp) {
4015
318
      do_subtree(tp, &np);
4016
318
      adopted = 1;
4017
                        /*
4018
                         * if do_subtree adopted the entire bucket, stop
4019
                         */
4020
318
                        if(NULL == nbuckets[i])
4021
265
                            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
64
                            if(onp == np)
4032
0
                                break;
4033
53
                        if(NULL == onp) { /* not in the list */
4034
53
                            np = nbuckets[i]; /* start over */
4035
53
                        }
4036
53
        }
4037
131k
    }
4038
81.2k
            }
4039
3.43k
    }
4040
4041
    /*
4042
     * Report on outstanding orphans
4043
     *    and link them back into the orphan list
4044
     */
4045
416k
    for (i = 0; i < NHASHSIZE; i++)
4046
412k
        if (nbuckets[i]) {
4047
75.8k
            if (orphan_nodes)
4048
72.6k
                onp = np->next = nbuckets[i];
4049
3.22k
            else
4050
3.22k
                onp = orphan_nodes = nbuckets[i];
4051
75.8k
            nbuckets[i] = NULL;
4052
198k
            while (onp) {
4053
123k
                char            modbuf[256];
4054
123k
                snmp_log(LOG_WARNING,
4055
123k
                         "Cannot resolve OID in %s: %s ::= { %s %ld } at line %d in %s\n",
4056
123k
                         module_name(onp->modid, modbuf),
4057
123k
                         (onp->label ? onp->label : "<no label>"),
4058
123k
                         (onp->parent ? onp->parent : "<no parent>"),
4059
123k
                         onp->subid, onp->lineno, onp->filename);
4060
123k
                np = onp;
4061
123k
                onp = onp->next;
4062
123k
            }
4063
75.8k
        }
4064
3.22k
}
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
194k
{
4077
194k
    int status = 0;
4078
194k
    status = read_module_internal(name);
4079
4080
194k
    if (status == MODULE_NOT_FOUND) {
4081
183k
        if (!read_module_replacements(name))
4082
182k
            print_module_not_found(name);
4083
183k
    } else if (status == MODULE_SYNTAX_ERROR) {
4084
4.85k
        gMibError = 0;
4085
4.85k
        gLoop = 1;
4086
4087
4.85k
        strncat(gMibNames, " ", sizeof(gMibNames) - strlen(gMibNames) - 1);
4088
4.85k
        strncat(gMibNames, name, sizeof(gMibNames) - strlen(gMibNames) - 1);
4089
4.85k
    }
4090
4091
194k
    return tree_head;
4092
194k
}
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
12.5k
{
4102
12.5k
    struct tree    *tp, *next;
4103
12.5k
    int             i;
4104
4105
40.8k
    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
28.3k
        int             nmod = tp->number_modules;
4114
28.3k
        if (nmod > 0) {         /* in some module */
4115
            /*
4116
             * Remove all copies of this module ID
4117
             */
4118
28.3k
            int             cnt = 0, *pi1, *pi2 = tp->module_list;
4119
57.6k
            for (i = 0, pi1 = pi2; i < nmod; i++, pi2++) {
4120
29.3k
                if (*pi2 == modID)
4121
21.1k
                    continue;
4122
8.18k
                cnt++;
4123
8.18k
                *pi1++ = *pi2;
4124
8.18k
            }
4125
28.3k
            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
20.3k
                tp->number_modules = cnt;
4131
20.3k
                switch (cnt) {
4132
20.3k
                case 0:
4133
20.3k
                    tp->module_list[0] = -1;    /* Mark unused, */
4134
20.3k
        NETSNMP_FALLTHROUGH;
4135
4136
20.3k
                case 1:        /* save the remaining module */
4137
20.3k
                    if (&(tp->modid) != tp->module_list) {
4138
496
                        tp->modid = tp->module_list[0];
4139
496
                        free(tp->module_list);
4140
496
                        tp->module_list = &(tp->modid);
4141
496
                    }
4142
20.3k
                    break;
4143
4144
0
                default:
4145
0
                    break;
4146
20.3k
                }
4147
20.3k
            }                   /* if tree node is in this module */
4148
28.3k
        }
4149
        /*
4150
         * if tree node is in some module 
4151
         */
4152
28.3k
        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
28.3k
        if (tp->child_list)
4161
6.77k
            unload_module_by_ID(modID, tp->child_list);
4162
4163
4164
28.3k
        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
20.3k
            if (tp->child_list == NULL) {
4170
20.3k
                unlink_tree(tp);
4171
20.3k
                free_tree(tp);
4172
20.3k
            } else {
4173
26
                free_partial_tree(tp, TRUE);
4174
26
            }
4175
20.3k
        }
4176
28.3k
    }
4177
12.5k
}
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.29k
{
4215
3.29k
    struct module  *mp;
4216
3.29k
    struct module_compatability *mcp;
4217
3.29k
    struct tc      *ptc;
4218
3.29k
    unsigned int    i;
4219
4220
3.29k
    for (mcp = module_map_head; mcp; mcp = module_map_head) {
4221
3.29k
        if (mcp == module_map)
4222
3.29k
            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
5.79k
    for (mp = module_head; mp; mp = module_head) {
4231
2.50k
        struct module_import *mi = mp->imports;
4232
2.50k
        if (mi) {
4233
7.03k
            for (i = 0; i < (unsigned int)mp->no_imports; ++i) {
4234
5.76k
                SNMP_FREE((mi + i)->label);
4235
5.76k
            }
4236
1.26k
            mp->no_imports = 0;
4237
1.26k
            if (mi == root_imports)
4238
877
                memset(mi, 0, sizeof(*mi));
4239
385
            else
4240
385
                free(mi);
4241
1.26k
        }
4242
4243
2.50k
        unload_module_by_ID(mp->modid, tree_head);
4244
2.50k
        module_head = mp->next;
4245
2.50k
        free(mp->name);
4246
2.50k
        free(mp->file);
4247
2.50k
        free(mp);
4248
2.50k
    }
4249
3.29k
    unload_module_by_ID(-1, tree_head);
4250
    /*
4251
     * tree nodes are cleared 
4252
     */
4253
4254
332k
    for (i = 0, ptc = tclist; i < tc_alloc; i++, ptc++) {
4255
329k
        if (ptc->type == 0)
4256
329k
            continue;
4257
400
        free_enums(&ptc->enums);
4258
400
        free_ranges(&ptc->ranges);
4259
400
        free(ptc->descriptor);
4260
400
        if (ptc->hint)
4261
2
            free(ptc->hint);
4262
400
        if (ptc->description)
4263
0
            free(ptc->description);
4264
400
    }
4265
3.29k
    SNMP_FREE(tclist);
4266
3.29k
    tc_alloc = 0;
4267
4268
3.29k
    memset(buckets, 0, sizeof(buckets));
4269
3.29k
    memset(nbuckets, 0, sizeof(nbuckets));
4270
3.29k
    memset(tbuckets, 0, sizeof(tbuckets));
4271
4272
13.1k
    for (i = 0; i < sizeof(root_imports) / sizeof(root_imports[0]); i++) {
4273
9.88k
        SNMP_FREE(root_imports[i].label);
4274
9.88k
    }
4275
4276
3.29k
    max_module = 0;
4277
3.29k
    current_module = 0;
4278
3.29k
    module_map_head = NULL;
4279
3.29k
    SNMP_FREE(last_err_module);
4280
3.29k
}
4281
4282
static void
4283
new_module(const char *name, const char *file)
4284
13.3k
{
4285
13.3k
    struct module  *mp;
4286
4287
26.4M
    for (mp = module_head; mp; mp = mp->next)
4288
26.4M
        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.31k
                DEBUGMSGTL(("parse-mibs", "    %s is now in %s\n",
4295
2.31k
                            name, file));
4296
2.31k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
4297
2.31k
               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.31k
                free(mp->file);
4307
2.31k
                mp->file = strdup(file);
4308
2.31k
            }
4309
2.92k
            return;
4310
2.92k
        }
4311
4312
    /*
4313
     * Add this module to the list 
4314
     */
4315
10.4k
    DEBUGMSGTL(("parse-mibs", "  Module %d %s is in %s\n", max_module,
4316
10.4k
                name, file));
4317
10.4k
    mp = calloc(1, sizeof(struct module));
4318
10.4k
    if (mp == NULL)
4319
0
        return;
4320
10.4k
    mp->name = strdup(name);
4321
10.4k
    mp->file = strdup(file);
4322
10.4k
    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.4k
    mp->imports = NULL;
4329
10.4k
    mp->no_imports = -1;        /* Not yet loaded */
4330
10.4k
    mp->modid = max_module;
4331
10.4k
    ++max_module;
4332
4333
10.4k
    mp->next = module_head;     /* Or add to the *end* of the list? */
4334
10.4k
    module_head = mp;
4335
10.4k
}
4336
4337
4338
static void
4339
scan_objlist(struct node *root, struct module *mp, struct objgroup *list, const char *error)
4340
26.8k
{
4341
26.8k
    int             oLine = mibLine;
4342
4343
43.7k
    while (list) {
4344
16.9k
        struct objgroup *gp = list;
4345
16.9k
        struct node    *np;
4346
16.9k
        list = list->next;
4347
16.9k
        np = root;
4348
66.7k
        while (np)
4349
50.2k
            if (label_compare(np->label, gp->name))
4350
49.7k
                np = np->next;
4351
461
            else
4352
461
                break;
4353
16.9k
        if (!np) {
4354
16.4k
      int i;
4355
16.4k
      struct module_import *mip;
4356
      /* if not local, check if it was IMPORTed */
4357
23.2k
      for (i = 0, mip = mp->imports; i < mp->no_imports; i++, mip++)
4358
6.80k
    if (strcmp(mip->label, gp->name) == 0)
4359
18
        break;
4360
16.4k
      if (i == mp->no_imports) {
4361
524
    mibLine = gp->line;
4362
524
    print_error(error, gp->name, QUOTESTRING);
4363
524
      }
4364
16.4k
        }
4365
16.9k
        free(gp->name);
4366
16.9k
        free(gp);
4367
16.9k
    }
4368
26.8k
    mibLine = oLine;
4369
26.8k
}
4370
4371
static void free_objgroup(struct objgroup *o)
4372
14.3k
{
4373
29.5k
    while (o) {
4374
15.2k
        struct objgroup *next = o->next;
4375
4376
15.2k
        free(o->name);
4377
15.2k
        free(o);
4378
15.2k
        o = next;
4379
15.2k
    }
4380
14.3k
}
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.1k
{
4389
#ifdef TEST
4390
    extern void     xmalloc_stats(FILE *);
4391
#endif
4392
10.1k
    char            token[MAXTOKEN];
4393
10.1k
    char            name[MAXTOKEN+1];
4394
10.1k
    int             type = LABEL;
4395
10.1k
    int             lasttype = LABEL;
4396
4397
29.7k
#define BETWEEN_MIBS          1
4398
19.6k
#define IN_MIB                2
4399
10.1k
    int             state = BETWEEN_MIBS;
4400
10.1k
    struct node    *np = NULL, *root = NULL;
4401
10.1k
    struct objgroup *oldgroups = NULL, *oldobjects = NULL, *oldnotifs =
4402
10.1k
        NULL;
4403
4404
10.1k
    DEBUGMSGTL(("parse-file", "Parsing file:  %s...\n", File));
4405
4406
10.1k
    if (last_err_module)
4407
2.76k
        free(last_err_module);
4408
10.1k
    last_err_module = NULL;
4409
4410
135k
    while (type != ENDOFFILE) {
4411
130k
        struct node *nnp;
4412
4413
130k
        if (lasttype == CONTINUE)
4414
32.7k
            lasttype = type;
4415
97.4k
        else
4416
97.4k
            type = lasttype = get_token(fp, token, MAXTOKEN);
4417
4418
130k
        switch (type) {
4419
8.96k
        case END:
4420
8.96k
            if (state != IN_MIB) {
4421
25
                print_error("Error, END before start of MIB", NULL, type);
4422
25
                gMibError = MODULE_SYNTAX_ERROR;
4423
25
                goto free_mib;
4424
8.94k
            } else {
4425
8.94k
                struct module  *mp;
4426
#ifdef TEST
4427
                printf("\nNodes for Module %s:\n", name);
4428
                print_nodes(stdout, root);
4429
#endif
4430
41.3M
                for (mp = module_head; mp; mp = mp->next)
4431
41.3M
                    if (mp->modid == current_module)
4432
8.94k
                        break;
4433
8.94k
                scan_objlist(root, mp, objgroups, "Undefined OBJECT-GROUP");
4434
8.94k
                scan_objlist(root, mp, objects, "Undefined OBJECT");
4435
8.94k
                scan_objlist(root, mp, notifs, "Undefined NOTIFICATION");
4436
8.94k
                objgroups = oldgroups;
4437
8.94k
                objects = oldobjects;
4438
8.94k
                notifs = oldnotifs;
4439
8.94k
                do_linkup(mp, root);
4440
8.94k
                np = root = NULL;
4441
8.94k
            }
4442
8.94k
            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
8.94k
            continue;
4450
2.88k
        case IMPORTS:
4451
2.88k
            parse_imports(fp);
4452
2.88k
            continue;
4453
54
        case EXPORTS:
4454
517
            while (type != SEMI && type != ENDOFFILE)
4455
463
                type = get_token(fp, token, MAXTOKEN);
4456
54
            continue;
4457
81.3k
        case LABEL:
4458
81.4k
        case INTEGER:
4459
81.6k
        case INTEGER32:
4460
81.8k
        case UINTEGER32:
4461
82.1k
        case UNSIGNED32:
4462
83.0k
        case COUNTER:
4463
83.0k
        case COUNTER64:
4464
83.4k
        case GAUGE:
4465
84.0k
        case IPADDR:
4466
84.0k
        case NETADDR:
4467
84.0k
        case NSAPADDRESS:
4468
84.9k
        case OBJSYNTAX:
4469
85.3k
        case APPSYNTAX:
4470
85.3k
        case SIMPLESYNTAX:
4471
85.5k
        case OBJNAME:
4472
86.3k
        case NOTIFNAME:
4473
86.8k
        case KW_OPAQUE:
4474
87.1k
        case TIMETICKS:
4475
87.1k
            break;
4476
2.88k
        case ENDOFFILE:
4477
2.88k
            continue;
4478
28.2k
        default:
4479
28.2k
            strlcpy(name, token, sizeof(name));
4480
28.2k
            type = get_token(fp, token, MAXTOKEN);
4481
28.2k
            nnp = NULL;
4482
28.2k
            if (type == MACRO) {
4483
596
                nnp = parse_macro(fp, name);
4484
596
                if (nnp == NULL) {
4485
19
                    print_error("Bad parse of MACRO", NULL, type);
4486
19
                    gMibError = MODULE_SYNTAX_ERROR;
4487
19
                }
4488
596
                free_node(nnp); /* IGNORE */
4489
596
                nnp = NULL;
4490
596
            } else
4491
27.6k
                print_error(name, "is a reserved word", lasttype);
4492
28.2k
            continue;           /* see if we can parse the rest of the file */
4493
130k
        }
4494
87.1k
        strlcpy(name, token, sizeof(name));
4495
87.1k
        type = get_token(fp, token, MAXTOKEN);
4496
87.1k
        nnp = NULL;
4497
4498
        /*
4499
         * Handle obsolete method to assign an object identifier to a
4500
         * module
4501
         */
4502
87.1k
        if (lasttype == LABEL && type == LEFTBRACKET) {
4503
787k
            while (type != RIGHTBRACKET && type != ENDOFFILE)
4504
785k
                type = get_token(fp, token, MAXTOKEN);
4505
2.26k
            if (type == ENDOFFILE) {
4506
413
                print_error("Expected \"}\"", token, type);
4507
413
                gMibError = MODULE_SYNTAX_ERROR;
4508
413
                goto free_mib;
4509
413
            }
4510
1.85k
            type = get_token(fp, token, MAXTOKEN);
4511
1.85k
        }
4512
4513
86.7k
        switch (type) {
4514
10.6k
        case DEFINITIONS:
4515
10.6k
            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
10.6k
            state = IN_MIB;
4521
10.6k
            current_module = which_module(name);
4522
10.6k
            oldgroups = objgroups;
4523
10.6k
            objgroups = NULL;
4524
10.6k
            oldobjects = objects;
4525
10.6k
            objects = NULL;
4526
10.6k
            oldnotifs = notifs;
4527
10.6k
            notifs = NULL;
4528
10.6k
            if (current_module == -1) {
4529
222
                new_module(name, File);
4530
222
                current_module = which_module(name);
4531
222
            }
4532
10.6k
            DEBUGMSGTL(("parse-mibs", "Parsing MIB: %d %s\n",
4533
10.6k
                        current_module, name));
4534
256k
            while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE)
4535
255k
                if (type == BEGIN)
4536
10.4k
                    break;
4537
10.6k
            break;
4538
11.8k
        case OBJTYPE:
4539
11.8k
            nnp = parse_objecttype(fp, name);
4540
11.8k
            if (nnp == NULL) {
4541
613
                print_error("Bad parse of OBJECT-TYPE", NULL, type);
4542
613
                gMibError = MODULE_SYNTAX_ERROR;
4543
613
                goto free_mib;
4544
613
            }
4545
11.2k
            break;
4546
11.2k
        case OBJGROUP:
4547
2.65k
            nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
4548
2.65k
            if (nnp == NULL) {
4549
73
                print_error("Bad parse of OBJECT-GROUP", NULL, type);
4550
73
                gMibError = MODULE_SYNTAX_ERROR;
4551
73
                goto free_mib;
4552
73
            }
4553
2.58k
            break;
4554
2.58k
        case NOTIFGROUP:
4555
294
            nnp = parse_objectgroup(fp, name, NOTIFICATIONS, &notifs);
4556
294
            if (nnp == NULL) {
4557
31
                print_error("Bad parse of NOTIFICATION-GROUP", NULL, type);
4558
31
                gMibError = MODULE_SYNTAX_ERROR;
4559
31
                goto free_mib;
4560
31
            }
4561
263
            break;
4562
577
        case TRAPTYPE:
4563
577
            nnp = parse_trapDefinition(fp, name);
4564
577
            if (nnp == NULL) {
4565
171
                print_error("Bad parse of TRAP-TYPE", NULL, type);
4566
171
                gMibError = MODULE_SYNTAX_ERROR;
4567
171
                goto free_mib;
4568
171
            }
4569
406
            break;
4570
1.70k
        case NOTIFTYPE:
4571
1.70k
            nnp = parse_notificationDefinition(fp, name);
4572
1.70k
            if (nnp == NULL) {
4573
145
                print_error("Bad parse of NOTIFICATION-TYPE", NULL, type);
4574
145
                gMibError = MODULE_SYNTAX_ERROR;
4575
145
                goto free_mib;
4576
145
            }
4577
1.56k
            break;
4578
11.3k
        case COMPLIANCE:
4579
11.3k
            nnp = parse_compliance(fp, name);
4580
11.3k
            if (nnp == NULL) {
4581
735
                print_error("Bad parse of MODULE-COMPLIANCE", NULL, type);
4582
735
                gMibError = MODULE_SYNTAX_ERROR;
4583
735
                goto free_mib;
4584
735
            }
4585
10.5k
            break;
4586
10.5k
        case AGENTCAP:
4587
3.41k
            nnp = parse_capabilities(fp, name);
4588
3.41k
            if (nnp == NULL) {
4589
244
                print_error("Bad parse of AGENT-CAPABILITIES", NULL, type);
4590
244
                gMibError = MODULE_SYNTAX_ERROR;
4591
244
                goto free_mib;
4592
244
            }
4593
3.17k
            break;
4594
3.17k
        case MACRO:
4595
287
            nnp = parse_macro(fp, name);
4596
287
            if (nnp == NULL) {
4597
72
                print_error("Bad parse of MACRO", NULL, type);
4598
72
                gMibError = MODULE_SYNTAX_ERROR;
4599
72
            }
4600
287
            free_node(nnp);     /* IGNORE */
4601
287
            nnp = NULL;
4602
287
            break;
4603
6.11k
        case MODULEIDENTITY:
4604
6.11k
            nnp = parse_moduleIdentity(fp, name);
4605
6.11k
            if (nnp == NULL) {
4606
354
                print_error("Bad parse of MODULE-IDENTITY", NULL, type);
4607
354
                gMibError = MODULE_SYNTAX_ERROR;
4608
354
                goto free_mib;
4609
354
            }
4610
5.75k
            break;
4611
5.75k
        case OBJIDENTITY:
4612
676
            nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
4613
676
            if (nnp == NULL) {
4614
71
                print_error("Bad parse of OBJECT-IDENTITY", NULL, type);
4615
71
                gMibError = MODULE_SYNTAX_ERROR;
4616
71
                goto free_mib;
4617
71
            }
4618
605
            break;
4619
1.09k
        case OBJECT:
4620
1.09k
            type = get_token(fp, token, MAXTOKEN);
4621
1.09k
            if (type != IDENTIFIER) {
4622
14
                print_error("Expected IDENTIFIER", token, type);
4623
14
                gMibError = MODULE_SYNTAX_ERROR;
4624
14
                goto free_mib;
4625
14
            }
4626
1.07k
            type = get_token(fp, token, MAXTOKEN);
4627
1.07k
            if (type != EQUALS) {
4628
9
                print_error("Expected \"::=\"", token, type);
4629
9
                gMibError = MODULE_SYNTAX_ERROR;
4630
9
                goto free_mib;
4631
9
            }
4632
1.07k
            nnp = parse_objectid(fp, name);
4633
1.07k
            if (nnp == NULL) {
4634
2
                print_error("Bad parse of OBJECT IDENTIFIER", NULL, type);
4635
2
                gMibError = MODULE_SYNTAX_ERROR;
4636
2
                goto free_mib;
4637
2
            }
4638
1.06k
            break;
4639
33.1k
        case EQUALS:
4640
33.1k
            nnp = parse_asntype(fp, name, &type, token);
4641
33.1k
            lasttype = CONTINUE;
4642
33.1k
            break;
4643
1.09k
        case ENDOFFILE:
4644
1.09k
            break;
4645
1.86k
        default:
4646
1.86k
            print_error("Bad operator", token, type);
4647
1.86k
            gMibError = MODULE_SYNTAX_ERROR;
4648
1.86k
            goto free_mib;
4649
86.7k
        }
4650
82.3k
        if (nnp) {
4651
48.3k
            struct node *op;
4652
48.3k
            if (np)
4653
38.2k
                np->next = nnp;
4654
10.0k
            else
4655
10.0k
                np = root = nnp;
4656
246k
            while (np->next)
4657
198k
                np = np->next;
4658
48.3k
            if (np->type == TYPE_OTHER)
4659
37.1k
                np->type = type;
4660
48.3k
            op = root;
4661
7.40M
            while (op != nnp) {
4662
7.35M
                if (strcmp(nnp->label, op->label) == 0 && nnp->subid != op->subid) {
4663
132k
                    snmp_log(LOG_ERR, 
4664
132k
                        "Duplicate Object '%s' at line %d in %s. First at line %d\n",
4665
132k
                        op->label, mibLine, File, op->lineno);
4666
132k
        erroneousMibs++;
4667
132k
    }
4668
7.35M
                op = op->next;
4669
7.35M
            }
4670
48.3k
        }
4671
82.3k
    }
4672
5.40k
    DEBUGMSGTL(("parse-file", "End of file (%s)\n", File));
4673
5.40k
    return root;
4674
4675
4.77k
free_mib:
4676
80.7k
    for (; root; root = np) {
4677
75.9k
        np = root->next;
4678
75.9k
        free_node(root);
4679
75.9k
    }
4680
4.77k
    free_objgroup(objgroups);
4681
4.77k
    objgroups = NULL;
4682
4.77k
    free_objgroup(objects);
4683
4.77k
    objects = NULL;
4684
4.77k
    free_objgroup(notifs);
4685
4.77k
    notifs = NULL;
4686
4.77k
    return NULL;
4687
10.1k
}
4688
4689
/*
4690
 * return zero if character is not a label character. 
4691
 */
4692
static int
4693
is_labelchar(int ich)
4694
14.6M
{
4695
14.6M
    netsnmp_assert(ich == EOF || (0 <= ich && ich < 256));
4696
14.6M
    if ((isalnum(ich)) || (ich == '-'))
4697
10.9M
        return 1;
4698
3.69M
    if (ich == '_' && netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
4699
3.76k
               NETSNMP_DS_LIB_MIB_PARSE_LABEL)) {
4700
954
        return 1;
4701
954
    }
4702
4703
3.69M
    return 0;
4704
3.69M
}
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
49.2M
{
4714
49.2M
#ifdef HAVE_FGETC_UNLOCKED
4715
49.2M
    return fgetc_unlocked(stream);
4716
#else
4717
    return getc(stream);
4718
#endif
4719
49.2M
}
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
6.99M
{
4729
6.99M
    int             ch, ch_next;
4730
6.99M
    char           *cp;
4731
6.99M
    int             hash;
4732
6.99M
    struct tok     *tp;
4733
6.99M
    int             too_long;
4734
6.99M
    enum { bdigits, xdigits, other } seenSymbols;
4735
4736
7.83M
fetch_next_token:
4737
7.83M
    cp = token;
4738
7.83M
    hash = 0;
4739
7.83M
    too_long = 0;
4740
    /*
4741
     * skip all white space 
4742
     */
4743
11.5M
    do {
4744
11.5M
        ch = netsnmp_getc(fp);
4745
11.5M
        if (ch == '\n')
4746
382k
            mibLine++;
4747
11.5M
    }
4748
11.5M
    while (isspace(ch) && ch != EOF);
4749
7.83M
    *cp++ = ch;
4750
7.83M
    *cp = '\0';
4751
7.83M
    switch (ch) {
4752
11.0k
    case EOF:
4753
11.0k
        return ENDOFFILE;
4754
177k
    case '"':
4755
177k
        return parseQuoteString(fp, token, maxtlen);
4756
294k
    case '\'':                 /* binary or hex constant */
4757
294k
        seenSymbols = bdigits;
4758
5.19M
        while ((ch = netsnmp_getc(fp)) != EOF && ch != '\'') {
4759
4.89M
            switch (seenSymbols) {
4760
99.4k
            case bdigits:
4761
99.4k
                if (ch == '0' || ch == '1')
4762
5.70k
                    break;
4763
93.7k
                seenSymbols = xdigits;
4764
93.7k
                NETSNMP_FALLTHROUGH;
4765
107k
            case xdigits:
4766
107k
                if (isxdigit(ch))
4767
21.6k
                    break;
4768
85.7k
                seenSymbols = other;
4769
85.7k
                NETSNMP_FALLTHROUGH;
4770
4.86M
            case other:
4771
4.86M
                break;
4772
4.89M
            }
4773
4.89M
            if (cp - token < maxtlen - 2)
4774
1.29M
                *cp++ = ch;
4775
4.89M
        }
4776
294k
        if (ch == '\'') {
4777
293k
            unsigned long   val = 0;
4778
293k
            char           *run = token + 1;
4779
293k
            ch = netsnmp_getc(fp);
4780
293k
            switch (ch) {
4781
15
            case EOF:
4782
15
                return ENDOFFILE;
4783
930
            case 'b':
4784
1.44k
            case 'B':
4785
1.44k
                if (seenSymbols > bdigits) {
4786
764
                    *cp++ = '\'';
4787
764
                    *cp = 0;
4788
764
                    return LABEL;
4789
764
                }
4790
1.81k
                while (run != cp)
4791
1.13k
                    val = val * 2 + *run++ - '0';
4792
685
                break;
4793
70.8k
            case 'h':
4794
73.3k
            case 'H':
4795
73.3k
                if (seenSymbols > xdigits) {
4796
56.9k
                    *cp++ = '\'';
4797
56.9k
                    *cp = 0;
4798
56.9k
                    return LABEL;
4799
56.9k
                }
4800
31.8k
                while (run != cp) {
4801
15.3k
                    ch = *run++;
4802
15.3k
                    if ('0' <= ch && ch <= '9')
4803
13.8k
                        val = val * 16 + ch - '0';
4804
1.52k
                    else if ('a' <= ch && ch <= 'f')
4805
589
                        val = val * 16 + ch - 'a' + 10;
4806
934
                    else if ('A' <= ch && ch <= 'F')
4807
934
                        val = val * 16 + ch - 'A' + 10;
4808
15.3k
                }
4809
16.4k
                break;
4810
218k
            default:
4811
218k
                *cp++ = '\'';
4812
218k
                *cp = 0;
4813
218k
                return LABEL;
4814
293k
            }
4815
17.1k
            sprintf(token, "%ld", val);
4816
17.1k
            return NUMBER;
4817
293k
        } else
4818
1.18k
            return LABEL;
4819
40.6k
    case '(':
4820
40.6k
        return LEFTPAREN;
4821
37.5k
    case ')':
4822
37.5k
        return RIGHTPAREN;
4823
1.27M
    case '{':
4824
1.27M
        return LEFTBRACKET;
4825
683k
    case '}':
4826
683k
        return RIGHTBRACKET;
4827
10.6k
    case '[':
4828
10.6k
        return LEFTSQBRACK;
4829
14.9k
    case ']':
4830
14.9k
        return RIGHTSQBRACK;
4831
10.3k
    case ';':
4832
10.3k
        return SEMI;
4833
46.7k
    case ',':
4834
46.7k
        return COMMA;
4835
16.9k
    case '|':
4836
16.9k
        return BAR;
4837
171k
    case '.':
4838
171k
        ch_next = netsnmp_getc(fp);
4839
171k
        if (ch_next == '.')
4840
162k
            return RANGE;
4841
8.85k
        ungetc(ch_next, fp);
4842
8.85k
        return LABEL;
4843
511k
    case ':':
4844
511k
        ch_next = netsnmp_getc(fp);
4845
511k
        if (ch_next != ':') {
4846
20.8k
            ungetc(ch_next, fp);
4847
20.8k
            return LABEL;
4848
20.8k
        }
4849
490k
        ch_next = netsnmp_getc(fp);
4850
490k
        if (ch_next != '=') {
4851
406k
            ungetc(ch_next, fp);
4852
406k
            return LABEL;
4853
406k
        }
4854
84.3k
        return EQUALS;
4855
895k
    case '-':
4856
895k
        ch_next = netsnmp_getc(fp);
4857
895k
        if (ch_next == '-') {
4858
840k
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
4859
840k
               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
840k
            } 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
840k
                ch = ' ';
4873
840k
                ch_next = netsnmp_getc(fp);
4874
5.71M
                while (ch_next != EOF && ch_next != '\n' &&
4875
5.55M
                       (ch != '-' || ch_next != '-')) {
4876
4.86M
                    ch = ch_next;
4877
4.86M
                    ch_next = netsnmp_getc(fp);
4878
4.86M
                }
4879
840k
            }
4880
840k
            if (ch_next == EOF)
4881
123
                return ENDOFFILE;
4882
840k
            if (ch_next == '\n')
4883
155k
                mibLine++;
4884
840k
            goto fetch_next_token;
4885
840k
        }
4886
54.4k
        ungetc(ch_next, fp);
4887
54.4k
  NETSNMP_FALLTHROUGH;
4888
3.69M
    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
3.69M
        if (!is_labelchar(ch))
4895
2.68M
            return LABEL;
4896
1.01M
        hash += tolower(ch);
4897
1.01M
      more:
4898
10.9M
        while (is_labelchar(ch_next = netsnmp_getc(fp))) {
4899
9.97M
            hash += tolower(ch_next);
4900
9.97M
            if (cp - token < maxtlen - 1)
4901
7.18M
                *cp++ = ch_next;
4902
2.79M
            else
4903
2.79M
                too_long = 1;
4904
9.97M
        }
4905
1.01M
        ungetc(ch_next, fp);
4906
1.01M
        *cp = '\0';
4907
4908
1.01M
        if (too_long)
4909
1.78k
            print_error("Warning: token too long", token, CONTINUE);
4910
3.39M
        for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
4911
2.76M
            if ((tp->hash == hash) && (!label_compare(tp->name, token)))
4912
392k
                break;
4913
2.76M
        }
4914
1.01M
        if (tp) {
4915
392k
            if (tp->token != CONTINUE)
4916
386k
                return (tp->token);
4917
6.01k
            while (isspace((ch_next = netsnmp_getc(fp))))
4918
896k
                if (ch_next == '\n')
4919
66.3k
                    mibLine++;
4920
6.01k
            if (ch_next == EOF)
4921
15
                return ENDOFFILE;
4922
5.99k
            if (isalnum(ch_next)) {
4923
5.24k
                *cp++ = ch_next;
4924
5.24k
                hash += tolower(ch_next);
4925
5.24k
                goto more;
4926
5.24k
            }
4927
5.99k
        }
4928
625k
        if (token[0] == '-' || isdigit((unsigned char)(token[0]))) {
4929
571k
            for (cp = token + 1; *cp; cp++)
4930
436k
                if (!isdigit((unsigned char)(*cp)))
4931
32.6k
                    return LABEL;
4932
134k
            return NUMBER;
4933
167k
        }
4934
458k
        return LABEL;
4935
7.83M
    }
4936
7.83M
}
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
25.4k
{
4950
25.4k
    FILE           *fp;
4951
25.4k
    char            token[MAXTOKEN], token2[MAXTOKEN];
4952
4953
    /*
4954
     * which module is this 
4955
     */
4956
25.4k
    if ((fp = fopen(tmpstr, "r")) == NULL) {
4957
14
        snmp_log_perror(tmpstr);
4958
14
        return 1;
4959
14
    }
4960
25.3k
    DEBUGMSGTL(("parse-mibs", "Checking file: %s...\n",
4961
25.3k
                tmpstr));
4962
25.3k
    mibLine = 1;
4963
25.3k
    File = tmpstr;
4964
25.3k
    if (get_token(fp, token, MAXTOKEN) != LABEL) {
4965
14.9k
      fclose(fp);
4966
14.9k
      return 1;
4967
14.9k
    }
4968
    /*
4969
     * simple test for this being a MIB 
4970
     */
4971
10.3k
    if (get_token(fp, token2, MAXTOKEN) == DEFINITIONS) {
4972
4.65k
        new_module(token, tmpstr);
4973
4.65k
        fclose(fp);
4974
4.65k
        return 0;
4975
5.74k
    } else {
4976
5.74k
        fclose(fp);
4977
5.74k
        return 1;
4978
5.74k
    }
4979
10.3k
}
4980
4981
static int elemcmp(const void *a, const void *b)
4982
40.0k
{
4983
40.0k
    const char *const *s1 = a, *const *s2 = b;
4984
4985
40.0k
    return strcmp(*s1, *s2);
4986
40.0k
}
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.30k
{
4994
3.30k
    DIR            *dir, *dir2;
4995
3.30k
    struct dirent  *file;
4996
3.30k
    char          **filenames = NULL;
4997
3.30k
    int             fname_len, i, filename_count = 0, array_size = 0;
4998
3.30k
    char           *tmpstr;
4999
5000
3.30k
    *result = NULL;
5001
5002
3.30k
    dir = opendir(dirname);
5003
3.30k
    if (!dir)
5004
66
        return -1;
5005
5006
38.3k
    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
35.1k
        fname_len = strlen(file->d_name);
5013
35.1k
        if (fname_len > 0 && file->d_name[0] != '.'
5014
28.6k
            && file->d_name[0] != '#'
5015
28.6k
            && file->d_name[fname_len-1] != '#'
5016
28.6k
            && file->d_name[fname_len-1] != '~') {
5017
28.6k
            if (asprintf(&tmpstr, "%s/%s", dirname, file->d_name) < 0)
5018
0
                continue;
5019
28.6k
            dir2 = opendir(tmpstr);
5020
28.6k
            if (dir2) {
5021
                /* file is a directory, don't read it */
5022
6.47k
                closedir(dir2);
5023
22.1k
            } else {
5024
22.1k
                if (filename_count >= array_size) {
5025
3.23k
                    char **new_filenames;
5026
5027
3.23k
                    array_size = (array_size + 16) * 2;
5028
3.23k
                    new_filenames = realloc(filenames,
5029
3.23k
                                        array_size * sizeof(filenames[0]));
5030
3.23k
                    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.23k
                    filenames = new_filenames;
5039
3.23k
                }
5040
22.1k
                filenames[filename_count++] = tmpstr;
5041
22.1k
                tmpstr = NULL;
5042
22.1k
            }
5043
28.6k
            free(tmpstr);
5044
28.6k
        }
5045
35.1k
    }
5046
3.23k
    closedir(dir);
5047
5048
3.23k
    if (filenames)
5049
3.23k
        qsort(filenames, filename_count, sizeof(filenames[0]), elemcmp);
5050
3.23k
    *result = filenames;
5051
5052
3.23k
    return filename_count;
5053
3.23k
}
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.30k
{
5064
3.30k
    const char     *oldFile = File;
5065
3.30k
    char          **filenames;
5066
3.30k
    int             count = 0;
5067
3.30k
    int             filename_count, i;
5068
5069
3.30k
    DEBUGMSGTL(("parse-mibs", "Scanning directory %s\n", dirname));
5070
5071
3.30k
    filename_count = scan_directory(&filenames, dirname);
5072
5073
3.30k
    if (filename_count >= 0) {
5074
25.4k
        for (i = 0; i < filename_count; i++) {
5075
22.1k
            if (add_mibfile(filenames[i], strrchr(filenames[i], '/')) == 0)
5076
2.34k
                count++;
5077
22.1k
      free(filenames[i]);
5078
22.1k
        }
5079
3.23k
        File = oldFile;
5080
3.23k
        free(filenames);
5081
3.23k
        return (count);
5082
3.23k
    }
5083
66
    else
5084
66
        DEBUGMSGTL(("parse-mibs","cannot open MIB directory %s\n", dirname));
5085
5086
66
    return (-1);
5087
3.30k
}
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
9.53k
{
5097
9.53k
    FILE           *fp;
5098
9.53k
    char            token[MAXTOKEN];
5099
5100
9.53k
    fp = fopen(filename, "r");
5101
9.53k
    if (fp == NULL) {
5102
409
        snmp_log_perror(filename);
5103
409
        return NULL;
5104
409
    }
5105
9.12k
    mibLine = 1;
5106
9.12k
    File = filename;
5107
9.12k
    DEBUGMSGTL(("parse-mibs", "Parsing file: %s...\n", filename));
5108
9.12k
    if (get_token(fp, token, MAXTOKEN) != LABEL) {
5109
654
      snmp_log(LOG_ERR, "Failed to parse MIB file %s\n", filename);
5110
654
      fclose(fp);
5111
654
      return NULL;
5112
654
    }
5113
8.46k
    fclose(fp);
5114
8.46k
    new_module(token, filename);
5115
8.46k
    (void) netsnmp_read_module(token);
5116
5117
8.46k
    return tree_head;
5118
9.12k
}
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
177k
{
5176
177k
    register int    ch;
5177
177k
    int             count = 0;
5178
177k
    int             too_long = 0;
5179
177k
    char           *token_start = token;
5180
5181
12.5M
    for (ch = netsnmp_getc(fp); ch != EOF; ch = netsnmp_getc(fp)) {
5182
12.5M
        if (ch == '\r')
5183
2.62k
            continue;
5184
12.5M
        if (ch == '\n') {
5185
103k
            mibLine++;
5186
12.4M
        } else if (ch == '"') {
5187
177k
            netsnmp_assert(token - token_start < maxtlen);
5188
177k
            *token = '\0';
5189
177k
            if (too_long && netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
5190
1.23k
             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
177k
            return QUOTESTRING;
5203
177k
        }
5204
        /*
5205
         * maximum description length check.  If greater, keep parsing
5206
         * but truncate the string 
5207
         */
5208
12.3M
        if (++count < maxtlen)
5209
5.00M
            *token++ = ch;
5210
7.35M
        else
5211
7.35M
            too_long = 1;
5212
12.3M
    }
5213
5214
590
    return 0;
5215
177k
}
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
2.34k
{
5227
2.34k
    int             type;
5228
2.34k
    char            token[MAXTOKEN];
5229
2.34k
    char            nextIsImplied = 0;
5230
5231
2.34k
    struct index_list *mylist = NULL;
5232
2.34k
    struct index_list **mypp = &mylist;
5233
5234
2.34k
    free_indexes(retp);
5235
5236
2.34k
    type = get_token(fp, token, MAXTOKEN);
5237
5238
2.34k
    if (type != LEFTBRACKET) {
5239
12
        return NULL;
5240
12
    }
5241
5242
2.33k
    type = get_token(fp, token, MAXTOKEN);
5243
85.1k
    while (type != RIGHTBRACKET && type != ENDOFFILE) {
5244
82.7k
        if ((type == LABEL) || (type & SYNTAX_MASK)) {
5245
69.8k
            *mypp = calloc(1, sizeof(struct index_list));
5246
69.8k
            if (*mypp) {
5247
69.8k
                (*mypp)->ilabel = strdup(token);
5248
69.8k
                (*mypp)->isimplied = nextIsImplied;
5249
69.8k
                mypp = &(*mypp)->next;
5250
69.8k
                nextIsImplied = 0;
5251
69.8k
            }
5252
69.8k
        } else if (type == IMPLIED) {
5253
222
            nextIsImplied = 1;
5254
222
        }
5255
82.7k
        type = get_token(fp, token, MAXTOKEN);
5256
82.7k
    }
5257
5258
2.33k
    *retp = mylist;
5259
2.33k
    return mylist;
5260
2.34k
}
5261
5262
static struct varbind_list *
5263
getVarbinds(FILE * fp, struct varbind_list **retp)
5264
1.79k
{
5265
1.79k
    int             type;
5266
1.79k
    char            token[MAXTOKEN];
5267
5268
1.79k
    struct varbind_list *mylist = NULL;
5269
1.79k
    struct varbind_list **mypp = &mylist;
5270
5271
1.79k
    free_varbinds(retp);
5272
5273
1.79k
    type = get_token(fp, token, MAXTOKEN);
5274
5275
1.79k
    if (type != LEFTBRACKET) {
5276
22
        return NULL;
5277
22
    }
5278
5279
1.77k
    type = get_token(fp, token, MAXTOKEN);
5280
382k
    while (type != RIGHTBRACKET && type != ENDOFFILE) {
5281
380k
        if ((type == LABEL) || (type & SYNTAX_MASK)) {
5282
375k
            *mypp = calloc(1, sizeof(struct varbind_list));
5283
375k
            if (*mypp) {
5284
375k
                (*mypp)->vblabel = strdup(token);
5285
375k
                mypp = &(*mypp)->next;
5286
375k
            }
5287
375k
        }
5288
380k
        type = get_token(fp, token, MAXTOKEN);
5289
380k
    }
5290
5291
1.77k
    *retp = mylist;
5292
1.77k
    return mylist;
5293
1.79k
}
5294
5295
static void
5296
free_indexes(struct index_list **spp)
5297
311k
{
5298
311k
    if (spp && *spp) {
5299
2.14k
        struct index_list *pp, *npp;
5300
5301
2.14k
        pp = *spp;
5302
2.14k
        *spp = NULL;
5303
5304
63.6k
        while (pp) {
5305
61.4k
            npp = pp->next;
5306
61.4k
            if (pp->ilabel)
5307
61.4k
                free(pp->ilabel);
5308
61.4k
            free(pp);
5309
61.4k
            pp = npp;
5310
61.4k
        }
5311
2.14k
    }
5312
311k
}
5313
5314
static void
5315
free_varbinds(struct varbind_list **spp)
5316
310k
{
5317
310k
    if (spp && *spp) {
5318
1.67k
        struct varbind_list *pp, *npp;
5319
5320
1.67k
        pp = *spp;
5321
1.67k
        *spp = NULL;
5322
5323
177k
        while (pp) {
5324
175k
            npp = pp->next;
5325
175k
            if (pp->vblabel)
5326
175k
                free(pp->vblabel);
5327
175k
            free(pp);
5328
175k
            pp = npp;
5329
175k
        }
5330
1.67k
    }
5331
310k
}
5332
5333
static void
5334
free_ranges(struct range_list **spp)
5335
315k
{
5336
315k
    if (spp && *spp) {
5337
3.03k
        struct range_list *pp, *npp;
5338
5339
3.03k
        pp = *spp;
5340
3.03k
        *spp = NULL;
5341
5342
8.07k
        while (pp) {
5343
5.03k
            npp = pp->next;
5344
5.03k
            free(pp);
5345
5.03k
            pp = npp;
5346
5.03k
        }
5347
3.03k
    }
5348
315k
}
5349
5350
static void
5351
free_enums(struct enum_list **spp)
5352
313k
{
5353
313k
    if (spp && *spp) {
5354
2.49k
        struct enum_list *pp, *npp;
5355
5356
2.49k
        pp = *spp;
5357
2.49k
        *spp = NULL;
5358
5359
12.3k
        while (pp) {
5360
9.85k
            npp = pp->next;
5361
9.85k
            if (pp->label)
5362
9.85k
                free(pp->label);
5363
9.85k
            free(pp);
5364
9.85k
            pp = npp;
5365
9.85k
        }
5366
2.49k
    }
5367
313k
}
5368
5369
static struct enum_list *
5370
copy_enums(struct enum_list *sp)
5371
426
{
5372
426
    struct enum_list *xp = NULL, **spp = &xp;
5373
5374
946
    while (sp) {
5375
520
        *spp = calloc(1, sizeof(struct enum_list));
5376
520
        if (!*spp)
5377
0
            break;
5378
520
        (*spp)->label = strdup(sp->label);
5379
520
        (*spp)->value = sp->value;
5380
520
        spp = &(*spp)->next;
5381
520
        sp = sp->next;
5382
520
    }
5383
426
    return (xp);
5384
426
}
5385
5386
static struct range_list *
5387
copy_ranges(struct range_list *sp)
5388
426
{
5389
426
    struct range_list *xp = NULL, **spp = &xp;
5390
5391
1.27k
    while (sp) {
5392
851
        *spp = calloc(1, sizeof(struct range_list));
5393
851
        if (!*spp)
5394
0
            break;
5395
851
        (*spp)->low = sp->low;
5396
851
        (*spp)->high = sp->high;
5397
851
        spp = &(*spp)->next;
5398
851
        sp = sp->next;
5399
851
    }
5400
426
    return (xp);
5401
426
}
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
45
{
5410
45
    int             type;
5411
45
    char            token[MAXTOKEN];
5412
45
    int             bracketcount = 1;
5413
5414
45
    type = get_token(fp, token, MAXTOKEN);
5415
5416
45
    if (type != LEFTBRACKET)
5417
4
        return 0;
5418
1.07M
    while ((type != RIGHTBRACKET || bracketcount > 0) && type != ENDOFFILE) {
5419
1.07M
        type = get_token(fp, token, MAXTOKEN);
5420
1.07M
        if (type == LEFTBRACKET)
5421
1.05M
            bracketcount++;
5422
19.1k
        else if (type == RIGHTBRACKET)
5423
362
            bracketcount--;
5424
1.07M
    }
5425
5426
41
    if (type == RIGHTBRACKET)
5427
7
        return OBJID;
5428
34
    else
5429
34
        return 0;
5430
41
}
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
37.3k
{
5695
37.3k
    struct node    *nnp;
5696
    /*
5697
     * printf("merge defval --> %s\n",np->defaultValue); 
5698
     */
5699
37.3k
    nnp = parse_objectid(fp, name);
5700
37.3k
    if (nnp) {
5701
5702
        /*
5703
         * apply last OID sub-identifier data to the information 
5704
         */
5705
        /*
5706
         * already collected for this node. 
5707
         */
5708
35.7k
        struct node    *headp, *nextp;
5709
35.7k
        int             ncount = 0;
5710
35.7k
        nextp = headp = nnp;
5711
111k
        while (nnp->next) {
5712
75.5k
            nextp = nnp;
5713
75.5k
            ncount++;
5714
75.5k
            nnp = nnp->next;
5715
75.5k
        }
5716
5717
35.7k
        np->label = nnp->label;
5718
35.7k
        np->subid = nnp->subid;
5719
35.7k
        np->modid = nnp->modid;
5720
35.7k
        np->parent = nnp->parent;
5721
35.7k
  if (nnp->filename != NULL) {
5722
35.7k
    free(nnp->filename);
5723
35.7k
  }
5724
35.7k
        free(nnp);
5725
5726
35.7k
        if (ncount) {
5727
14.1k
            nextp->next = np;
5728
14.1k
            np = headp;
5729
14.1k
        }
5730
35.7k
    } else {
5731
1.62k
        free_node(np);
5732
1.62k
        np = NULL;
5733
1.62k
    }
5734
5735
37.3k
    return np;
5736
37.3k
}
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
75.3k
{
5752
75.3k
    free_partial_tree(tp, FALSE);
5753
5754
75.3k
    tp->label = np->label;
5755
75.3k
    np->label = NULL;
5756
75.3k
    tp->enums = np->enums;
5757
75.3k
    np->enums = NULL;
5758
75.3k
    tp->ranges = np->ranges;
5759
75.3k
    np->ranges = NULL;
5760
75.3k
    tp->indexes = np->indexes;
5761
75.3k
    np->indexes = NULL;
5762
75.3k
    tp->augments = np->augments;
5763
75.3k
    np->augments = NULL;
5764
75.3k
    tp->varbinds = np->varbinds;
5765
75.3k
    np->varbinds = NULL;
5766
75.3k
    tp->hint = np->hint;
5767
75.3k
    np->hint = NULL;
5768
75.3k
    tp->units = np->units;
5769
75.3k
    np->units = NULL;
5770
75.3k
    tp->description = np->description;
5771
75.3k
    np->description = NULL;
5772
75.3k
    tp->reference = np->reference;
5773
75.3k
    np->reference = NULL;
5774
75.3k
    tp->defaultValue = np->defaultValue;
5775
75.3k
    np->defaultValue = NULL;
5776
75.3k
    tp->subid = np->subid;
5777
75.3k
    tp->tc_index = np->tc_index;
5778
75.3k
    tp->type = translation_table[np->type];
5779
75.3k
    tp->access = np->access;
5780
75.3k
    tp->status = np->status;
5781
5782
75.3k
    set_function(tp);
5783
75.3k
}
5784
5785
#endif /* NETSNMP_DISABLE_MIB_LOADING */