Coverage Report

Created: 2025-11-09 06:23

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