Coverage Report

Created: 2025-08-11 06:35

/src/net-snmp/snmplib/parse.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * parse.c
3
 *
4
 */
5
/* Portions of this file are subject to the following copyrights.  See
6
 * the Net-SNMP's COPYING file for more details and other copyrights
7
 * that may apply:
8
 */
9
/******************************************************************
10
        Copyright 1989, 1991, 1992 by Carnegie Mellon University
11
12
                      All Rights Reserved
13
14
Permission to use, copy, modify, and distribute this software and its
15
documentation for any purpose and without fee is hereby granted,
16
provided that the above copyright notice appear in all copies and that
17
both that copyright notice and this permission notice appear in
18
supporting documentation, and that the name of CMU not be
19
used in advertising or publicity pertaining to distribution of the
20
software without specific, written prior permission.
21
22
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
24
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
25
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
26
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
27
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28
SOFTWARE.
29
******************************************************************/
30
/*
31
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
32
 * Use is subject to license terms specified in the COPYING file
33
 * distributed with the Net-SNMP package.
34
 */
35
#include <net-snmp/net-snmp-config.h>
36
#include <net-snmp/net-snmp-features.h>
37
38
#ifndef NETSNMP_DISABLE_MIB_LOADING
39
40
#ifdef HAVE_LIMITS_H
41
#include <limits.h>
42
#endif
43
#include <stdio.h>
44
#ifdef HAVE_STDLIB_H
45
#include <stdlib.h>
46
#endif
47
#ifdef HAVE_STRING_H
48
#include <string.h>
49
#else
50
#include <strings.h>
51
#endif
52
#include <ctype.h>
53
#include <sys/types.h>
54
#ifdef HAVE_SYS_STAT_H
55
#include <sys/stat.h>
56
#endif
57
58
#ifdef HAVE_DIRENT_H
59
#include <dirent.h>
60
#endif
61
#ifdef TIME_WITH_SYS_TIME
62
# include <sys/time.h>
63
# include <time.h>
64
#else
65
# ifdef HAVE_SYS_TIME_H
66
#  include <sys/time.h>
67
# else
68
#  include <time.h>
69
# endif
70
#endif
71
#ifdef HAVE_NETINET_IN_H
72
#include <netinet/in.h>
73
#endif
74
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
75
#include <regex.h>
76
#endif
77
#ifdef HAVE_UNISTD_H
78
#include <unistd.h>
79
#endif
80
81
#include <errno.h>
82
83
#include <net-snmp/types.h>
84
#include <net-snmp/output_api.h>
85
#include <net-snmp/config_api.h>
86
#include <net-snmp/utilities.h>
87
88
#include <net-snmp/library/parse.h>
89
#include <net-snmp/library/mib.h>
90
#include <net-snmp/library/snmp_api.h>
91
#include <net-snmp/library/tools.h>
92
93
netsnmp_feature_child_of(find_module, mib_api);
94
netsnmp_feature_child_of(get_tc_description, mib_api);
95
96
/*
97
 * A linked list of nodes.
98
 */
99
struct node {
100
    struct node    *next;
101
    char           *label;  /* This node's (unique) textual name */
102
    u_long          subid;  /* This node's integer subidentifier */
103
    int             modid;  /* The module containing this node */
104
    char           *parent; /* The parent's textual name */
105
    int             tc_index; /* index into tclist (-1 if NA) */
106
    int             type;   /* The type of object this represents */
107
    int             access;
108
    int             status;
109
    struct enum_list *enums; /* (optional) list of enumerated integers */
110
    struct range_list *ranges;
111
    struct index_list *indexes;
112
    char           *augments;
113
    struct varbind_list *varbinds;
114
    char           *hint;
115
    char           *units;
116
    char           *description; /* description (a quoted string) */
117
    char           *reference; /* references (a quoted string) */
118
    char           *defaultValue;
119
    char           *filename;
120
    int             lineno;
121
};
122
123
/*
124
 * This is one element of an object identifier with either an integer
125
 * subidentifier, or a textual string label, or both.
126
 * The subid is -1 if not present, and label is NULL if not present.
127
 */
128
struct subid_s {
129
    int             subid;
130
    int             modid;
131
    char           *label;
132
};
133
134
3.48k
#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.93M
#define SYNTAX_MASK     0x80
158
/*
159
 * types of tokens
160
 * Tokens with the SYNTAX_MASK bit set are syntax tokens 
161
 */
162
1.02M
#define CONTINUE    -1
163
7.98M
#define ENDOFFILE   0
164
7.16M
#define LABEL       1
165
#define SUBTREE     2
166
618k
#define SYNTAX      3
167
6.33k
#define OBJID       (4 | SYNTAX_MASK)
168
6.17k
#define OCTETSTR    (5 | SYNTAX_MASK)
169
108k
#define INTEGER     (6 | SYNTAX_MASK)
170
107k
#define NETADDR     (7 | SYNTAX_MASK)
171
107k
#define IPADDR      (8 | SYNTAX_MASK)
172
111k
#define COUNTER     (9 | SYNTAX_MASK)
173
112k
#define GAUGE       (10 | SYNTAX_MASK)
174
112k
#define TIMETICKS   (11 | SYNTAX_MASK)
175
111k
#define KW_OPAQUE   (12 | SYNTAX_MASK)
176
6.22k
#define NUL         (13 | SYNTAX_MASK)
177
82.3k
#define SEQUENCE    14
178
994
#define OF          15          /* SEQUENCE OF */
179
16.5k
#define OBJTYPE     16
180
16.5k
#define ACCESS      17
181
37.3k
#define READONLY    18
182
25.6k
#define READWRITE   19
183
25.7k
#define WRITEONLY   20
184
#ifdef NOACCESS
185
#undef NOACCESS                 /* agent 'NOACCESS' token */
186
#endif
187
27.7k
#define NOACCESS    21
188
35.7k
#define STATUS      22
189
32.7k
#define MANDATORY   23
190
17.0k
#define KW_OPTIONAL    24
191
18.3k
#define OBSOLETE    25
192
/*
193
 * #define RECOMMENDED 26 
194
 */
195
#define PUNCT       27
196
4.47M
#define EQUALS      28
197
254k
#define NUMBER      29
198
4.19M
#define LEFTBRACKET 30
199
6.60M
#define RIGHTBRACKET 31
200
339k
#define LEFTPAREN   32
201
48.6k
#define RIGHTPAREN  33
202
52.6k
#define COMMA       34
203
635k
#define DESCRIPTION 35
204
1.30M
#define QUOTESTRING 36
205
3.30k
#define INDEX       37
206
3.47k
#define DEFVAL      38
207
20.6k
#define DEPRECATED  39
208
6.43k
#define SIZE        40
209
10.7k
#define BITSTRING   (41 | SYNTAX_MASK)
210
110k
#define NSAPADDRESS (42 | SYNTAX_MASK)
211
108k
#define COUNTER64   (43 | SYNTAX_MASK)
212
5.60k
#define OBJGROUP    44
213
5.92k
#define NOTIFTYPE   45
214
280
#define AUGMENTS    46
215
16.0k
#define COMPLIANCE  47
216
21.7k
#define READCREATE  48
217
16.5k
#define UNITS       49
218
12.7k
#define REFERENCE   50
219
45
#define NUM_ENTRIES 51
220
8.98k
#define MODULEIDENTITY 52
221
5.77k
#define LASTUPDATED 53
222
4.85k
#define ORGANIZATION 54
223
2.47k
#define CONTACTINFO 55
224
106k
#define UINTEGER32 (56 | SYNTAX_MASK)
225
65.6k
#define CURRENT     57
226
21.6k
#define DEFINITIONS 58
227
60.7k
#define END         59
228
2.87M
#define SEMI        60
229
3.73k
#define TRAPTYPE    61
230
1.07k
#define ENTERPRISE  62
231
/*
232
 * #define DISPLAYSTR (63 | SYNTAX_MASK) 
233
 */
234
188k
#define BEGIN       64
235
2.82k
#define IMPORTS     65
236
96
#define EXPORTS     66
237
4.81k
#define ACCNOTIFY   67
238
25.0k
#define BAR         68
239
200k
#define RANGE       69
240
19.0k
#define CONVENTION  70
241
296k
#define DISPLAYHINT 71
242
216k
#define FROM        72
243
8.65k
#define AGENTCAP    73
244
29.2k
#define MACRO       74
245
18.4k
#define IMPLIED     75
246
1.83k
#define SUPPORTS    76
247
1.38k
#define INCLUDES    77
248
2
#define VARIATION   78
249
1.44k
#define REVISION    79
250
0
#define NOTIMPL     80
251
5.75k
#define OBJECTS     81
252
470
#define NOTIFICATIONS 82
253
20.7k
#define MODULE      83
254
7.49k
#define MINACCESS   84
255
5.44k
#define PRODREL     85
256
7.49k
#define WRSYNTAX    86
257
0
#define CREATEREQ   87
258
3.68k
#define NOTIFGROUP  88
259
10.3k
#define MANDATORYGROUPS 89
260
37.3k
#define GROUP     90
261
48.9k
#define OBJECT      91
262
4.74k
#define IDENTIFIER  92
263
39.2k
#define CHOICE      93
264
37.5k
#define LEFTSQBRACK 95
265
247k
#define RIGHTSQBRACK  96
266
5.80k
#define IMPLICIT    97
267
104k
#define APPSYNTAX (98 | SYNTAX_MASK)
268
104k
#define OBJSYNTAX (99 | SYNTAX_MASK)
269
104k
#define SIMPLESYNTAX  (100 | SYNTAX_MASK)
270
104k
#define OBJNAME   (101 | SYNTAX_MASK)
271
105k
#define NOTIFNAME (102 | SYNTAX_MASK)
272
402
#define VARIABLES 103
273
109k
#define UNSIGNED32  (104 | SYNTAX_MASK)
274
106k
#define INTEGER32 (105 | SYNTAX_MASK)
275
4.35k
#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
391k
#define MODULE_NOT_FOUND  0
514
24.4k
#define MODULE_LOADED_OK  1
515
9.88k
#define MODULE_ALREADY_LOADED 2
516
/*
517
 * #define MODULE_LOAD_FAILED   3       
518
 */
519
0
#define MODULE_LOAD_FAILED  MODULE_NOT_FOUND
520
28.0k
#define MODULE_SYNTAX_ERROR     4
521
522
int gMibError = 0,gLoop = 0;
523
static char *gpMibErrorString;
524
char gMibNames[STRINGMAX];
525
526
1.54M
#define HASHSIZE        32
527
1.54M
#define BUCKET(x)       (x & (HASHSIZE-1))
528
529
8.10M
#define NHASHSIZE    128
530
4.54M
#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
954
#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
58
{
634
58
    if (options) {
635
2.21k
        while (*options) {
636
2.18k
            switch (*options) {
637
350
            case 'u':
638
350
                netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL,
639
350
                               !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
640
350
                                               NETSNMP_DS_LIB_MIB_PARSE_LABEL));
641
350
                break;
642
643
560
            case 'c':
644
560
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
645
560
            NETSNMP_DS_LIB_MIB_COMMENT_TERM);
646
560
                break;
647
648
237
            case 'e':
649
237
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
650
237
            NETSNMP_DS_LIB_MIB_ERRORS);
651
237
                break;
652
653
95
            case 'w':
654
95
                netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
655
95
           NETSNMP_DS_LIB_MIB_WARNINGS, 1);
656
95
                break;
657
658
270
            case 'W':
659
270
                netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
660
270
           NETSNMP_DS_LIB_MIB_WARNINGS, 2);
661
270
                break;
662
663
351
            case 'd':
664
351
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 
665
351
            NETSNMP_DS_LIB_SAVE_MIB_DESCRS);
666
351
                break;
667
668
291
            case 'R':
669
291
                netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID, 
670
291
            NETSNMP_DS_LIB_MIB_REPLACE);
671
291
                break;
672
673
29
            default:
674
                /*
675
                 * return at the unknown option 
676
                 */
677
29
                return options;
678
2.18k
            }
679
2.15k
            options++;
680
2.15k
        }
681
58
    }
682
29
    return NULL;
683
58
}
684
685
static int
686
name_hash(const char *name)
687
4.84M
{
688
4.84M
    int             hash = 0;
689
4.84M
    const char     *cp;
690
691
4.84M
    if (!name)
692
0
        return 0;
693
24.9M
    for (cp = name; *cp; cp++)
694
20.0M
        hash += tolower((unsigned char)(*cp));
695
4.84M
    return (hash);
696
4.84M
}
697
698
void
699
netsnmp_init_mib_internals(void)
700
215k
{
701
215k
    register struct tok *tp;
702
215k
    register int    b, i;
703
215k
    int             max_modc;
704
705
215k
    if (tree_head)
706
212k
        return;
707
708
    /*
709
     * Set up hash list of pre-defined tokens
710
     */
711
3.21k
    memset(buckets, 0, sizeof(buckets));
712
298k
    for (tp = tokens; tp->name; tp++) {
713
295k
        tp->hash = name_hash(tp->name);
714
295k
        b = BUCKET(tp->hash);
715
295k
        if (buckets[b])
716
192k
            tp->next = buckets[b];      /* BUG ??? */
717
295k
        buckets[b] = tp;
718
295k
    }
719
720
    /*
721
     * Initialise other internal structures
722
     */
723
724
3.21k
    max_modc = sizeof(module_map) / sizeof(module_map[0]) - 1;
725
70.6k
    for (i = 0; i < max_modc; ++i)
726
67.4k
        module_map[i].next = &(module_map[i + 1]);
727
3.21k
    module_map[max_modc].next = NULL;
728
3.21k
    module_map_head = module_map;
729
730
3.21k
    memset(nbuckets, 0, sizeof(nbuckets));
731
3.21k
    memset(tbuckets, 0, sizeof(tbuckets));
732
3.21k
    tc_alloc = TC_INCR;
733
3.21k
    tclist = calloc(tc_alloc, sizeof(struct tc));
734
3.21k
    build_translation_table();
735
3.21k
    init_tree_roots();          /* Set up initial roots */
736
    /*
737
     * Relies on 'add_mibdir' having set up the modules 
738
     */
739
3.21k
}
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
13.8k
{
752
13.8k
    struct node    *np, *nextp;
753
13.8k
    int             hash;
754
755
13.8k
    memset(nbuckets, 0, sizeof(nbuckets));
756
290k
    for (np = nodes; np;) {
757
277k
        nextp = np->next;
758
277k
        hash = NBUCKET(name_hash(np->parent));
759
277k
        np->next = nbuckets[hash];
760
277k
        nbuckets[hash] = np;
761
277k
        np = nextp;
762
277k
    }
763
13.8k
}
764
765
static int      erroneousMibs = 0;
766
767
netsnmp_feature_child_of(parse_get_error_count, netsnmp_unused);
768
#ifndef NETSNMP_FEATURE_REMOVE_PARSE_GET_ERROR_COUNT
769
int
770
get_mib_parse_error_count(void)
771
0
{
772
0
    return erroneousMibs;
773
0
}
774
#endif /* NETSNMP_FEATURE_REMOVE_PARSE_GET_ERROR_COUNT */
775
776
777
static void
778
print_error(const char *str, const char *token, int type)
779
442k
{
780
442k
    erroneousMibs++;
781
442k
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
782
442k
                                NETSNMP_DS_LIB_MIB_ERRORS))
783
276k
  return;
784
166k
    DEBUGMSGTL(("parse-mibs", "\n"));
785
166k
    if (type == ENDOFFILE)
786
372
        snmp_log(LOG_ERR, "%s (EOF): At line %d in %s\n", str, mibLine,
787
372
                 File);
788
166k
    else if (token && *token)
789
165k
        snmp_log(LOG_ERR, "%s (%s): At line %d in %s\n", str, token,
790
165k
                 mibLine, File);
791
458
    else
792
458
        snmp_log(LOG_ERR, "%s: At line %d in %s\n", str, mibLine, File);
793
166k
}
794
795
static void
796
print_module_not_found(const char *cp)
797
187k
{
798
187k
    if (first_err_module) {
799
10
        snmp_log(LOG_ERR, "MIB search path: %s\n",
800
10
                           netsnmp_get_mib_directory());
801
10
        first_err_module = 0;
802
10
    }
803
187k
    if (!last_err_module || strcmp(cp, last_err_module))
804
153k
        print_error("Cannot find module", cp, CONTINUE);
805
187k
    if (last_err_module)
806
181k
        free(last_err_module);
807
187k
    last_err_module = strdup(cp);
808
187k
}
809
810
static struct node *
811
alloc_node(int modid)
812
318k
{
813
318k
    struct node    *np;
814
815
318k
    np = calloc(1, sizeof(struct node));
816
318k
    if (!np)
817
0
        return NULL;
818
819
318k
    np->tc_index = -1;
820
318k
    np->modid = modid;
821
318k
    np->filename = strdup(File);
822
318k
    np->lineno = mibLine;
823
824
318k
    return np;
825
318k
}
826
827
static void
828
unlink_tbucket(struct tree *tp)
829
47.9k
{
830
47.9k
    int             hash = NBUCKET(name_hash(tp->label));
831
47.9k
    struct tree    *otp = NULL, *ntp = tbuckets[hash];
832
833
67.9k
    while (ntp && ntp != tp) {
834
19.9k
        otp = ntp;
835
19.9k
        ntp = ntp->next;
836
19.9k
    }
837
47.9k
    if (!ntp)
838
0
        snmp_log(LOG_EMERG, "Can't find %s in tbuckets\n", tp->label);
839
47.9k
    else if (otp)
840
8.41k
        otp->next = ntp->next;
841
39.5k
    else
842
39.5k
        tbuckets[hash] = tp->next;
843
47.9k
}
844
845
static void
846
unlink_tree(struct tree *tp)
847
35.6k
{
848
35.6k
    struct tree    *otp = NULL, *ntp = tp->parent;
849
850
35.6k
    if (!ntp) {                 /* this tree has no parent */
851
9.60k
        DEBUGMSGTL(("unlink_tree", "Tree node %s has no parent\n",
852
9.60k
                    tp->label));
853
26.0k
    } else {
854
26.0k
        ntp = ntp->child_list;
855
856
999k
        while (ntp && ntp != tp) {
857
973k
            otp = ntp;
858
973k
            ntp = ntp->next_peer;
859
973k
        }
860
26.0k
        if (!ntp)
861
0
            snmp_log(LOG_EMERG, "Can't find %s in %s's children\n",
862
0
                     tp->label, tp->parent->label);
863
26.0k
        else if (otp)
864
6.22k
            otp->next_peer = ntp->next_peer;
865
19.8k
        else
866
19.8k
            tp->parent->child_list = tp->next_peer;
867
26.0k
    }
868
869
35.6k
    if (tree_head == tp)
870
9.60k
        tree_head = tp->next_peer;
871
35.6k
}
872
873
static void
874
free_partial_tree(struct tree *tp, int keep_label)
875
150k
{
876
150k
    if (!tp)
877
0
        return;
878
879
    /*
880
     * remove the data from this tree node 
881
     */
882
150k
    free_enums(&tp->enums);
883
150k
    free_ranges(&tp->ranges);
884
150k
    free_indexes(&tp->indexes);
885
150k
    free_varbinds(&tp->varbinds);
886
150k
    if (!keep_label)
887
150k
        SNMP_FREE(tp->label);
888
150k
    SNMP_FREE(tp->hint);
889
150k
    SNMP_FREE(tp->units);
890
150k
    SNMP_FREE(tp->description);
891
150k
    SNMP_FREE(tp->reference);
892
150k
    SNMP_FREE(tp->augments);
893
150k
    SNMP_FREE(tp->defaultValue);
894
150k
}
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
39.7k
{
903
39.7k
    if (!Tree)
904
0
        return;
905
906
39.7k
    unlink_tbucket(Tree);
907
39.7k
    free_partial_tree(Tree, FALSE);
908
39.7k
    if (Tree->module_list != &Tree->modid)
909
935
        free(Tree->module_list);
910
39.7k
    free(Tree);
911
39.7k
}
912
913
static void
914
free_node(struct node *np)
915
249k
{
916
249k
    if (!np)
917
97
        return;
918
919
249k
    free_enums(&np->enums);
920
249k
    free_ranges(&np->ranges);
921
249k
    free_indexes(&np->indexes);
922
249k
    free_varbinds(&np->varbinds);
923
249k
    free(np->label);
924
249k
    free(np->hint);
925
249k
    free(np->units);
926
249k
    free(np->description);
927
249k
    free(np->reference);
928
249k
    free(np->defaultValue);
929
249k
    free(np->parent);
930
249k
    free(np->augments);
931
249k
    free(np->filename);
932
249k
    free(np);
933
249k
}
934
935
static void
936
print_range_value(FILE * fp, int type, struct range_list * rp)
937
0
{
938
0
    switch (type) {
939
0
    case TYPE_INTEGER:
940
0
    case TYPE_INTEGER32:
941
0
        if (rp->low == rp->high)
942
0
            fprintf(fp, "%d", rp->low);
943
0
        else
944
0
            fprintf(fp, "%d..%d", rp->low, rp->high);
945
0
        break;
946
0
    case TYPE_UNSIGNED32:
947
0
    case TYPE_OCTETSTR:
948
0
    case TYPE_GAUGE:
949
0
    case TYPE_UINTEGER:
950
0
        if (rp->low == rp->high)
951
0
            fprintf(fp, "%u", (unsigned)rp->low);
952
0
        else
953
0
            fprintf(fp, "%u..%u", (unsigned)rp->low, (unsigned)rp->high);
954
0
        break;
955
0
    default:
956
        /* No other range types allowed */
957
0
        break;
958
0
    }
959
0
}
960
961
#ifdef TEST
962
static void
963
print_nodes(FILE * fp, struct node *root)
964
{
965
    struct enum_list *ep;
966
    struct index_list *ip;
967
    struct varbind_list *vp;
968
    struct node    *np;
969
970
    for (np = root; np; np = np->next) {
971
        fprintf(fp, "%s ::= { %s %ld } (%d)\n", np->label, np->parent,
972
                np->subid, np->type);
973
        if (np->tc_index >= 0)
974
            fprintf(fp, "  TC = %s\n", tclist[np->tc_index].descriptor);
975
        if (np->enums) {
976
            fprintf(fp, "  Enums: \n");
977
            for (ep = np->enums; ep; ep = ep->next) {
978
                fprintf(fp, "    %s(%d)\n", ep->label, ep->value);
979
            }
980
        }
981
        if (np->ranges) {
982
            struct range_list *rp;
983
            fprintf(fp, "  Ranges: ");
984
            for (rp = np->ranges; rp; rp = rp->next) {
985
                fprintf(fp, "\n    ");
986
                print_range_value(fp, np->type, rp);
987
            }
988
            fprintf(fp, "\n");
989
        }
990
        if (np->indexes) {
991
            fprintf(fp, "  Indexes: \n");
992
            for (ip = np->indexes; ip; ip = ip->next) {
993
                fprintf(fp, "    %s\n", ip->ilabel);
994
            }
995
        }
996
        if (np->augments)
997
            fprintf(fp, "  Augments: %s\n", np->augments);
998
        if (np->varbinds) {
999
            fprintf(fp, "  Varbinds: \n");
1000
            for (vp = np->varbinds; vp; vp = vp->next) {
1001
                fprintf(fp, "    %s\n", vp->vblabel);
1002
            }
1003
        }
1004
        if (np->hint)
1005
            fprintf(fp, "  Hint: %s\n", np->hint);
1006
        if (np->units)
1007
            fprintf(fp, "  Units: %s\n", np->units);
1008
        if (np->defaultValue)
1009
            fprintf(fp, "  DefaultValue: %s\n", np->defaultValue);
1010
    }
1011
}
1012
#endif
1013
1014
void
1015
print_subtree(FILE * f, struct tree *tree, int count)
1016
0
{
1017
0
    struct tree    *tp;
1018
0
    int             i;
1019
0
    char            modbuf[256];
1020
1021
0
    for (i = 0; i < count; i++)
1022
0
        fprintf(f, "  ");
1023
0
    fprintf(f, "Children of %s(%ld):\n", tree->label, tree->subid);
1024
0
    count++;
1025
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1026
0
        for (i = 0; i < count; i++)
1027
0
            fprintf(f, "  ");
1028
0
        fprintf(f, "%s:%s(%ld) type=%d",
1029
0
                module_name(tp->module_list[0], modbuf),
1030
0
                tp->label, tp->subid, tp->type);
1031
0
        if (tp->tc_index != -1)
1032
0
            fprintf(f, " tc=%d", tp->tc_index);
1033
0
        if (tp->hint)
1034
0
            fprintf(f, " hint=%s", tp->hint);
1035
0
        if (tp->units)
1036
0
            fprintf(f, " units=%s", tp->units);
1037
0
        if (tp->number_modules > 1) {
1038
0
            fprintf(f, " modules:");
1039
0
            for (i = 1; i < tp->number_modules; i++)
1040
0
                fprintf(f, " %s", module_name(tp->module_list[i], modbuf));
1041
0
        }
1042
0
        fprintf(f, "\n");
1043
0
    }
1044
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1045
0
        if (tp->child_list)
1046
0
            print_subtree(f, tp, count);
1047
0
    }
1048
0
}
1049
1050
void
1051
print_ascii_dump_tree(FILE * f, struct tree *tree, int count)
1052
0
{
1053
0
    struct tree    *tp;
1054
1055
0
    count++;
1056
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1057
0
        fprintf(f, "%s OBJECT IDENTIFIER ::= { %s %ld }\n", tp->label,
1058
0
                tree->label, tp->subid);
1059
0
    }
1060
0
    for (tp = tree->child_list; tp; tp = tp->next_peer) {
1061
0
        if (tp->child_list)
1062
0
            print_ascii_dump_tree(f, tp, count);
1063
0
    }
1064
0
}
1065
1066
static int      translation_table[256];
1067
1068
static void
1069
build_translation_table(void)
1070
3.21k
{
1071
3.21k
    int             count;
1072
1073
824k
    for (count = 0; count < 256; count++) {
1074
821k
        switch (count) {
1075
3.21k
        case OBJID:
1076
3.21k
            translation_table[count] = TYPE_OBJID;
1077
3.21k
            break;
1078
3.21k
        case OCTETSTR:
1079
3.21k
            translation_table[count] = TYPE_OCTETSTR;
1080
3.21k
            break;
1081
3.21k
        case INTEGER:
1082
3.21k
            translation_table[count] = TYPE_INTEGER;
1083
3.21k
            break;
1084
3.21k
        case NETADDR:
1085
3.21k
            translation_table[count] = TYPE_NETADDR;
1086
3.21k
            break;
1087
3.21k
        case IPADDR:
1088
3.21k
            translation_table[count] = TYPE_IPADDR;
1089
3.21k
            break;
1090
3.21k
        case COUNTER:
1091
3.21k
            translation_table[count] = TYPE_COUNTER;
1092
3.21k
            break;
1093
3.21k
        case GAUGE:
1094
3.21k
            translation_table[count] = TYPE_GAUGE;
1095
3.21k
            break;
1096
3.21k
        case TIMETICKS:
1097
3.21k
            translation_table[count] = TYPE_TIMETICKS;
1098
3.21k
            break;
1099
3.21k
        case KW_OPAQUE:
1100
3.21k
            translation_table[count] = TYPE_OPAQUE;
1101
3.21k
            break;
1102
3.21k
        case NUL:
1103
3.21k
            translation_table[count] = TYPE_NULL;
1104
3.21k
            break;
1105
3.21k
        case COUNTER64:
1106
3.21k
            translation_table[count] = TYPE_COUNTER64;
1107
3.21k
            break;
1108
3.21k
        case BITSTRING:
1109
3.21k
            translation_table[count] = TYPE_BITSTRING;
1110
3.21k
            break;
1111
3.21k
        case NSAPADDRESS:
1112
3.21k
            translation_table[count] = TYPE_NSAPADDRESS;
1113
3.21k
            break;
1114
3.21k
        case INTEGER32:
1115
3.21k
            translation_table[count] = TYPE_INTEGER32;
1116
3.21k
            break;
1117
3.21k
        case UINTEGER32:
1118
3.21k
            translation_table[count] = TYPE_UINTEGER;
1119
3.21k
            break;
1120
3.21k
        case UNSIGNED32:
1121
3.21k
            translation_table[count] = TYPE_UNSIGNED32;
1122
3.21k
            break;
1123
3.21k
        case TRAPTYPE:
1124
3.21k
            translation_table[count] = TYPE_TRAPTYPE;
1125
3.21k
            break;
1126
3.21k
        case NOTIFTYPE:
1127
3.21k
            translation_table[count] = TYPE_NOTIFTYPE;
1128
3.21k
            break;
1129
3.21k
        case NOTIFGROUP:
1130
3.21k
            translation_table[count] = TYPE_NOTIFGROUP;
1131
3.21k
            break;
1132
3.21k
        case OBJGROUP:
1133
3.21k
            translation_table[count] = TYPE_OBJGROUP;
1134
3.21k
            break;
1135
3.21k
        case MODULEIDENTITY:
1136
3.21k
            translation_table[count] = TYPE_MODID;
1137
3.21k
            break;
1138
3.21k
        case OBJIDENTITY:
1139
3.21k
            translation_table[count] = TYPE_OBJIDENTITY;
1140
3.21k
            break;
1141
3.21k
        case AGENTCAP:
1142
3.21k
            translation_table[count] = TYPE_AGENTCAP;
1143
3.21k
            break;
1144
3.21k
        case COMPLIANCE:
1145
3.21k
            translation_table[count] = TYPE_MODCOMP;
1146
3.21k
            break;
1147
744k
        default:
1148
744k
            translation_table[count] = TYPE_OTHER;
1149
744k
            break;
1150
821k
        }
1151
821k
    }
1152
3.21k
}
1153
1154
static void
1155
init_tree_roots(void)
1156
3.21k
{
1157
3.21k
    struct tree    *tp, *lasttp;
1158
3.21k
    int             base_modid;
1159
3.21k
    int             hash;
1160
1161
3.21k
    base_modid = which_module("SNMPv2-SMI");
1162
3.21k
    if (base_modid == -1)
1163
3.21k
        base_modid = which_module("RFC1155-SMI");
1164
3.21k
    if (base_modid == -1)
1165
3.21k
        base_modid = which_module("RFC1213-MIB");
1166
1167
    /*
1168
     * build root node 
1169
     */
1170
3.21k
    tp = calloc(1, sizeof(struct tree));
1171
3.21k
    if (tp == NULL)
1172
0
        return;
1173
3.21k
    tp->label = strdup("joint-iso-ccitt");
1174
3.21k
    tp->modid = base_modid;
1175
3.21k
    tp->number_modules = 1;
1176
3.21k
    tp->module_list = &(tp->modid);
1177
3.21k
    tp->subid = 2;
1178
3.21k
    tp->tc_index = -1;
1179
3.21k
    set_function(tp);           /* from mib.c */
1180
3.21k
    hash = NBUCKET(name_hash(tp->label));
1181
3.21k
    tp->next = tbuckets[hash];
1182
3.21k
    tbuckets[hash] = tp;
1183
3.21k
    lasttp = tp;
1184
3.21k
    root_imports[0].label = strdup(tp->label);
1185
3.21k
    root_imports[0].modid = base_modid;
1186
1187
    /*
1188
     * build root node 
1189
     */
1190
3.21k
    tp = calloc(1, sizeof(struct tree));
1191
3.21k
    if (tp == NULL)
1192
0
        return;
1193
3.21k
    tp->next_peer = lasttp;
1194
3.21k
    tp->label = strdup("ccitt");
1195
3.21k
    tp->modid = base_modid;
1196
3.21k
    tp->number_modules = 1;
1197
3.21k
    tp->module_list = &(tp->modid);
1198
3.21k
    tp->subid = 0;
1199
3.21k
    tp->tc_index = -1;
1200
3.21k
    set_function(tp);           /* from mib.c */
1201
3.21k
    hash = NBUCKET(name_hash(tp->label));
1202
3.21k
    tp->next = tbuckets[hash];
1203
3.21k
    tbuckets[hash] = tp;
1204
3.21k
    lasttp = tp;
1205
3.21k
    root_imports[1].label = strdup(tp->label);
1206
3.21k
    root_imports[1].modid = base_modid;
1207
1208
    /*
1209
     * build root node 
1210
     */
1211
3.21k
    tp = calloc(1, sizeof(struct tree));
1212
3.21k
    if (tp == NULL)
1213
0
        return;
1214
3.21k
    tp->next_peer = lasttp;
1215
3.21k
    tp->label = strdup("iso");
1216
3.21k
    tp->modid = base_modid;
1217
3.21k
    tp->number_modules = 1;
1218
3.21k
    tp->module_list = &(tp->modid);
1219
3.21k
    tp->subid = 1;
1220
3.21k
    tp->tc_index = -1;
1221
3.21k
    set_function(tp);           /* from mib.c */
1222
3.21k
    hash = NBUCKET(name_hash(tp->label));
1223
3.21k
    tp->next = tbuckets[hash];
1224
3.21k
    tbuckets[hash] = tp;
1225
3.21k
    lasttp = tp;
1226
3.21k
    root_imports[2].label = strdup(tp->label);
1227
3.21k
    root_imports[2].modid = base_modid;
1228
1229
3.21k
    tree_head = tp;
1230
3.21k
}
1231
1232
#ifdef STRICT_MIB_PARSEING
1233
#define label_compare strcasecmp
1234
#else
1235
7.17G
#define label_compare strcmp
1236
#endif
1237
1238
1239
struct tree    *
1240
find_tree_node(const char *name, int modid)
1241
1.04M
{
1242
1.04M
    struct tree    *tp, *headtp;
1243
1.04M
    int             count, *int_p;
1244
1245
1.04M
    if (!name || !*name)
1246
50.0k
        return (NULL);
1247
1248
991k
    headtp = tbuckets[NBUCKET(name_hash(name))];
1249
181M
    for (tp = headtp; tp; tp = tp->next) {
1250
181M
        if (tp->label && !label_compare(tp->label, name)) {
1251
1252
19.5M
            if (modid == -1)    /* Any module */
1253
235k
                return (tp);
1254
1255
19.2M
            for (int_p = tp->module_list, count = 0;
1256
54.6M
                 count < tp->number_modules; ++count, ++int_p)
1257
35.6M
                if (*int_p == modid)
1258
236k
                    return (tp);
1259
19.2M
        }
1260
181M
    }
1261
1262
520k
    return (NULL);
1263
991k
}
1264
1265
/*
1266
 * computes a value which represents how close name1 is to name2.
1267
 * * high scores mean a worse match.
1268
 * * (yes, the algorithm sucks!)
1269
 */
1270
2.43k
#define MAX_BAD 0xffffff
1271
1272
static          u_int
1273
compute_match(const char *search_base, const char *key)
1274
1.43k
{
1275
1.43k
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
1276
1.43k
    int             rc;
1277
1.43k
    regex_t         parsetree;
1278
1.43k
    regmatch_t      pmatch;
1279
1.43k
    rc = regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED);
1280
1.43k
    if (rc == 0)
1281
1.35k
        rc = regexec(&parsetree, search_base, 1, &pmatch, 0);
1282
1.43k
    regfree(&parsetree);
1283
1.43k
    if (rc == 0) {
1284
        /*
1285
         * found 
1286
         */
1287
71
        return pmatch.rm_so;
1288
71
    }
1289
#else                           /* use our own wildcard matcher */
1290
    /*
1291
     * first find the longest matching substring (ick) 
1292
     */
1293
    char           *first = NULL, *result = NULL, *entry;
1294
    const char     *position;
1295
    char           *newkey = strdup(key);
1296
    char           *st;
1297
1298
1299
    entry = strtok_r(newkey, "*", &st);
1300
    position = search_base;
1301
    while (entry) {
1302
        result = strcasestr(position, entry);
1303
1304
        if (result == NULL) {
1305
            free(newkey);
1306
            return MAX_BAD;
1307
        }
1308
1309
        if (first == NULL)
1310
            first = result;
1311
1312
        position = result + strlen(entry);
1313
        entry = strtok_r(NULL, "*", &st);
1314
    }
1315
    free(newkey);
1316
    if (result)
1317
        return (first - search_base);
1318
#endif
1319
1320
    /*
1321
     * not found 
1322
     */
1323
1.35k
    return MAX_BAD;
1324
1.43k
}
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
536
{
1342
536
    struct tree    *tp, *best_so_far = NULL, *retptr;
1343
536
    u_int           old_match = MAX_BAD, new_match = MAX_BAD;
1344
1345
536
    if (!pattrn || !*pattrn)
1346
4
        return (NULL);
1347
1348
532
    if (!tree_top)
1349
51
        tree_top = get_tree_head();
1350
1351
1.94k
    for (tp = tree_top; tp; tp = tp->next_peer) {
1352
1.43k
        if (!tp->reported && tp->label)
1353
1.43k
            new_match = compute_match(tp->label, pattrn);
1354
1.43k
        tp->reported = 1;
1355
1356
1.43k
        if (new_match < old_match) {
1357
58
            best_so_far = tp;
1358
58
            old_match = new_match;
1359
58
        }
1360
1.43k
        if (new_match == 0)
1361
17
            break;              /* this is the best result we can get */
1362
1.41k
        if (tp->child_list) {
1363
0
            retptr =
1364
0
                find_best_tree_node(pattrn, tp->child_list, &new_match);
1365
0
            if (new_match < old_match) {
1366
0
                best_so_far = retptr;
1367
0
                old_match = new_match;
1368
0
            }
1369
0
            if (new_match == 0)
1370
0
                break;          /* this is the best result we can get */
1371
0
        }
1372
1.41k
    }
1373
532
    if (match)
1374
0
        *match = old_match;
1375
532
    return (best_so_far);
1376
536
}
1377
1378
1379
static void
1380
merge_anon_children(struct tree *tp1, struct tree *tp2)
1381
                /*
1382
                 * NB: tp1 is the 'anonymous' node 
1383
                 */
1384
16.1k
{
1385
16.1k
    struct tree    *child1, *child2, *previous;
1386
1387
30.8k
    for (child1 = tp1->child_list; child1;) {
1388
1389
14.7k
        for (child2 = tp2->child_list, previous = NULL;
1390
61.7k
             child2; previous = child2, child2 = child2->next_peer) {
1391
1392
55.2k
            if (child1->subid == child2->subid) {
1393
                /*
1394
                 * Found 'matching' children,
1395
                 *  so merge them
1396
                 */
1397
48.6k
                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
48.6k
                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
48.6k
                } else if (!label_compare(child1->label, child2->label)) {
1425
40.4k
                    if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1426
40.4k
             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
40.4k
                    continue;
1433
40.4k
                } else {
1434
                    /*
1435
                     * Two copies of the same node.
1436
                     * 'child2' adopts the children of 'child1'
1437
                     */
1438
1439
8.19k
                    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
8.19k
                        child2->child_list = child1->child_list;
1444
8.19k
                    for (previous = child1->child_list;
1445
14.9k
                         previous; previous = previous->next_peer)
1446
6.76k
                        previous->parent = child2;
1447
8.19k
                    child1->child_list = NULL;
1448
1449
8.19k
                    previous = child1;  /* Finished with 'child1' */
1450
8.19k
                    child1 = child1->next_peer;
1451
8.19k
                    free_tree(previous);
1452
8.19k
                    goto next;
1453
8.19k
                }
1454
48.6k
            }
1455
55.2k
        }
1456
        /*
1457
         * If no match, move 'child1' to 'tp2' child_list
1458
         */
1459
6.50k
        if (child1) {
1460
6.50k
            previous = child1;
1461
6.50k
            child1 = child1->next_peer;
1462
6.50k
            previous->parent = tp2;
1463
6.50k
            previous->next_peer = tp2->child_list;
1464
6.50k
            tp2->child_list = previous;
1465
6.50k
        }
1466
14.7k
      next:;
1467
14.7k
    }
1468
16.1k
}
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
657k
{
1478
657k
    struct tree    *tp, *anon_tp = NULL;
1479
657k
    struct tree    *xroot = root;
1480
657k
    struct node    *np, **headp;
1481
657k
    struct node    *oldnp = NULL, *child_list = NULL, *childp = NULL;
1482
657k
    int             hash;
1483
657k
    int            *int_p;
1484
1485
55.9M
    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
55.2M
        xroot = xroot->next_peer;
1491
55.2M
    }
1492
1493
657k
    tp = root;
1494
657k
    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
899k
    for (np = *headp; np; np = np->next) {
1500
241k
        if (!label_compare(tp->label, np->parent)) {
1501
            /*
1502
             * take this node out of the node list 
1503
             */
1504
157k
            if (oldnp == NULL) {
1505
128k
                *headp = np->next;      /* fix root of node list */
1506
128k
            } else {
1507
29.8k
                oldnp->next = np->next; /* link around this node */
1508
29.8k
            }
1509
157k
            if (child_list)
1510
56.2k
                childp->next = np;
1511
101k
            else
1512
101k
                child_list = np;
1513
157k
            childp = np;
1514
157k
        } else {
1515
83.6k
            oldnp = np;
1516
83.6k
        }
1517
1518
241k
    }
1519
657k
    if (childp)
1520
101k
        childp->next = NULL;
1521
    /*
1522
     * Take each element in the child list and place it into the tree.
1523
     */
1524
815k
    for (np = child_list; np; np = np->next) {
1525
157k
        struct tree    *otp = NULL;
1526
157k
        struct tree    *xxroot = xroot;
1527
157k
        anon_tp = NULL;
1528
157k
        tp = xroot->child_list;
1529
1530
157k
        if (np->subid == -1) {
1531
            /*
1532
             * name ::= { parent } 
1533
             */
1534
1.25k
            np->subid = xroot->subid;
1535
1.25k
            tp = xroot;
1536
1.25k
            xxroot = xroot->parent;
1537
1.25k
        }
1538
1539
1.42M
        while (tp) {
1540
1.38M
            if (tp->subid == np->subid)
1541
112k
                break;
1542
1.26M
            else {
1543
1.26M
                otp = tp;
1544
1.26M
                tp = tp->next_peer;
1545
1.26M
            }
1546
1.38M
        }
1547
157k
        if (tp) {
1548
112k
            if (!label_compare(tp->label, np->label)) {
1549
                /*
1550
                 * Update list of modules 
1551
                 */
1552
51.0k
                int_p = malloc((tp->number_modules + 1) * sizeof(int));
1553
51.0k
                if (int_p == NULL)
1554
0
                    return;
1555
51.0k
                memcpy(int_p, tp->module_list,
1556
51.0k
                       tp->number_modules * sizeof(int));
1557
51.0k
                int_p[tp->number_modules] = np->modid;
1558
51.0k
                if (tp->module_list != &tp->modid)
1559
36.3k
                    free(tp->module_list);
1560
51.0k
                ++tp->number_modules;
1561
51.0k
                tp->module_list = int_p;
1562
1563
51.0k
                if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
1564
51.0k
             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
51.0k
                do_subtree(tp, nodes);
1574
51.0k
                continue;
1575
51.0k
            }
1576
61.7k
            if (!strncmp(np->label, ANON, ANON_LEN) ||
1577
61.7k
                !strncmp(tp->label, ANON, ANON_LEN)) {
1578
16.3k
                anon_tp = tp;   /* Need to merge these two trees later */
1579
45.3k
            } else if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1580
45.3k
            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
61.7k
        }
1587
1588
106k
        tp = calloc(1, sizeof(struct tree));
1589
106k
        if (tp == NULL)
1590
0
            return;
1591
106k
        tp->parent = xxroot;
1592
106k
        tp->modid = np->modid;
1593
106k
        tp->number_modules = 1;
1594
106k
        tp->module_list = &(tp->modid);
1595
106k
        tree_from_node(tp, np);
1596
106k
        if (!otp && !xxroot) {
1597
257
          free(tp);
1598
257
          return;
1599
257
        }
1600
106k
        tp->next_peer = otp ? otp->next_peer : xxroot->child_list;
1601
106k
        if (otp)
1602
16.9k
            otp->next_peer = tp;
1603
89.6k
        else
1604
89.6k
            xxroot->child_list = tp;
1605
106k
        hash = NBUCKET(name_hash(tp->label));
1606
106k
        tp->next = tbuckets[hash];
1607
106k
        tbuckets[hash] = tp;
1608
106k
        do_subtree(tp, nodes);
1609
1610
106k
        if (anon_tp) {
1611
16.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
12.0k
                merge_anon_children(tp, anon_tp);
1617
1618
                /*
1619
                 * unlink and destroy tp 
1620
                 */
1621
12.0k
                unlink_tree(tp);
1622
12.0k
                free_tree(tp);
1623
12.0k
            } else if (!strncmp(anon_tp->label, ANON, ANON_LEN)) {
1624
4.09k
                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
4.09k
                merge_anon_children(anon_tp, tp);
1631
1632
                /*
1633
                 * unlink anon_tp from the hash 
1634
                 */
1635
4.09k
                unlink_tbucket(anon_tp);
1636
1637
                /*
1638
                 * get rid of old contents of anon_tp 
1639
                 */
1640
4.09k
                free_partial_tree(anon_tp, FALSE);
1641
1642
                /*
1643
                 * put in the current information 
1644
                 */
1645
4.09k
                anon_tp->label = tp->label;
1646
4.09k
                anon_tp->child_list = tp->child_list;
1647
4.09k
                anon_tp->modid = tp->modid;
1648
4.09k
                anon_tp->tc_index = tp->tc_index;
1649
4.09k
                anon_tp->type = tp->type;
1650
4.09k
                anon_tp->enums = tp->enums;
1651
4.09k
                anon_tp->indexes = tp->indexes;
1652
4.09k
                anon_tp->augments = tp->augments;
1653
4.09k
                anon_tp->varbinds = tp->varbinds;
1654
4.09k
                anon_tp->ranges = tp->ranges;
1655
4.09k
                anon_tp->hint = tp->hint;
1656
4.09k
                anon_tp->units = tp->units;
1657
4.09k
                anon_tp->description = tp->description;
1658
4.09k
                anon_tp->reference = tp->reference;
1659
4.09k
                anon_tp->defaultValue = tp->defaultValue;
1660
4.09k
                anon_tp->parent = tp->parent;
1661
1662
4.09k
                set_function(anon_tp);
1663
1664
                /*
1665
                 * update parent pointer in moved children 
1666
                 */
1667
4.09k
                ntp = anon_tp->child_list;
1668
10.6k
                while (ntp) {
1669
6.50k
                    ntp->parent = anon_tp;
1670
6.50k
                    ntp = ntp->next_peer;
1671
6.50k
                }
1672
1673
                /*
1674
                 * hash in anon_tp in its new place 
1675
                 */
1676
4.09k
                hash = NBUCKET(name_hash(anon_tp->label));
1677
4.09k
                anon_tp->next = tbuckets[hash];
1678
4.09k
                tbuckets[hash] = anon_tp;
1679
1680
                /*
1681
                 * unlink and destroy tp 
1682
                 */
1683
4.09k
                unlink_tbucket(tp);
1684
4.09k
                unlink_tree(tp);
1685
4.09k
                free(tp);
1686
4.09k
            } else {
1687
                /*
1688
                 * Uh?  One of these two should have been anonymous! 
1689
                 */
1690
171
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
1691
171
               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
171
            }
1697
16.3k
            anon_tp = NULL;
1698
16.3k
        }
1699
106k
    }
1700
    /*
1701
     * free all nodes that were copied into tree 
1702
     */
1703
657k
    oldnp = NULL;
1704
815k
    for (np = child_list; np; np = np->next) {
1705
157k
        if (oldnp)
1706
56.2k
            free_node(oldnp);
1707
157k
        oldnp = np;
1708
157k
    }
1709
657k
    if (oldnp)
1710
101k
        free_node(oldnp);
1711
657k
}
1712
1713
static void
1714
do_linkup(struct module *mp, struct node *np)
1715
10.6k
{
1716
10.6k
    struct module_import *mip;
1717
10.6k
    struct node    *onp, *oldp, *newp;
1718
10.6k
    struct tree    *tp;
1719
10.6k
    int             i, more;
1720
    /*
1721
     * All modules implicitly import
1722
     *   the roots of the tree
1723
     */
1724
10.6k
    if (snmp_get_do_debugging() > 1)
1725
0
        dump_module_list();
1726
10.6k
    DEBUGMSGTL(("parse-mibs", "Processing IMPORTS for module %d %s\n",
1727
10.6k
                mp->modid, mp->name));
1728
10.6k
    if (mp->no_imports == 0) {
1729
954
        mp->no_imports = NUMBER_OF_ROOT_NODES;
1730
954
        mp->imports = root_imports;
1731
954
    }
1732
1733
    /*
1734
     * Build the tree
1735
     */
1736
10.6k
    init_node_hash(np);
1737
1.28M
    for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
1738
1.27M
        char            modbuf[256];
1739
1.27M
        DEBUGMSGTL(("parse-mibs", "  Processing import: %s\n",
1740
1.27M
                    mip->label));
1741
1.27M
        if (get_tc_index(mip->label, mip->modid) != -1)
1742
334k
            continue;
1743
939k
        tp = find_tree_node(mip->label, mip->modid);
1744
939k
        if (!tp) {
1745
469k
      if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_ERRORS))
1746
350
                snmp_log(LOG_WARNING,
1747
350
                         "Did not find '%s' in module %s (%s)\n",
1748
350
                         mip->label, module_name(mip->modid, modbuf),
1749
350
                         File);
1750
469k
            continue;
1751
469k
        }
1752
469k
        do_subtree(tp, &np);
1753
469k
    }
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
10.6k
    if (!np)
1762
657
        return;
1763
39.8k
    for (tp = tree_head; tp; tp = tp->next_peer)
1764
29.8k
        do_subtree(tp, &np);
1765
9.95k
    if (!np)
1766
0
        return;
1767
1768
    /*
1769
     * quietly move all internal references to the orphan list 
1770
     */
1771
9.95k
    oldp = orphan_nodes;
1772
11.0k
    do {
1773
1.42M
        for (i = 0; i < NHASHSIZE; i++)
1774
3.84M
            for (onp = nbuckets[i]; onp; onp = onp->next) {
1775
2.43M
                struct node    *op = NULL;
1776
2.43M
                int             hash = NBUCKET(name_hash(onp->label));
1777
2.43M
                np = nbuckets[hash];
1778
2.50M
                while (np) {
1779
74.1k
                    if (label_compare(onp->label, np->parent)) {
1780
58.4k
                        op = np;
1781
58.4k
                        np = np->next;
1782
58.4k
                    } else {
1783
15.7k
                        if (op)
1784
955
                            op->next = np->next;
1785
14.7k
                        else
1786
14.7k
                            nbuckets[hash] = np->next;
1787
15.7k
      DEBUGMSGTL(("parse-mibs", "Moving %s to orphanage", np->label));
1788
15.7k
                        np->next = orphan_nodes;
1789
15.7k
                        orphan_nodes = np;
1790
15.7k
                        op = NULL;
1791
15.7k
                        np = nbuckets[hash];
1792
15.7k
                    }
1793
74.1k
                }
1794
2.43M
            }
1795
11.0k
        newp = orphan_nodes;
1796
11.0k
        more = 0;
1797
30.6k
        for (onp = orphan_nodes; onp != oldp; onp = onp->next) {
1798
19.5k
            struct node    *op = NULL;
1799
19.5k
            int             hash = NBUCKET(name_hash(onp->label));
1800
19.5k
            np = nbuckets[hash];
1801
25.1k
            while (np) {
1802
5.60k
                if (label_compare(onp->label, np->parent)) {
1803
1.73k
                    op = np;
1804
1.73k
                    np = np->next;
1805
3.86k
                } else {
1806
3.86k
                    if (op)
1807
211
                        op->next = np->next;
1808
3.65k
                    else
1809
3.65k
                        nbuckets[hash] = np->next;
1810
3.86k
                    np->next = orphan_nodes;
1811
3.86k
                    orphan_nodes = np;
1812
3.86k
                    op = NULL;
1813
3.86k
                    np = nbuckets[hash];
1814
3.86k
                    more = 1;
1815
3.86k
                }
1816
5.60k
            }
1817
19.5k
        }
1818
11.0k
        oldp = newp;
1819
11.0k
    } while (more);
1820
1821
    /*
1822
     * complain about left over nodes 
1823
     */
1824
134M
    for (np = orphan_nodes; np && np->next; np = np->next);     /* find the end of the orphan list */
1825
1.28M
    for (i = 0; i < NHASHSIZE; i++)
1826
1.27M
        if (nbuckets[i]) {
1827
5.05k
            if (orphan_nodes)
1828
5.05k
                onp = np->next = nbuckets[i];
1829
1
            else
1830
1
                onp = orphan_nodes = nbuckets[i];
1831
5.05k
            nbuckets[i] = NULL;
1832
12.1k
            while (onp) {
1833
7.09k
                snmp_log(LOG_WARNING,
1834
7.09k
                         "Cannot resolve OID in %s: %s ::= { %s %ld } at line %d in %s\n",
1835
7.09k
                         (mp->name ? mp->name : "<no module>"),
1836
7.09k
                         (onp->label ? onp->label : "<no label>"),
1837
7.09k
                         (onp->parent ? onp->parent : "<no parent>"),
1838
7.09k
                         onp->subid, onp->lineno, onp->filename);
1839
7.09k
                np = onp;
1840
7.09k
                onp = onp->next;
1841
7.09k
            }
1842
5.05k
        }
1843
9.95k
    return;
1844
9.95k
}
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
62.1k
{
1861
62.1k
    struct subid_s *id = id_arg;
1862
62.1k
    int             i, count, type;
1863
62.1k
    char            token[MAXTOKEN];
1864
1865
62.1k
    if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET) {
1866
1.48k
        print_error("Expected \"{\"", token, type);
1867
1.48k
        return 0;
1868
1.48k
    }
1869
60.6k
    type = get_token(fp, token, MAXTOKEN);
1870
398k
    for (count = 0; count < length; count++, id++) {
1871
398k
        id->label = NULL;
1872
398k
        id->modid = current_module;
1873
398k
        id->subid = -1;
1874
398k
        if (type == RIGHTBRACKET)
1875
59.4k
            return count;
1876
339k
        if (type == LABEL) {
1877
            /*
1878
             * this entry has a label 
1879
             */
1880
262k
            id->label = strdup(token);
1881
262k
            type = get_token(fp, token, MAXTOKEN);
1882
262k
            if (type == LEFTPAREN) {
1883
264
                type = get_token(fp, token, MAXTOKEN);
1884
264
                if (type == NUMBER) {
1885
157
                    id->subid = strtoul(token, NULL, 10);
1886
157
                    if ((type =
1887
157
                         get_token(fp, token, MAXTOKEN)) != RIGHTPAREN) {
1888
80
                        print_error("Expected a closing parenthesis",
1889
80
                                    token, type);
1890
80
                        goto free_labels;
1891
80
                    }
1892
157
                } else {
1893
107
                    print_error("Expected a number", token, type);
1894
107
                    goto free_labels;
1895
107
                }
1896
262k
            } else {
1897
262k
                continue;
1898
262k
            }
1899
262k
        } else if (type == NUMBER) {
1900
            /*
1901
             * this entry  has just an integer sub-identifier 
1902
             */
1903
75.9k
            id->subid = strtoul(token, NULL, 10);
1904
75.9k
        } else {
1905
765
            print_error("Expected label or number", token, type);
1906
765
            goto free_labels;
1907
765
        }
1908
76.0k
        type = get_token(fp, token, MAXTOKEN);
1909
76.0k
    }
1910
308
    print_error("Too long OID", token, type);
1911
308
    --count;
1912
1913
1.26k
free_labels:
1914
16.1k
    for (i = 0; i <= count; i++) {
1915
14.8k
        free(id_arg[i].label);
1916
14.8k
        id_arg[i].label = NULL;
1917
14.8k
    }
1918
1919
1.26k
    return 0;
1920
308
}
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
62.1k
{
1947
62.1k
    register int    count;
1948
62.1k
    register struct subid_s *op, *nop;
1949
62.1k
    int             length;
1950
62.1k
    struct subid_s  loid[32];
1951
62.1k
    struct node    *np, *root = NULL, *oldnp = NULL;
1952
62.1k
    struct tree    *tp;
1953
1954
62.1k
    if ((length = getoid(fp, loid, 32)) == 0) {
1955
2.75k
        print_error("Bad object identifier", NULL, CONTINUE);
1956
2.75k
        return NULL;
1957
2.75k
    }
1958
1959
    /*
1960
     * Handle numeric-only object identifiers,
1961
     *  by labeling the first sub-identifier
1962
     */
1963
59.3k
    op = loid;
1964
59.3k
    if (!op->label) {
1965
7.68k
        if (length == 1) {
1966
80
            print_error("Attempt to define a root oid", name, OBJECT);
1967
80
            return NULL;
1968
80
        }
1969
16.1k
        for (tp = tree_head; tp; tp = tp->next_peer)
1970
15.6k
            if ((int) tp->subid == op->subid) {
1971
7.06k
                op->label = strdup(tp->label);
1972
7.06k
                break;
1973
7.06k
            }
1974
7.60k
    }
1975
1976
    /*
1977
     * Handle  "label OBJECT-IDENTIFIER ::= { subid }"
1978
     */
1979
59.3k
    if (length == 1) {
1980
8.50k
        op = loid;
1981
8.50k
        np = alloc_node(op->modid);
1982
8.50k
        if (np == NULL)
1983
0
            return (NULL);
1984
8.50k
        np->subid = op->subid;
1985
8.50k
        np->label = strdup(name);
1986
8.50k
        np->parent = op->label;
1987
8.50k
        return np;
1988
8.50k
    }
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
315k
    for (count = 0, op = loid, nop = loid + 1; count < (length - 1);
1995
264k
         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
264k
        if (op->label && (nop->label || (nop->subid != -1))) {
2003
255k
            np = alloc_node(nop->modid);
2004
255k
            if (np == NULL)
2005
0
                goto err;
2006
255k
            if (root == NULL) {
2007
50.7k
                root = np;
2008
205k
            } else {
2009
205k
                netsnmp_assert(oldnp);
2010
205k
                oldnp->next = np;
2011
205k
            }
2012
255k
            oldnp = np;
2013
2014
255k
            np->parent = strdup(op->label);
2015
255k
            if (count == (length - 2)) {
2016
                /*
2017
                 * The name for this node is the label for this entry 
2018
                 */
2019
47.1k
                np->label = strdup(name);
2020
47.1k
                if (np->label == NULL)
2021
0
                    goto err;
2022
208k
            } else {
2023
208k
                if (!nop->label) {
2024
29.8k
                    if (asprintf(&nop->label, "%s%d", ANON, anonymous++) < 0)
2025
0
                        goto err;
2026
29.8k
                }
2027
208k
                np->label = strdup(nop->label);
2028
208k
            }
2029
255k
            if (nop->subid != -1)
2030
61.9k
                np->subid = nop->subid;
2031
193k
            else
2032
193k
                print_error("Warning: This entry is pretty silly",
2033
193k
                            np->label, CONTINUE);
2034
255k
        }                       /* end if(op->label... */
2035
264k
    }
2036
2037
50.8k
out:
2038
    /*
2039
     * free the loid array 
2040
     */
2041
366k
    for (count = 0, op = loid; count < length; count++, op++) {
2042
315k
        free(op->label);
2043
315k
        op->label = NULL;
2044
315k
    }
2045
2046
50.8k
    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
50.8k
}
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
16.2k
{
2062
16.2k
    int             i;
2063
16.2k
    struct tc      *tcp;
2064
2065
16.2k
    i = get_tc_index(descriptor, modid);
2066
16.2k
    if (tc_index)
2067
6.78k
        *tc_index = i;
2068
16.2k
    if (i != -1) {
2069
1.50k
        tcp = &tclist[i];
2070
1.50k
        if (ep) {
2071
506
            free_enums(ep);
2072
506
            *ep = copy_enums(tcp->enums);
2073
506
        }
2074
1.50k
        if (rp) {
2075
506
            free_ranges(rp);
2076
506
            *rp = copy_ranges(tcp->ranges);
2077
506
        }
2078
1.50k
        if (hint) {
2079
506
            if (*hint)
2080
0
                free(*hint);
2081
506
            *hint = (tcp->hint ? strdup(tcp->hint) : NULL);
2082
506
        }
2083
1.50k
        return tcp->type;
2084
1.50k
    }
2085
14.7k
    return LABEL;
2086
16.2k
}
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.29M
{
2095
1.29M
    int             i;
2096
1.29M
    struct tc      *tcp;
2097
1.29M
    struct module  *mp;
2098
1.29M
    struct module_import *mip;
2099
2100
    /*
2101
     * Check that the descriptor isn't imported
2102
     *  by searching the import list
2103
     */
2104
2105
8.89G
    for (mp = module_head; mp; mp = mp->next)
2106
8.89G
        if (mp->modid == modid)
2107
648k
            break;
2108
1.29M
    if (mp)
2109
37.8M
        for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
2110
37.8M
            if (!label_compare(mip->label, descriptor)) {
2111
                /*
2112
                 * Found it - so amend the module ID 
2113
                 */
2114
632k
                modid = mip->modid;
2115
632k
                break;
2116
632k
            }
2117
37.8M
        }
2118
2119
2120
6.50G
    for (i = 0, tcp = tclist; i < tc_alloc; i++, tcp++) {
2121
6.50G
        if (tcp->type == 0)
2122
954k
            break;
2123
6.50G
        if (!label_compare(descriptor, tcp->descriptor) &&
2124
6.50G
            ((modid == tcp->modid) || (modid == -1))) {
2125
336k
            return i;
2126
336k
        }
2127
6.50G
    }
2128
954k
    return -1;
2129
1.29M
}
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
7.39k
{
2166
7.39k
    register int    type;
2167
7.39k
    char            token[MAXTOKEN];
2168
7.39k
    struct enum_list *ep = NULL, **epp = &ep;
2169
2170
7.39k
    free_enums(retp);
2171
2172
19.3k
    while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
2173
19.2k
        if (type == RIGHTBRACKET)
2174
6.52k
            break;
2175
        /* some enums use "deprecated" to indicate a no longer value label */
2176
        /* (EG: IP-MIB's IpAddressStatusTC) */
2177
12.7k
        if (type == LABEL || type == DEPRECATED) {
2178
            /*
2179
             * this is an enumerated label 
2180
             */
2181
7.28k
            *epp = calloc(1, sizeof(struct enum_list));
2182
7.28k
            if (*epp == NULL)
2183
0
                return (NULL);
2184
            /*
2185
             * a reasonable approximation for the length 
2186
             */
2187
7.28k
            (*epp)->label = strdup(token);
2188
7.28k
            type = get_token(fp, token, MAXTOKEN);
2189
7.28k
            if (type != LEFTPAREN) {
2190
628
                print_error("Expected \"(\"", token, type);
2191
628
                goto err;
2192
628
            }
2193
6.66k
            type = get_token(fp, token, MAXTOKEN);
2194
6.66k
            if (type != NUMBER) {
2195
87
                print_error("Expected integer", token, type);
2196
87
                goto err;
2197
87
            }
2198
6.57k
            (*epp)->value = strtol(token, NULL, 10);
2199
6.57k
            (*epp)->lineno = mibLine;
2200
6.57k
            type = get_token(fp, token, MAXTOKEN);
2201
6.57k
            if (type != RIGHTPAREN) {
2202
104
                print_error("Expected \")\"", token, type);
2203
104
                goto err;
2204
6.46k
            } else {
2205
6.46k
                struct enum_list *op = ep;
2206
35.7k
                while (op != *epp) {
2207
30.1k
                    if (strcmp((*epp)->label, op->label) == 0) {
2208
382
                        snmp_log(LOG_ERR,
2209
382
                            "Duplicate enum label '%s' at line %d in %s. First at line %d\n",
2210
382
                            (*epp)->label, mibLine, File, op->lineno);
2211
382
                        erroneousMibs++;
2212
382
                        break;
2213
382
                    }
2214
29.7k
                    else if ((*epp)->value == op->value) {
2215
459
                        snmp_log(LOG_ERR,
2216
459
                            "Duplicate enum value '%d' at line %d in %s. First at line %d\n",
2217
459
                            (*epp)->value, mibLine, File, op->lineno);
2218
459
                        erroneousMibs++;
2219
459
                        break;
2220
459
                    }
2221
29.2k
                    op = op->next;
2222
29.2k
                }
2223
6.46k
            }
2224
6.46k
            epp = &(*epp)->next;
2225
6.46k
        }
2226
12.7k
    }
2227
6.57k
    if (type == ENDOFFILE) {
2228
56
        print_error("Expected \"}\"", token, type);
2229
56
        goto err;
2230
56
    }
2231
6.52k
    *retp = ep;
2232
6.52k
    return ep;
2233
2234
875
err:
2235
875
    free_enums(&ep);
2236
875
    return NULL;
2237
6.57k
}
2238
2239
static struct range_list *
2240
parse_ranges(FILE * fp, struct range_list **retp)
2241
4.50k
{
2242
4.50k
    int             low, high;
2243
4.50k
    char            nexttoken[MAXTOKEN];
2244
4.50k
    int             nexttype;
2245
4.50k
    struct range_list *rp = NULL, **rpp = &rp;
2246
4.50k
    int             size = 0, taken = 1;
2247
2248
4.50k
    free_ranges(retp);
2249
2250
4.50k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
2251
4.50k
    if (nexttype == SIZE) {
2252
1.37k
        size = 1;
2253
1.37k
        taken = 0;
2254
1.37k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2255
1.37k
        if (nexttype != LEFTPAREN)
2256
296
            print_error("Expected \"(\" after SIZE", nexttoken, nexttype);
2257
1.37k
    }
2258
2259
6.10k
    do {
2260
6.10k
        if (!taken)
2261
2.97k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2262
3.12k
        else
2263
3.12k
            taken = 0;
2264
6.10k
        high = low = strtoul(nexttoken, NULL, 10);
2265
6.10k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2266
6.10k
        if (nexttype == RANGE) {
2267
3.64k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2268
3.64k
            errno = 0;
2269
3.64k
            high = strtoul(nexttoken, NULL, 10);
2270
3.64k
            if ( errno == ERANGE ) {
2271
603
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
2272
603
                                       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
603
            }
2277
3.64k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2278
3.64k
        }
2279
6.10k
        *rpp = (struct range_list *) calloc(1, sizeof(struct range_list));
2280
6.10k
        if (*rpp == NULL)
2281
0
            break;
2282
6.10k
        (*rpp)->low = low;
2283
6.10k
        (*rpp)->high = high;
2284
6.10k
        rpp = &(*rpp)->next;
2285
2286
6.10k
    } while (nexttype == BAR);
2287
4.50k
    if (size) {
2288
1.37k
        if (nexttype != RIGHTPAREN)
2289
296
            print_error("Expected \")\" after SIZE", nexttoken, nexttype);
2290
1.37k
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2291
1.37k
    }
2292
4.50k
    if (nexttype != RIGHTPAREN)
2293
636
        print_error("Expected \")\"", nexttoken, nexttype);
2294
2295
4.50k
    *retp = rp;
2296
4.50k
    return rp;
2297
4.50k
}
2298
2299
/*
2300
 * Parses an asn type.  Structures are ignored by this parser.
2301
 * Returns NULL on error.
2302
 */
2303
static struct node *
2304
parse_asntype(FILE * fp, char *name, int *ntype, char *ntoken)
2305
40.6k
{
2306
40.6k
    int             type, i;
2307
40.6k
    char            token[MAXTOKEN];
2308
40.6k
    char            quoted_string_buffer[MAXQUOTESTR];
2309
40.6k
    char           *hint = NULL;
2310
40.6k
    char           *descr = NULL;
2311
40.6k
    struct tc      *tcp;
2312
40.6k
    int             level;
2313
2314
40.6k
    type = get_token(fp, token, MAXTOKEN);
2315
40.6k
    if (type == SEQUENCE || type == CHOICE) {
2316
2.77k
        level = 0;
2317
517k
        while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
2318
517k
            if (type == LEFTBRACKET) {
2319
219k
                level++;
2320
298k
            } else if (type == RIGHTBRACKET && --level == 0) {
2321
2.69k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2322
2.69k
                return NULL;
2323
2.69k
            }
2324
517k
        }
2325
74
        print_error("Expected \"}\"", token, type);
2326
74
        return NULL;
2327
37.9k
    } else if (type == LEFTBRACKET) {
2328
13.0k
        struct node    *np;
2329
13.0k
        int             ch_next = '{';
2330
13.0k
        ungetc(ch_next, fp);
2331
13.0k
        np = parse_objectid(fp, name);
2332
13.0k
        if (np != NULL) {
2333
11.7k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2334
11.7k
            return np;
2335
11.7k
        }
2336
1.27k
        return NULL;
2337
24.9k
    } else if (type == LEFTSQBRACK) {
2338
5.85k
        int             size = 0;
2339
228k
        do {
2340
228k
            type = get_token(fp, token, MAXTOKEN);
2341
228k
        } while (type != ENDOFFILE && type != RIGHTSQBRACK);
2342
5.85k
        if (type != RIGHTSQBRACK) {
2343
45
            print_error("Expected \"]\"", token, type);
2344
45
            return NULL;
2345
45
        }
2346
5.80k
        type = get_token(fp, token, MAXTOKEN);
2347
5.80k
        if (type == IMPLICIT)
2348
3.42k
            type = get_token(fp, token, MAXTOKEN);
2349
5.80k
        *ntype = get_token(fp, ntoken, MAXTOKEN);
2350
5.80k
        if (*ntype == LEFTPAREN) {
2351
4.73k
            switch (type) {
2352
1.55k
            case OCTETSTR:
2353
1.55k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2354
1.55k
                if (*ntype != SIZE) {
2355
41
                    print_error("Expected SIZE", ntoken, *ntype);
2356
41
                    return NULL;
2357
41
                }
2358
1.51k
                size = 1;
2359
1.51k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2360
1.51k
                if (*ntype != LEFTPAREN) {
2361
696
                    print_error("Expected \"(\" after SIZE", ntoken,
2362
696
                                *ntype);
2363
696
                    return NULL;
2364
696
                }
2365
815
                NETSNMP_FALLTHROUGH;
2366
3.79k
            case INTEGER:
2367
3.79k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2368
6.58k
                do {
2369
6.58k
                    if (*ntype != NUMBER)
2370
2.97k
                        print_error("Expected NUMBER", ntoken, *ntype);
2371
6.58k
                    *ntype = get_token(fp, ntoken, MAXTOKEN);
2372
6.58k
                    if (*ntype == RANGE) {
2373
2.52k
                        *ntype = get_token(fp, ntoken, MAXTOKEN);
2374
2.52k
                        if (*ntype != NUMBER)
2375
479
                            print_error("Expected NUMBER", ntoken, *ntype);
2376
2.52k
                        *ntype = get_token(fp, ntoken, MAXTOKEN);
2377
2.52k
                    }
2378
6.58k
                } while (*ntype == BAR);
2379
3.79k
                if (*ntype != RIGHTPAREN) {
2380
605
                    print_error("Expected \")\"", ntoken, *ntype);
2381
605
                    return NULL;
2382
605
                }
2383
3.19k
                *ntype = get_token(fp, ntoken, MAXTOKEN);
2384
3.19k
                if (size) {
2385
801
                    if (*ntype != RIGHTPAREN) {
2386
343
                        print_error("Expected \")\" to terminate SIZE",
2387
343
                                    ntoken, *ntype);
2388
343
                        return NULL;
2389
343
                    }
2390
458
                    *ntype = get_token(fp, ntoken, MAXTOKEN);
2391
458
                }
2392
4.73k
            }
2393
4.73k
        }
2394
4.12k
        return NULL;
2395
19.0k
    } else {
2396
19.0k
        if (type == CONVENTION) {
2397
297k
            while (type != SYNTAX && type != ENDOFFILE) {
2398
296k
                if (type == DISPLAYHINT) {
2399
771
                    type = get_token(fp, token, MAXTOKEN);
2400
771
                    if (type != QUOTESTRING) {
2401
70
                        print_error("DISPLAY-HINT must be string", token,
2402
70
                                    type);
2403
701
                    } else {
2404
701
                        free(hint);
2405
701
                        hint = strdup(token);
2406
701
                    }
2407
295k
                } else if (type == DESCRIPTION &&
2408
295k
                           netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2409
342
                                                  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
295k
                    type =
2420
295k
                        get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2421
296k
            }
2422
616
            type = get_token(fp, token, MAXTOKEN);
2423
616
            if (type == OBJECT) {
2424
186
                type = get_token(fp, token, MAXTOKEN);
2425
186
                if (type != IDENTIFIER) {
2426
92
                    print_error("Expected IDENTIFIER", token, type);
2427
92
                    goto err;
2428
92
                }
2429
94
                type = OBJID;
2430
94
            }
2431
18.4k
        } else if (type == OBJECT) {
2432
1.24k
            type = get_token(fp, token, MAXTOKEN);
2433
1.24k
            if (type != IDENTIFIER) {
2434
86
                print_error("Expected IDENTIFIER", token, type);
2435
86
                goto err;
2436
86
            }
2437
1.16k
            type = OBJID;
2438
1.16k
        }
2439
2440
18.8k
        if (type == LABEL) {
2441
9.47k
            type = get_tc(token, current_module, NULL, NULL, NULL, NULL);
2442
9.47k
        }
2443
2444
        /*
2445
         * textual convention 
2446
         */
2447
18.8k
        tcp = NULL;
2448
72.8M
        for (i = 0; i < tc_alloc; i++) {
2449
72.8M
            if (tclist[i].type == 0) {
2450
931k
                if (tcp == NULL)
2451
18.7k
                    tcp = &tclist[i];
2452
71.9M
            } else if (strcmp(name, tclist[i].descriptor) == 0 &&
2453
71.9M
                       tclist[i].modid == current_module) {
2454
1.86M
                snmp_log(LOG_ERR,
2455
1.86M
                         "Duplicate TEXTUAL-CONVENTION '%s' at line %d in %s. First at line %d\n",
2456
1.86M
                         name, mibLine, File, tclist[i].lineno);
2457
1.86M
                erroneousMibs++;
2458
1.86M
            }
2459
72.8M
        }
2460
2461
18.8k
        if (tcp == NULL) {
2462
93
            tclist = realloc(tclist, (tc_alloc + TC_INCR)*sizeof(struct tc));
2463
93
            memset(tclist+tc_alloc, 0, TC_INCR*sizeof(struct tc));
2464
93
            tcp = tclist + tc_alloc;
2465
93
            tc_alloc += TC_INCR;
2466
93
        }
2467
18.8k
        if (!(type & SYNTAX_MASK)) {
2468
9.19k
            print_error("Textual convention doesn't map to real type",
2469
9.19k
                        token, type);
2470
9.19k
            goto err;
2471
9.19k
        }
2472
9.67k
        tcp->modid = current_module;
2473
9.67k
        tcp->descriptor = strdup(name);
2474
9.67k
        tcp->hint = hint;
2475
9.67k
        tcp->description = descr;
2476
9.67k
        tcp->lineno = mibLine;
2477
9.67k
        tcp->type = type;
2478
9.67k
        *ntype = get_token(fp, ntoken, MAXTOKEN);
2479
9.67k
        if (*ntype == LEFTPAREN) {
2480
1.05k
            tcp->ranges = parse_ranges(fp, &tcp->ranges);
2481
1.05k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2482
8.61k
        } else if (*ntype == LEFTBRACKET) {
2483
            /*
2484
             * if there is an enumeration list, parse it 
2485
             */
2486
5.89k
            tcp->enums = parse_enumlist(fp, &tcp->enums);
2487
5.89k
            *ntype = get_token(fp, ntoken, MAXTOKEN);
2488
5.89k
        }
2489
9.67k
        return NULL;
2490
18.8k
    }
2491
2492
9.37k
err:
2493
9.37k
    SNMP_FREE(descr);
2494
9.37k
    SNMP_FREE(hint);
2495
9.37k
    return NULL;
2496
40.6k
}
2497
2498
2499
/*
2500
 * Parses an OBJECT TYPE macro.
2501
 * Returns 0 on error.
2502
 */
2503
static struct node *
2504
parse_objecttype(FILE * fp, char *name)
2505
16.5k
{
2506
16.5k
    register int    type;
2507
16.5k
    char            token[MAXTOKEN];
2508
16.5k
    char            nexttoken[MAXTOKEN];
2509
16.5k
    char            quoted_string_buffer[MAXQUOTESTR];
2510
16.5k
    int             nexttype, tctype;
2511
16.5k
    register struct node *np;
2512
2513
16.5k
    type = get_token(fp, token, MAXTOKEN);
2514
16.5k
    if (type != SYNTAX) {
2515
18
        print_error("Bad format for OBJECT-TYPE", token, type);
2516
18
        return NULL;
2517
18
    }
2518
16.5k
    np = alloc_node(current_module);
2519
16.5k
    if (np == NULL)
2520
0
        return (NULL);
2521
16.5k
    type = get_token(fp, token, MAXTOKEN);
2522
16.5k
    if (type == OBJECT) {
2523
911
        type = get_token(fp, token, MAXTOKEN);
2524
911
        if (type != IDENTIFIER) {
2525
5
            print_error("Expected IDENTIFIER", token, type);
2526
5
            free_node(np);
2527
5
            return NULL;
2528
5
        }
2529
906
        type = OBJID;
2530
906
    }
2531
16.5k
    if (type == LABEL) {
2532
6.78k
        int             tmp_index;
2533
6.78k
        tctype = get_tc(token, current_module, &tmp_index,
2534
6.78k
                        &np->enums, &np->ranges, &np->hint);
2535
6.78k
        if (tctype == LABEL &&
2536
6.78k
            netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
2537
6.27k
             NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
2538
0
            print_error("Warning: No known translation for type", token,
2539
0
                        type);
2540
0
        }
2541
6.78k
        type = tctype;
2542
6.78k
        np->tc_index = tmp_index;       /* store TC for later reference */
2543
6.78k
    }
2544
16.5k
    np->type = type;
2545
16.5k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
2546
16.5k
    switch (type) {
2547
994
    case SEQUENCE:
2548
994
        if (nexttype == OF) {
2549
925
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2550
925
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2551
2552
925
        }
2553
994
        break;
2554
1.42k
    case INTEGER:
2555
2.50k
    case INTEGER32:
2556
2.50k
    case UINTEGER32:
2557
3.84k
    case UNSIGNED32:
2558
5.29k
    case COUNTER:
2559
5.39k
    case GAUGE:
2560
5.56k
    case BITSTRING:
2561
11.8k
    case LABEL:
2562
11.8k
        if (nexttype == LEFTBRACKET) {
2563
            /*
2564
             * if there is an enumeration list, parse it 
2565
             */
2566
943
            np->enums = parse_enumlist(fp, &np->enums);
2567
943
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2568
10.8k
        } else if (nexttype == LEFTPAREN) {
2569
            /*
2570
             * if there is a range list, parse it 
2571
             */
2572
2.21k
            np->ranges = parse_ranges(fp, &np->ranges);
2573
2.21k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2574
2.21k
        }
2575
11.8k
        break;
2576
619
    case OCTETSTR:
2577
840
    case KW_OPAQUE:
2578
        /*
2579
         * parse any SIZE specification 
2580
         */
2581
840
        if (nexttype == LEFTPAREN) {
2582
107
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
2583
107
            if (nexttype == SIZE) {
2584
100
                nexttype = get_token(fp, nexttoken, MAXTOKEN);
2585
100
                if (nexttype == LEFTPAREN) {
2586
93
                    np->ranges = parse_ranges(fp, &np->ranges);
2587
93
                    nexttype = get_token(fp, nexttoken, MAXTOKEN);      /* ) */
2588
93
                    if (nexttype == RIGHTPAREN) {
2589
82
                        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2590
82
                        break;
2591
82
                    }
2592
93
                }
2593
100
            }
2594
25
            print_error("Bad SIZE syntax", token, type);
2595
25
            free_node(np);
2596
25
            return NULL;
2597
107
        }
2598
733
        break;
2599
910
    case OBJID:
2600
1.30k
    case NETADDR:
2601
1.60k
    case IPADDR:
2602
1.89k
    case TIMETICKS:
2603
2.59k
    case NUL:
2604
2.59k
    case NSAPADDRESS:
2605
2.87k
    case COUNTER64:
2606
2.87k
        break;
2607
4
    default:
2608
4
        print_error("Bad syntax", token, type);
2609
4
        free_node(np);
2610
4
        return NULL;
2611
16.5k
    }
2612
16.5k
    if (nexttype == UNITS) {
2613
867
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2614
867
        if (type != QUOTESTRING) {
2615
1
            print_error("Bad UNITS", quoted_string_buffer, type);
2616
1
            free_node(np);
2617
1
            return NULL;
2618
1
        }
2619
866
        np->units = strdup(quoted_string_buffer);
2620
866
        nexttype = get_token(fp, nexttoken, MAXTOKEN);
2621
866
    }
2622
16.5k
    if (nexttype != ACCESS) {
2623
105
        print_error("Should be ACCESS", nexttoken, nexttype);
2624
105
        free_node(np);
2625
105
        return NULL;
2626
105
    }
2627
16.4k
    type = get_token(fp, token, MAXTOKEN);
2628
16.4k
    if (type != READONLY && type != READWRITE && type != WRITEONLY
2629
16.4k
        && type != NOACCESS && type != READCREATE && type != ACCNOTIFY) {
2630
33
        print_error("Bad ACCESS type", token, type);
2631
33
        free_node(np);
2632
33
        return NULL;
2633
33
    }
2634
16.3k
    np->access = type;
2635
16.3k
    type = get_token(fp, token, MAXTOKEN);
2636
16.3k
    if (type != STATUS) {
2637
36
        print_error("Should be STATUS", token, type);
2638
36
        free_node(np);
2639
36
        return NULL;
2640
36
    }
2641
16.3k
    type = get_token(fp, token, MAXTOKEN);
2642
16.3k
    if (type != MANDATORY && type != CURRENT && type != KW_OPTIONAL &&
2643
16.3k
        type != OBSOLETE && type != DEPRECATED) {
2644
22
        print_error("Bad STATUS", token, type);
2645
22
        free_node(np);
2646
22
        return NULL;
2647
22
    }
2648
16.3k
    np->status = type;
2649
    /*
2650
     * Optional parts of the OBJECT-TYPE macro
2651
     */
2652
16.3k
    type = get_token(fp, token, MAXTOKEN);
2653
38.2k
    while (type != EQUALS && type != ENDOFFILE) {
2654
22.1k
        switch (type) {
2655
14.7k
        case DESCRIPTION:
2656
14.7k
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2657
2658
14.7k
            if (type != QUOTESTRING) {
2659
30
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2660
30
                free_node(np);
2661
30
                return NULL;
2662
30
            }
2663
14.6k
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2664
14.6k
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2665
0
                np->description = strdup(quoted_string_buffer);
2666
0
            }
2667
14.6k
            break;
2668
2669
214
        case REFERENCE:
2670
214
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2671
214
            if (type != QUOTESTRING) {
2672
2
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2673
2
                free_node(np);
2674
2
                return NULL;
2675
2
            }
2676
212
            np->reference = strdup(quoted_string_buffer);
2677
212
            break;
2678
3.30k
        case INDEX:
2679
3.30k
            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
3.30k
            np->indexes = getIndexes(fp, &np->indexes);
2686
3.30k
            if (np->indexes == NULL) {
2687
6
                print_error("Bad INDEX list", token, type);
2688
6
                free_node(np);
2689
6
                return NULL;
2690
6
            }
2691
3.30k
            break;
2692
3.30k
        case AUGMENTS:
2693
280
            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
279
            np->indexes = getIndexes(fp, &np->indexes);
2700
279
            if (np->indexes == NULL) {
2701
3
                print_error("Bad AUGMENTS list", token, type);
2702
3
                free_node(np);
2703
3
                return NULL;
2704
3
            }
2705
276
            np->augments = strdup(np->indexes->ilabel);
2706
276
            free_indexes(&np->indexes);
2707
276
            break;
2708
3.47k
        case DEFVAL:
2709
            /*
2710
             * Mark's defVal section 
2711
             */
2712
3.47k
            type = get_token(fp, quoted_string_buffer,
2713
3.47k
                             sizeof(quoted_string_buffer));
2714
3.47k
            if (type != LEFTBRACKET) {
2715
11
                print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2716
11
                            type);
2717
11
                free_node(np);
2718
11
                return NULL;
2719
11
            }
2720
2721
3.46k
            {
2722
3.46k
                int             level = 1;
2723
3.46k
                char            defbuf[512];
2724
2725
3.46k
                defbuf[0] = 0;
2726
498k
                while (1) {
2727
498k
                    type = get_token(fp, quoted_string_buffer,
2728
498k
                                     sizeof(quoted_string_buffer));
2729
498k
                    if ((type == RIGHTBRACKET && --level == 0)
2730
498k
                        || type == ENDOFFILE)
2731
3.46k
                        break;
2732
494k
                    else if (type == LEFTBRACKET)
2733
307k
                        level++;
2734
494k
                    if (type == QUOTESTRING)
2735
361
                        strlcat(defbuf, "\\\"", sizeof(defbuf));
2736
494k
                    strlcat(defbuf, quoted_string_buffer, sizeof(defbuf));
2737
494k
                    if (type == QUOTESTRING)
2738
361
                        strlcat(defbuf, "\\\"", sizeof(defbuf));
2739
494k
                    strlcat(defbuf, " ", sizeof(defbuf));
2740
494k
                }
2741
2742
3.46k
                if (type != RIGHTBRACKET) {
2743
72
                    print_error("Bad DEFAULTVALUE", quoted_string_buffer,
2744
72
                                type);
2745
72
                    free_node(np);
2746
72
                    return NULL;
2747
72
                }
2748
2749
                /*
2750
                 * Ensure strlen(defbuf) is above zero
2751
                 */
2752
3.39k
                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
3.39k
                defbuf[strlen(defbuf) - 1] = 0;
2759
3.39k
                np->defaultValue = strdup(defbuf);
2760
3.39k
            }
2761
2762
0
            break;
2763
2764
45
        case NUM_ENTRIES:
2765
45
            if (tossObjectIdentifier(fp) != OBJID) {
2766
35
                print_error("Bad Object Identifier", token, type);
2767
35
                free_node(np);
2768
35
                return NULL;
2769
35
            }
2770
10
            break;
2771
2772
80
        default:
2773
80
            print_error("Bad format of optional clauses", token, type);
2774
80
            free_node(np);
2775
80
            return NULL;
2776
2777
22.1k
        }
2778
21.8k
        type = get_token(fp, token, MAXTOKEN);
2779
21.8k
    }
2780
16.0k
    if (type != EQUALS) {
2781
66
        print_error("Bad format", token, type);
2782
66
        free_node(np);
2783
66
        return NULL;
2784
66
    }
2785
16.0k
    return merge_parse_objectid(np, fp, name);
2786
16.0k
}
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.00k
{
2798
4.00k
    int             type;
2799
4.00k
    char            token[MAXTOKEN];
2800
4.00k
    char            quoted_string_buffer[MAXQUOTESTR];
2801
4.00k
    struct node    *np;
2802
2803
4.00k
    np = alloc_node(current_module);
2804
4.00k
    if (np == NULL)
2805
0
        return (NULL);
2806
4.00k
    type = get_token(fp, token, MAXTOKEN);
2807
4.00k
    if (type == what) {
2808
2.29k
        type = get_token(fp, token, MAXTOKEN);
2809
2.29k
        if (type != LEFTBRACKET) {
2810
130
            print_error("Expected \"{\"", token, type);
2811
130
            goto skip;
2812
130
        }
2813
6.58k
        do {
2814
6.58k
            struct objgroup *o;
2815
6.58k
            type = get_token(fp, token, MAXTOKEN);
2816
6.58k
            if (type != LABEL) {
2817
355
                print_error("Bad identifier", token, type);
2818
355
                goto skip;
2819
355
            }
2820
6.22k
            o = (struct objgroup *) malloc(sizeof(struct objgroup));
2821
6.22k
            if (!o) {
2822
0
                print_error("Resource failure", token, type);
2823
0
                goto skip;
2824
0
            }
2825
6.22k
            o->line = mibLine;
2826
6.22k
            o->name = strdup(token);
2827
6.22k
            o->next = *ol;
2828
6.22k
            *ol = o;
2829
6.22k
            type = get_token(fp, token, MAXTOKEN);
2830
6.22k
        } while (type == COMMA);
2831
1.81k
        if (type != RIGHTBRACKET) {
2832
1.41k
            print_error("Expected \"}\" after list", token, type);
2833
1.41k
            goto skip;
2834
1.41k
        }
2835
396
        type = get_token(fp, token, type);
2836
396
    }
2837
2.10k
    if (type != STATUS) {
2838
652
        print_error("Expected STATUS", token, type);
2839
652
        goto skip;
2840
652
    }
2841
1.45k
    type = get_token(fp, token, MAXTOKEN);
2842
1.45k
    if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
2843
143
        print_error("Bad STATUS value", token, type);
2844
143
        goto skip;
2845
143
    }
2846
1.30k
    type = get_token(fp, token, MAXTOKEN);
2847
1.30k
    if (type != DESCRIPTION) {
2848
187
        print_error("Expected DESCRIPTION", token, type);
2849
187
        goto skip;
2850
187
    }
2851
1.12k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2852
1.12k
    if (type != QUOTESTRING) {
2853
13
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2854
13
        free_node(np);
2855
13
        return NULL;
2856
13
    }
2857
1.10k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2858
1.10k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2859
0
        np->description = strdup(quoted_string_buffer);
2860
0
    }
2861
1.10k
    type = get_token(fp, token, MAXTOKEN);
2862
1.10k
    if (type == REFERENCE) {
2863
390
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2864
390
        if (type != QUOTESTRING) {
2865
6
            print_error("Bad REFERENCE", quoted_string_buffer, type);
2866
6
            free_node(np);
2867
6
            return NULL;
2868
6
        }
2869
384
        np->reference = strdup(quoted_string_buffer);
2870
384
        type = get_token(fp, token, MAXTOKEN);
2871
384
    }
2872
1.10k
    if (type != EQUALS)
2873
254
        print_error("Expected \"::=\"", token, type);
2874
3.98k
  skip:
2875
80.8k
    while (type != EQUALS && type != ENDOFFILE)
2876
76.8k
        type = get_token(fp, token, MAXTOKEN);
2877
2878
3.98k
    return merge_parse_objectid(np, fp, name);
2879
1.10k
}
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
2.71k
{
2888
2.71k
    register int    type;
2889
2.71k
    char            token[MAXTOKEN];
2890
2.71k
    char            quoted_string_buffer[MAXQUOTESTR];
2891
2.71k
    register struct node *np;
2892
2893
2.71k
    np = alloc_node(current_module);
2894
2.71k
    if (np == NULL)
2895
0
        return (NULL);
2896
2.71k
    type = get_token(fp, token, MAXTOKEN);
2897
284k
    while (type != EQUALS && type != ENDOFFILE) {
2898
281k
        switch (type) {
2899
442
        case DESCRIPTION:
2900
442
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2901
442
            if (type != QUOTESTRING) {
2902
18
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2903
18
                goto free_node;
2904
18
            }
2905
424
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2906
424
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2907
0
                np->description = strdup(quoted_string_buffer);
2908
0
            }
2909
424
            break;
2910
319
        case REFERENCE:
2911
319
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2912
319
            if (type != QUOTESTRING) {
2913
5
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2914
5
                goto free_node;
2915
5
            }
2916
314
            free(np->reference);
2917
314
            np->reference = strdup(quoted_string_buffer);
2918
314
            break;
2919
2.22k
        case OBJECTS:
2920
2.22k
            np->varbinds = getVarbinds(fp, &np->varbinds);
2921
2.22k
            if (!np->varbinds) {
2922
17
                print_error("Bad OBJECTS list", token, type);
2923
17
                goto free_node;
2924
17
            }
2925
2.20k
            break;
2926
278k
        default:
2927
            /*
2928
             * NOTHING 
2929
             */
2930
278k
            break;
2931
281k
        }
2932
281k
        type = get_token(fp, token, MAXTOKEN);
2933
281k
    }
2934
2.67k
    return merge_parse_objectid(np, fp, name);
2935
2936
40
free_node:
2937
40
    free_node(np);
2938
40
    return NULL;
2939
2.71k
}
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
528
{
2948
528
    register int    type;
2949
528
    char            token[MAXTOKEN];
2950
528
    char            quoted_string_buffer[MAXQUOTESTR];
2951
528
    register struct node *np;
2952
2953
528
    np = alloc_node(current_module);
2954
528
    if (np == NULL)
2955
0
        return (NULL);
2956
528
    type = get_token(fp, token, MAXTOKEN);
2957
26.9k
    while (type != EQUALS && type != ENDOFFILE) {
2958
26.4k
        switch (type) {
2959
243
        case DESCRIPTION:
2960
243
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2961
243
            if (type != QUOTESTRING) {
2962
13
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
2963
13
                goto free_node;
2964
13
            }
2965
230
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
2966
230
               NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
2967
0
                np->description = strdup(quoted_string_buffer);
2968
0
            }
2969
230
            break;
2970
74
        case REFERENCE:
2971
            /* I'm not sure REFERENCEs are legal in smiv1 traps??? */
2972
74
            type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
2973
74
            if (type != QUOTESTRING) {
2974
2
                print_error("Bad REFERENCE", quoted_string_buffer, type);
2975
2
                goto free_node;
2976
2
            }
2977
72
            np->reference = strdup(quoted_string_buffer);
2978
72
            break;
2979
1.07k
        case ENTERPRISE:
2980
1.07k
            type = get_token(fp, token, MAXTOKEN);
2981
1.07k
            if (type == LEFTBRACKET) {
2982
489
                type = get_token(fp, token, MAXTOKEN);
2983
489
                if (type != LABEL) {
2984
5
                    print_error("Bad Trap Format", token, type);
2985
5
                    goto free_node;
2986
5
                }
2987
484
                np->parent = strdup(token);
2988
                /*
2989
                 * Get right bracket 
2990
                 */
2991
484
                type = get_token(fp, token, MAXTOKEN);
2992
589
            } else if (type == LABEL) {
2993
582
                np->parent = strdup(token);
2994
582
            } else {
2995
7
                goto free_node;
2996
7
            }
2997
1.06k
            break;
2998
1.06k
        case VARIABLES:
2999
402
            np->varbinds = getVarbinds(fp, &np->varbinds);
3000
402
            if (!np->varbinds) {
3001
8
                print_error("Bad VARIABLES list", token, type);
3002
8
                goto free_node;
3003
8
            }
3004
394
            break;
3005
24.6k
        default:
3006
            /*
3007
             * NOTHING 
3008
             */
3009
24.6k
            break;
3010
26.4k
        }
3011
26.3k
        type = get_token(fp, token, MAXTOKEN);
3012
26.3k
    }
3013
493
    type = get_token(fp, token, MAXTOKEN);
3014
3015
493
    np->label = strdup(name);
3016
3017
493
    if (type != NUMBER) {
3018
131
        print_error("Expected a Number", token, type);
3019
131
        goto free_node;
3020
131
    }
3021
362
    np->subid = strtoul(token, NULL, 10);
3022
362
    np->next = alloc_node(current_module);
3023
362
    if (np->next == NULL)
3024
0
        goto free_node;
3025
3026
    /* Catch the syntax error */
3027
362
    if (np->parent == NULL) {
3028
8
        gMibError = MODULE_SYNTAX_ERROR;
3029
8
        goto free_next_node;
3030
8
    }
3031
3032
354
    np->next->parent = np->parent;
3033
354
    np->parent = NULL;
3034
354
    if (asprintf(&np->parent, "%s#", np->next->parent) < 0)
3035
0
        goto free_next_node;
3036
354
    np->next->label = strdup(np->parent);
3037
354
    return np;
3038
3039
8
free_next_node:
3040
8
    free_node(np->next);
3041
3042
174
free_node:
3043
174
    free_node(np);
3044
174
    return NULL;
3045
8
}
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.45k
{
3055
4.45k
    int             type, nexttype;
3056
4.45k
    struct node    *np = alloc_node(current_module);
3057
4.45k
    char            nexttoken[MAXTOKEN];
3058
3059
4.45k
    if (!np)
3060
0
  return 0;
3061
3062
4.45k
    type = get_token(fp, token, maxtoken);
3063
4.45k
    nexttype = get_token(fp, nexttoken, MAXTOKEN);
3064
4.45k
    switch (type) {
3065
505
    case INTEGER:
3066
1.00k
    case INTEGER32:
3067
1.07k
    case UINTEGER32:
3068
1.50k
    case UNSIGNED32:
3069
1.58k
    case COUNTER:
3070
1.65k
    case GAUGE:
3071
1.96k
    case BITSTRING:
3072
2.49k
    case LABEL:
3073
2.49k
        if (nexttype == LEFTBRACKET) {
3074
            /*
3075
             * if there is an enumeration list, parse it 
3076
             */
3077
557
            np->enums = parse_enumlist(fp, &np->enums);
3078
557
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3079
1.93k
        } else if (nexttype == LEFTPAREN) {
3080
            /*
3081
             * if there is a range list, parse it 
3082
             */
3083
1.04k
            np->ranges = parse_ranges(fp, &np->ranges);
3084
1.04k
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3085
1.04k
        }
3086
2.49k
        break;
3087
792
    case OCTETSTR:
3088
856
    case KW_OPAQUE:
3089
        /*
3090
         * parse any SIZE specification 
3091
         */
3092
856
        if (nexttype == LEFTPAREN) {
3093
278
            nexttype = get_token(fp, nexttoken, MAXTOKEN);
3094
278
            if (nexttype == SIZE) {
3095
173
                nexttype = get_token(fp, nexttoken, MAXTOKEN);
3096
173
                if (nexttype == LEFTPAREN) {
3097
91
                    np->ranges = parse_ranges(fp, &np->ranges);
3098
91
                    nexttype = get_token(fp, nexttoken, MAXTOKEN);      /* ) */
3099
91
                    if (nexttype == RIGHTPAREN) {
3100
68
                        nexttype = get_token(fp, nexttoken, MAXTOKEN);
3101
68
                        break;
3102
68
                    }
3103
91
                }
3104
173
            }
3105
210
            print_error("Bad SIZE syntax", token, type);
3106
210
            free_node(np);
3107
210
            return nexttype;
3108
278
        }
3109
578
        break;
3110
578
    case OBJID:
3111
98
    case NETADDR:
3112
169
    case IPADDR:
3113
391
    case TIMETICKS:
3114
425
    case NUL:
3115
900
    case NSAPADDRESS:
3116
983
    case COUNTER64:
3117
983
        break;
3118
124
    default:
3119
124
        print_error("Bad syntax", token, type);
3120
124
        free_node(np);
3121
124
        return nexttype;
3122
4.45k
    }
3123
4.11k
    free_node(np);
3124
4.11k
    return nexttype;
3125
4.45k
}
3126
3127
static int
3128
compliance_lookup(const char *name, int modid)
3129
17.6k
{
3130
17.6k
    struct objgroup *op;
3131
3132
17.6k
    if (modid != -1)
3133
2.90k
        return find_tree_node(name, modid) != NULL;
3134
3135
14.7k
    op = malloc(sizeof(struct objgroup));
3136
14.7k
    if (!op)
3137
0
        return 0;
3138
3139
14.7k
    op->next = objgroups;
3140
14.7k
    op->name = strdup(name);
3141
14.7k
    if (!op->name) {
3142
0
        free(op);
3143
0
        return 0;
3144
0
    }
3145
14.7k
    op->line = mibLine;
3146
14.7k
    objgroups = op;
3147
14.7k
    return 1;
3148
14.7k
}
3149
3150
static struct node *
3151
parse_compliance(FILE * fp, char *name)
3152
12.8k
{
3153
12.8k
    int             type;
3154
12.8k
    char            token[MAXTOKEN];
3155
12.8k
    char            quoted_string_buffer[MAXQUOTESTR];
3156
12.8k
    struct node    *np;
3157
3158
12.8k
    np = alloc_node(current_module);
3159
12.8k
    if (np == NULL)
3160
0
        return (NULL);
3161
12.8k
    type = get_token(fp, token, MAXTOKEN);
3162
12.8k
    if (type != STATUS) {
3163
739
        print_error("Expected STATUS", token, type);
3164
739
        goto skip;
3165
739
    }
3166
12.1k
    type = get_token(fp, token, MAXTOKEN);
3167
12.1k
    if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
3168
417
        print_error("Bad STATUS", token, type);
3169
417
        goto skip;
3170
417
    }
3171
11.7k
    type = get_token(fp, token, MAXTOKEN);
3172
11.7k
    if (type != DESCRIPTION) {
3173
1.99k
        print_error("Expected DESCRIPTION", token, type);
3174
1.99k
        goto skip;
3175
1.99k
    }
3176
9.72k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3177
9.72k
    if (type != QUOTESTRING) {
3178
533
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3179
533
        goto skip;
3180
533
    }
3181
9.18k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3182
9.18k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS))
3183
0
        np->description = strdup(quoted_string_buffer);
3184
9.18k
    type = get_token(fp, token, MAXTOKEN);
3185
9.18k
    if (type == REFERENCE) {
3186
270
        type = get_token(fp, quoted_string_buffer,
3187
270
                         sizeof(quoted_string_buffer));
3188
270
        if (type != QUOTESTRING) {
3189
200
            print_error("Bad REFERENCE", quoted_string_buffer, type);
3190
200
            goto skip;
3191
200
        }
3192
70
        np->reference = strdup(quoted_string_buffer);
3193
70
        type = get_token(fp, token, MAXTOKEN);
3194
70
    }
3195
8.98k
    if (type != MODULE) {
3196
478
        print_error("Expected MODULE", token, type);
3197
478
        goto skip;
3198
478
    }
3199
11.7k
    while (type == MODULE) {
3200
10.6k
        int             modid = -1;
3201
10.6k
        char            modname[MAXTOKEN];
3202
10.6k
        type = get_token(fp, token, MAXTOKEN);
3203
10.6k
        if (type == LABEL
3204
10.6k
            && strcmp(token, module_name(current_module, modname))) {
3205
3.28k
            modid = read_module_internal(token);
3206
3.28k
            if (modid != MODULE_LOADED_OK
3207
3.28k
                && modid != MODULE_ALREADY_LOADED) {
3208
299
                print_error("Unknown module", token, type);
3209
299
                goto skip;
3210
299
            }
3211
2.98k
            modid = which_module(token);
3212
2.98k
            type = get_token(fp, token, MAXTOKEN);
3213
2.98k
        }
3214
10.3k
        if (type == MANDATORYGROUPS) {
3215
3.30k
            type = get_token(fp, token, MAXTOKEN);
3216
3.30k
            if (type != LEFTBRACKET) {
3217
84
                print_error("Expected \"{\"", token, type);
3218
84
                goto skip;
3219
84
            }
3220
7.80k
            do {
3221
7.80k
                type = get_token(fp, token, MAXTOKEN);
3222
7.80k
                if (type != LABEL) {
3223
108
                    print_error("Bad group name", token, type);
3224
108
                    goto skip;
3225
108
                }
3226
7.69k
                if (!compliance_lookup(token, modid))
3227
55
                    print_error("Unknown group", token, type);
3228
7.69k
                type = get_token(fp, token, MAXTOKEN);
3229
7.69k
            } while (type == COMMA);
3230
3.10k
            if (type != RIGHTBRACKET) {
3231
594
                print_error("Expected \"}\"", token, type);
3232
594
                goto skip;
3233
594
            }
3234
2.51k
            type = get_token(fp, token, MAXTOKEN);
3235
2.51k
        }
3236
13.5k
        while (type == GROUP || type == OBJECT) {
3237
10.2k
            if (type == GROUP) {
3238
2.66k
                type = get_token(fp, token, MAXTOKEN);
3239
2.66k
                if (type != LABEL) {
3240
226
                    print_error("Bad group name", token, type);
3241
226
                    goto skip;
3242
226
                }
3243
2.43k
                if (!compliance_lookup(token, modid))
3244
1.63k
                    print_error("Unknown group", token, type);
3245
2.43k
                type = get_token(fp, token, MAXTOKEN);
3246
7.61k
            } else {
3247
7.61k
                type = get_token(fp, token, MAXTOKEN);
3248
7.61k
                if (type != LABEL) {
3249
115
                    print_error("Bad object name", token, type);
3250
115
                    goto skip;
3251
115
                }
3252
7.49k
                if (!compliance_lookup(token, modid))
3253
371
                    print_error("Unknown group", token, type);
3254
7.49k
                type = get_token(fp, token, MAXTOKEN);
3255
7.49k
                if (type == SYNTAX)
3256
3.82k
                    type = eat_syntax(fp, token, MAXTOKEN);
3257
7.49k
                if (type == WRSYNTAX)
3258
629
                    type = eat_syntax(fp, token, MAXTOKEN);
3259
7.49k
                if (type == MINACCESS) {
3260
2.28k
                    type = get_token(fp, token, MAXTOKEN);
3261
2.28k
                    if (type != NOACCESS && type != ACCNOTIFY
3262
2.28k
                        && type != READONLY && type != WRITEONLY
3263
2.28k
                        && type != READCREATE && type != READWRITE) {
3264
150
                        print_error("Bad MIN-ACCESS spec", token, type);
3265
150
                        goto skip;
3266
150
                    }
3267
2.13k
                    type = get_token(fp, token, MAXTOKEN);
3268
2.13k
                }
3269
7.49k
            }
3270
9.78k
            if (type != DESCRIPTION) {
3271
5.39k
                print_error("Expected DESCRIPTION", token, type);
3272
5.39k
                goto skip;
3273
5.39k
            }
3274
4.38k
            type = get_token(fp, token, MAXTOKEN);
3275
4.38k
            if (type != QUOTESTRING) {
3276
403
                print_error("Bad DESCRIPTION", token, type);
3277
403
                goto skip;
3278
403
            }
3279
3.98k
            type = get_token(fp, token, MAXTOKEN);
3280
3.98k
        }
3281
9.56k
    }
3282
12.8k
  skip:
3283
993k
    while (type != EQUALS && type != ENDOFFILE)
3284
980k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3285
3286
12.8k
    return merge_parse_objectid(np, fp, name);
3287
8.50k
}
3288
3289
3290
/*
3291
 * Parses a capabilities macro
3292
 * Returns 0 on error.
3293
 */
3294
static struct node *
3295
parse_capabilities(FILE * fp, char *name)
3296
5.44k
{
3297
5.44k
    int             type;
3298
5.44k
    char            token[MAXTOKEN];
3299
5.44k
    char            quoted_string_buffer[MAXQUOTESTR];
3300
5.44k
    struct node    *np;
3301
3302
5.44k
    np = alloc_node(current_module);
3303
5.44k
    if (np == NULL)
3304
0
        return (NULL);
3305
5.44k
    type = get_token(fp, token, MAXTOKEN);
3306
5.44k
    if (type != PRODREL) {
3307
808
        print_error("Expected PRODUCT-RELEASE", token, type);
3308
808
        goto skip;
3309
808
    }
3310
4.63k
    type = get_token(fp, token, MAXTOKEN);
3311
4.63k
    if (type != QUOTESTRING) {
3312
243
        print_error("Expected STRING after PRODUCT-RELEASE", token, type);
3313
243
        goto skip;
3314
243
    }
3315
4.38k
    type = get_token(fp, token, MAXTOKEN);
3316
4.38k
    if (type != STATUS) {
3317
755
        print_error("Expected STATUS", token, type);
3318
755
        goto skip;
3319
755
    }
3320
3.63k
    type = get_token(fp, token, MAXTOKEN);
3321
3.63k
    if (type != CURRENT && type != OBSOLETE) {
3322
523
        print_error("STATUS should be current or obsolete", token, type);
3323
523
        goto skip;
3324
523
    }
3325
3.11k
    type = get_token(fp, token, MAXTOKEN);
3326
3.11k
    if (type != DESCRIPTION) {
3327
298
        print_error("Expected DESCRIPTION", token, type);
3328
298
        goto skip;
3329
298
    }
3330
2.81k
    type = get_token(fp, quoted_string_buffer, sizeof(quoted_string_buffer));
3331
2.81k
    if (type != QUOTESTRING) {
3332
942
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3333
942
        goto skip;
3334
942
    }
3335
1.87k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3336
1.87k
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
3337
0
        np->description = strdup(quoted_string_buffer);
3338
0
    }
3339
1.87k
    type = get_token(fp, token, MAXTOKEN);
3340
1.87k
    if (type == REFERENCE) {
3341
72
        type = get_token(fp, quoted_string_buffer,
3342
72
                         sizeof(quoted_string_buffer));
3343
72
        if (type != QUOTESTRING) {
3344
39
            print_error("Bad REFERENCE", quoted_string_buffer, type);
3345
39
            goto skip;
3346
39
        }
3347
33
        np->reference = strdup(quoted_string_buffer);
3348
33
        type = get_token(fp, token, type);
3349
33
    }
3350
1.83k
    while (type == SUPPORTS) {
3351
1.48k
        int             modid;
3352
1.48k
        struct tree    *tp;
3353
3354
1.48k
        type = get_token(fp, token, MAXTOKEN);
3355
1.48k
        if (type != LABEL) {
3356
84
            print_error("Bad module name", token, type);
3357
84
            goto skip;
3358
84
        }
3359
1.40k
        modid = read_module_internal(token);
3360
1.40k
        if (modid != MODULE_LOADED_OK && modid != MODULE_ALREADY_LOADED) {
3361
16
            print_error("Module not found", token, type);
3362
16
            goto skip;
3363
16
        }
3364
1.38k
        modid = which_module(token);
3365
1.38k
        type = get_token(fp, token, MAXTOKEN);
3366
1.38k
        if (type != INCLUDES) {
3367
75
            print_error("Expected INCLUDES", token, type);
3368
75
            goto skip;
3369
75
        }
3370
1.31k
        type = get_token(fp, token, MAXTOKEN);
3371
1.31k
        if (type != LEFTBRACKET) {
3372
117
            print_error("Expected \"{\"", token, type);
3373
117
            goto skip;
3374
117
        }
3375
1.23k
        do {
3376
1.23k
            type = get_token(fp, token, MAXTOKEN);
3377
1.23k
            if (type != LABEL) {
3378
1.11k
                print_error("Expected group name", token, type);
3379
1.11k
                goto skip;
3380
1.11k
            }
3381
128
            tp = find_tree_node(token, modid);
3382
128
            if (!tp)
3383
127
                print_error("Group not found in module", token, type);
3384
128
            type = get_token(fp, token, MAXTOKEN);
3385
128
        } while (type == COMMA);
3386
83
        if (type != RIGHTBRACKET) {
3387
81
            print_error("Expected \"}\" after group list", token, type);
3388
81
            goto skip;
3389
81
        }
3390
2
        type = get_token(fp, token, MAXTOKEN);
3391
2
        while (type == VARIATION) {
3392
0
            type = get_token(fp, token, MAXTOKEN);
3393
0
            if (type != LABEL) {
3394
0
                print_error("Bad object name", token, type);
3395
0
                goto skip;
3396
0
            }
3397
0
            tp = find_tree_node(token, modid);
3398
0
            if (!tp)
3399
0
                print_error("Object not found in module", token, type);
3400
0
            type = get_token(fp, token, MAXTOKEN);
3401
0
            if (type == SYNTAX) {
3402
0
                type = eat_syntax(fp, token, MAXTOKEN);
3403
0
            }
3404
0
            if (type == WRSYNTAX) {
3405
0
                type = eat_syntax(fp, token, MAXTOKEN);
3406
0
            }
3407
0
            if (type == ACCESS) {
3408
0
                type = get_token(fp, token, MAXTOKEN);
3409
0
                if (type != ACCNOTIFY && type != READONLY
3410
0
                    && type != READWRITE && type != READCREATE
3411
0
                    && type != WRITEONLY && type != NOTIMPL) {
3412
0
                    print_error("Bad ACCESS", token, type);
3413
0
                    goto skip;
3414
0
                }
3415
0
                type = get_token(fp, token, MAXTOKEN);
3416
0
            }
3417
0
            if (type == CREATEREQ) {
3418
0
                type = get_token(fp, token, MAXTOKEN);
3419
0
                if (type != LEFTBRACKET) {
3420
0
                    print_error("Expected \"{\"", token, type);
3421
0
                    goto skip;
3422
0
                }
3423
0
                do {
3424
0
                    type = get_token(fp, token, MAXTOKEN);
3425
0
                    if (type != LABEL) {
3426
0
                        print_error("Bad object name in list", token,
3427
0
                                    type);
3428
0
                        goto skip;
3429
0
                    }
3430
0
                    type = get_token(fp, token, MAXTOKEN);
3431
0
                } while (type == COMMA);
3432
0
                if (type != RIGHTBRACKET) {
3433
0
                    print_error("Expected \"}\" after list", token, type);
3434
0
                    goto skip;
3435
0
                }
3436
0
                type = get_token(fp, token, MAXTOKEN);
3437
0
            }
3438
0
            if (type == DEFVAL) {
3439
0
                int             level = 1;
3440
0
                type = get_token(fp, token, MAXTOKEN);
3441
0
                if (type != LEFTBRACKET) {
3442
0
                    print_error("Expected \"{\" after DEFVAL", token,
3443
0
                                type);
3444
0
                    goto skip;
3445
0
                }
3446
0
                do {
3447
0
                    type = get_token(fp, token, MAXTOKEN);
3448
0
                    if (type == LEFTBRACKET)
3449
0
                        level++;
3450
0
                    else if (type == RIGHTBRACKET)
3451
0
                        level--;
3452
0
                } while ((type != RIGHTBRACKET || level != 0)
3453
0
                         && type != ENDOFFILE);
3454
0
                if (type != RIGHTBRACKET) {
3455
0
                    print_error("Missing \"}\" after DEFVAL", token, type);
3456
0
                    goto skip;
3457
0
                }
3458
0
                type = get_token(fp, token, MAXTOKEN);
3459
0
            }
3460
0
            if (type != DESCRIPTION) {
3461
0
                print_error("Expected DESCRIPTION", token, type);
3462
0
                goto skip;
3463
0
            }
3464
0
            type = get_token(fp, quoted_string_buffer,
3465
0
                             sizeof(quoted_string_buffer));
3466
0
            if (type != QUOTESTRING) {
3467
0
                print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3468
0
                goto skip;
3469
0
            }
3470
0
            type = get_token(fp, token, MAXTOKEN);
3471
0
        }
3472
2
    }
3473
349
    if (type != EQUALS)
3474
339
        print_error("Expected \"::=\"", token, type);
3475
5.44k
  skip:
3476
486k
    while (type != EQUALS && type != ENDOFFILE) {
3477
480k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3478
480k
    }
3479
5.44k
    return merge_parse_objectid(np, fp, name);
3480
349
}
3481
3482
/*
3483
 * Parses a module identity macro
3484
 * Returns 0 on error.
3485
 */
3486
static void
3487
check_utc(const char *utc)
3488
5.68k
{
3489
5.68k
    int             len, year, month, day, hour, minute;
3490
3491
5.68k
    len = strlen(utc);
3492
5.68k
    if (len == 0) {
3493
234
        print_error("Timestamp has zero length", utc, QUOTESTRING);
3494
234
        return;
3495
234
    }
3496
5.44k
    if (utc[len - 1] != 'Z' && utc[len - 1] != 'z') {
3497
1.37k
        print_error("Timestamp should end with Z", utc, QUOTESTRING);
3498
1.37k
        return;
3499
1.37k
    }
3500
4.07k
    if (len == 11) {
3501
1.14k
        len = sscanf(utc, "%2d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
3502
1.14k
                     &minute);
3503
1.14k
        year += 1900;
3504
2.92k
    } else if (len == 13)
3505
515
        len = sscanf(utc, "%4d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
3506
515
                     &minute);
3507
2.41k
    else {
3508
2.41k
        print_error("Bad timestamp format (11 or 13 characters)",
3509
2.41k
                    utc, QUOTESTRING);
3510
2.41k
        return;
3511
2.41k
    }
3512
1.66k
    if (len != 5) {
3513
404
        print_error("Bad timestamp format", utc, QUOTESTRING);
3514
404
        return;
3515
404
    }
3516
1.25k
    if (month < 1 || month > 12)
3517
687
        print_error("Bad month in timestamp", utc, QUOTESTRING);
3518
1.25k
    if (day < 1 || day > 31)
3519
691
        print_error("Bad day in timestamp", utc, QUOTESTRING);
3520
1.25k
    if (hour < 0 || hour > 23)
3521
612
        print_error("Bad hour in timestamp", utc, QUOTESTRING);
3522
1.25k
    if (minute < 0 || minute > 59)
3523
669
        print_error("Bad minute in timestamp", utc, QUOTESTRING);
3524
1.25k
}
3525
3526
static struct node *
3527
parse_moduleIdentity(FILE * fp, char *name)
3528
5.77k
{
3529
5.77k
    register int    type;
3530
5.77k
    char            token[MAXTOKEN];
3531
5.77k
    char            quoted_string_buffer[MAXQUOTESTR];
3532
5.77k
    register struct node *np;
3533
3534
5.77k
    np = alloc_node(current_module);
3535
5.77k
    if (np == NULL)
3536
0
        return (NULL);
3537
5.77k
    type = get_token(fp, token, MAXTOKEN);
3538
5.77k
    if (type != LASTUPDATED) {
3539
826
        print_error("Expected LAST-UPDATED", token, type);
3540
826
        goto skip;
3541
826
    }
3542
4.94k
    type = get_token(fp, token, MAXTOKEN);
3543
4.94k
    if (type != QUOTESTRING) {
3544
99
        print_error("Need STRING for LAST-UPDATED", token, type);
3545
99
        goto skip;
3546
99
    }
3547
4.85k
    check_utc(token);
3548
4.85k
    type = get_token(fp, token, MAXTOKEN);
3549
4.85k
    if (type != ORGANIZATION) {
3550
2.12k
        print_error("Expected ORGANIZATION", token, type);
3551
2.12k
        goto skip;
3552
2.12k
    }
3553
2.72k
    type = get_token(fp, token, MAXTOKEN);
3554
2.72k
    if (type != QUOTESTRING) {
3555
257
        print_error("Bad ORGANIZATION", token, type);
3556
257
        goto skip;
3557
257
    }
3558
2.47k
    type = get_token(fp, token, MAXTOKEN);
3559
2.47k
    if (type != CONTACTINFO) {
3560
628
        print_error("Expected CONTACT-INFO", token, type);
3561
628
        goto skip;
3562
628
    }
3563
1.84k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3564
1.84k
    if (type != QUOTESTRING) {
3565
281
        print_error("Bad CONTACT-INFO", quoted_string_buffer, type);
3566
281
        goto skip;
3567
281
    }
3568
1.56k
    type = get_token(fp, token, MAXTOKEN);
3569
1.56k
    if (type != DESCRIPTION) {
3570
317
        print_error("Expected DESCRIPTION", token, type);
3571
317
        goto skip;
3572
317
    }
3573
1.24k
    type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3574
1.24k
    if (type != QUOTESTRING) {
3575
327
        print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3576
327
        goto skip;
3577
327
    }
3578
918
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
3579
918
             NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
3580
0
        np->description = strdup(quoted_string_buffer);
3581
0
    }
3582
918
    type = get_token(fp, token, MAXTOKEN);
3583
1.44k
    while (type == REVISION) {
3584
961
        type = get_token(fp, token, MAXTOKEN);
3585
961
        if (type != QUOTESTRING) {
3586
128
            print_error("Bad REVISION", token, type);
3587
128
            goto skip;
3588
128
        }
3589
833
        check_utc(token);
3590
833
        type = get_token(fp, token, MAXTOKEN);
3591
833
        if (type != DESCRIPTION) {
3592
234
            print_error("Expected DESCRIPTION", token, type);
3593
234
            goto skip;
3594
234
        }
3595
599
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3596
599
        if (type != QUOTESTRING) {
3597
69
            print_error("Bad DESCRIPTION", quoted_string_buffer, type);
3598
69
            goto skip;
3599
69
        }
3600
530
        type = get_token(fp, token, MAXTOKEN);
3601
530
    }
3602
487
    if (type != EQUALS)
3603
362
        print_error("Expected \"::=\"", token, type);
3604
5.77k
  skip:
3605
141k
    while (type != EQUALS && type != ENDOFFILE) {
3606
135k
        type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
3607
135k
    }
3608
5.77k
    return merge_parse_objectid(np, fp, name);
3609
487
}
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
1.12k
{
3620
1.12k
    register int    type;
3621
1.12k
    char            token[MAXTOKEN];
3622
1.12k
    struct node    *np;
3623
1.12k
    int             iLine = mibLine;
3624
3625
1.12k
    np = alloc_node(current_module);
3626
1.12k
    if (np == NULL)
3627
0
        return (NULL);
3628
1.12k
    type = get_token(fp, token, sizeof(token));
3629
103k
    while (type != EQUALS && type != ENDOFFILE) {
3630
101k
        type = get_token(fp, token, sizeof(token));
3631
101k
    }
3632
1.12k
    if (type != EQUALS) {
3633
44
        if (np)
3634
44
            free_node(np);
3635
44
        return NULL;
3636
44
    }
3637
3.60k
    while (type != BEGIN && type != ENDOFFILE) {
3638
2.52k
        type = get_token(fp, token, sizeof(token));
3639
2.52k
    }
3640
1.07k
    if (type != BEGIN) {
3641
31
        if (np)
3642
31
            free_node(np);
3643
31
        return NULL;
3644
31
    }
3645
24.5k
    while (type != END && type != ENDOFFILE) {
3646
23.4k
        type = get_token(fp, token, sizeof(token));
3647
23.4k
    }
3648
1.04k
    if (type != END) {
3649
22
        if (np)
3650
22
            free_node(np);
3651
22
        return NULL;
3652
22
    }
3653
3654
1.02k
    if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3655
1.02k
         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
1.02k
    return np;
3662
1.04k
}
3663
3664
/*
3665
 * Parses a module import clause
3666
 *   loading any modules referenced
3667
 */
3668
static void
3669
parse_imports(FILE * fp)
3670
2.82k
{
3671
2.82k
    register int    type;
3672
2.82k
    char            token[MAXTOKEN];
3673
2.82k
    char            modbuf[256];
3674
220k
#define MAX_IMPORTS 512
3675
2.82k
    struct module_import *import_list;
3676
2.82k
    int             this_module;
3677
2.82k
    struct module  *mp;
3678
3679
2.82k
    int             import_count = 0;   /* Total number of imported descriptors */
3680
2.82k
    int             i = 0, old_i;       /* index of first import from each module */
3681
3682
2.82k
    import_list = malloc(MAX_IMPORTS * sizeof(*import_list));
3683
3684
2.82k
    type = get_token(fp, token, MAXTOKEN);
3685
3686
    /*
3687
     * Parse the IMPORTS clause
3688
     */
3689
437k
    while (type != SEMI && type != ENDOFFILE) {
3690
435k
        if (type == LABEL) {
3691
218k
            if (import_count == MAX_IMPORTS) {
3692
251
                print_error("Too many imported symbols", token, type);
3693
992k
                do {
3694
992k
                    type = get_token(fp, token, MAXTOKEN);
3695
992k
                } while (type != SEMI && type != ENDOFFILE);
3696
251
                goto out;
3697
251
            }
3698
217k
            import_list[import_count++].label = strdup(token);
3699
217k
        } else if (type == FROM) {
3700
2.59k
            type = get_token(fp, token, MAXTOKEN);
3701
2.59k
            if (import_count == i) {    /* All imports are handled internally */
3702
388
                type = get_token(fp, token, MAXTOKEN);
3703
388
                continue;
3704
388
            }
3705
2.20k
            this_module = which_module(token);
3706
3707
64.0k
            for (old_i = i; i < import_count; ++i)
3708
61.8k
                import_list[i].modid = this_module;
3709
3710
            /*
3711
             * Recursively read any pre-requisite modules
3712
             */
3713
2.20k
            if (read_module_internal(token) == MODULE_NOT_FOUND) {
3714
1.85k
    int found = 0;
3715
50.6k
                for (; old_i < import_count; ++old_i) {
3716
48.7k
                    found += read_import_replacements(token, &import_list[old_i]);
3717
48.7k
                }
3718
1.85k
    if (!found)
3719
1.36k
        print_module_not_found(token);
3720
1.85k
            }
3721
2.20k
        }
3722
434k
        type = get_token(fp, token, MAXTOKEN);
3723
434k
    }
3724
3725
    /* Initialize modid in case the module name was missing. */
3726
32.4k
    for (; i < import_count; ++i)
3727
29.9k
        import_list[i].modid = -1;
3728
3729
    /*
3730
     * Save the import information
3731
     *   in the global module table
3732
     */
3733
3.48M
    for (mp = module_head; mp; mp = mp->next) {
3734
3.48M
        if (mp->modid == current_module) {
3735
2.57k
            if (import_count == 0)
3736
292
                goto out;
3737
2.27k
            if (mp->imports && (mp->imports != root_imports)) {
3738
                /*
3739
                 * this can happen if all modules are in one source file. 
3740
                 */
3741
60.2k
                for (i = 0; i < mp->no_imports; ++i) {
3742
59.0k
                    DEBUGMSGTL(("parse-mibs",
3743
59.0k
                                "#### freeing Module %d '%s' %d\n",
3744
59.0k
                                mp->modid, mp->imports[i].label,
3745
59.0k
                                mp->imports[i].modid));
3746
59.0k
                    free(mp->imports[i].label);
3747
59.0k
                }
3748
1.16k
                free(mp->imports);
3749
1.16k
            }
3750
2.27k
            mp->imports = (struct module_import *)
3751
2.27k
                calloc(import_count, sizeof(struct module_import));
3752
2.27k
            if (mp->imports == NULL)
3753
0
                goto out;
3754
91.6k
            for (i = 0; i < import_count; ++i) {
3755
89.4k
                mp->imports[i].label = import_list[i].label;
3756
89.4k
                import_list[i].label = NULL;
3757
89.4k
                mp->imports[i].modid = import_list[i].modid;
3758
89.4k
                DEBUGMSGTL(("parse-mibs",
3759
89.4k
                            "#### adding Module %d '%s' %d\n", mp->modid,
3760
89.4k
                            mp->imports[i].label, mp->imports[i].modid));
3761
89.4k
            }
3762
2.27k
            mp->no_imports = import_count;
3763
2.27k
            goto out;
3764
2.27k
        }
3765
3.48M
    }
3766
3767
    /*
3768
     * Shouldn't get this far
3769
     */
3770
0
    print_module_not_found(module_name(current_module, modbuf));
3771
3772
2.82k
out:
3773
220k
    for (i = 0; i < import_count; ++i)
3774
217k
        free(import_list[i].label);
3775
2.82k
    free(import_list);
3776
2.82k
    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
35.1k
{
3801
35.1k
    struct module  *mp;
3802
3803
123M
    for (mp = module_head; mp; mp = mp->next)
3804
123M
        if (!label_compare(mp->name, name))
3805
17.0k
            return (mp->modid);
3806
3807
18.1k
    DEBUGMSGTL(("parse-mibs", "Module %s not found\n", name));
3808
18.1k
    return (-1);
3809
35.1k
}
3810
3811
/*
3812
 * module_name - copy module name to user buffer, return ptr to same.
3813
 */
3814
char           *
3815
module_name(int modid, char *cp)
3816
97.2k
{
3817
97.2k
    struct module  *mp;
3818
3819
8.62M
    for (mp = module_head; mp; mp = mp->next)
3820
8.59M
        if (mp->modid == modid) {
3821
67.2k
            strcpy(cp, mp->name);
3822
67.2k
            return (cp);
3823
67.2k
        }
3824
3825
29.9k
    if (modid != -1) DEBUGMSGTL(("parse-mibs", "Module %d not found\n", modid));
3826
29.9k
    sprintf(cp, "#%d", modid);
3827
29.9k
    return (cp);
3828
97.2k
}
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
232k
{
3865
232k
    struct module_compatability *mcp;
3866
3867
4.75M
    for (mcp = module_map_head; mcp; mcp = mcp->next) {
3868
4.56M
        if (!label_compare(mcp->old_module, name)) {
3869
33.9k
            if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3870
33.9k
           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
33.9k
            (void) netsnmp_read_module(mcp->new_module);
3876
33.9k
            return 1;
3877
33.9k
        }
3878
4.56M
    }
3879
198k
    return 0;
3880
232k
}
3881
3882
static int
3883
read_import_replacements(const char *old_module_name,
3884
                         struct module_import *identifier)
3885
48.7k
{
3886
48.7k
    struct module_compatability *mcp;
3887
3888
    /*
3889
     * Look for matches first
3890
     */
3891
1.07M
    for (mcp = module_map_head; mcp; mcp = mcp->next) {
3892
1.03M
        if (!label_compare(mcp->old_module, old_module_name)) {
3893
3894
294k
            if (                /* exact match */
3895
294k
                   (mcp->tag_len == 0 &&
3896
294k
                    (mcp->tag == NULL ||
3897
68.4k
                     !label_compare(mcp->tag, identifier->label))) ||
3898
                   /*
3899
                    * prefix match 
3900
                    */
3901
294k
                   (mcp->tag_len != 0 &&
3902
290k
                    !strncmp(mcp->tag, identifier->label, mcp->tag_len))
3903
294k
                ) {
3904
3905
5.44k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
3906
5.44k
               NETSNMP_DS_LIB_MIB_WARNINGS)) {
3907
0
                    snmp_log(LOG_WARNING,
3908
0
                             "Importing %s from replacement module %s instead of %s (%s)\n",
3909
0
                             identifier->label, mcp->new_module,
3910
0
                             old_module_name, File);
3911
0
    }
3912
5.44k
                (void) netsnmp_read_module(mcp->new_module);
3913
5.44k
                identifier->modid = which_module(mcp->new_module);
3914
5.44k
                return 1;         /* finished! */
3915
5.44k
            }
3916
294k
        }
3917
1.03M
    }
3918
3919
    /*
3920
     * If no exact match, load everything relevant
3921
     */
3922
43.3k
    return read_module_replacements(old_module_name);
3923
48.7k
}
3924
3925
static int
3926
read_from_file(struct module *mp, const char *name)
3927
14.8k
{
3928
14.8k
    const char     *oldFile = File;
3929
14.8k
    int             oldLine = mibLine;
3930
14.8k
    int             oldModule = current_module;
3931
14.8k
    FILE           *fp;
3932
14.8k
    struct node    *np;
3933
14.8k
    int             res;
3934
3935
14.8k
    if (mp->no_imports != -1) {
3936
5.19k
        DEBUGMSGTL(("parse-mibs", "Module %s already loaded\n",
3937
5.19k
                    name));
3938
5.19k
        return MODULE_ALREADY_LOADED;
3939
5.19k
    }
3940
9.69k
    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
9.69k
#ifdef HAVE_FLOCKFILE
3950
9.69k
    flockfile(fp);
3951
9.69k
#endif
3952
9.69k
    mp->no_imports = 0; /* Note that we've read the file */
3953
9.69k
    File = mp->file;
3954
9.69k
    mibLine = 1;
3955
9.69k
    current_module = mp->modid;
3956
    /*
3957
     * Parse the file
3958
     */
3959
9.69k
    np = parse(fp);
3960
9.69k
#ifdef HAVE_FUNLOCKFILE
3961
9.69k
    funlockfile(fp);
3962
9.69k
#endif
3963
9.69k
    fclose(fp);
3964
9.69k
    File = oldFile;
3965
9.69k
    mibLine = oldLine;
3966
9.69k
    current_module = oldModule;
3967
9.69k
    res = !np && gMibError == MODULE_SYNTAX_ERROR ?
3968
5.35k
        MODULE_SYNTAX_ERROR : MODULE_LOADED_OK;
3969
15.5k
    while (np) {
3970
5.84k
        struct node *nnp = np->next;
3971
5.84k
        free_node(np);
3972
5.84k
        np = nnp;
3973
5.84k
    }
3974
9.69k
    return res;
3975
9.69k
}
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
205k
{
3985
205k
    struct module  *mp;
3986
3987
205k
    netsnmp_init_mib_internals();
3988
3989
290M
    for (mp = module_head; mp; mp = mp->next)
3990
290M
        if (!label_compare(mp->name, name))
3991
14.8k
            return read_from_file(mp, name);
3992
3993
190k
    return MODULE_NOT_FOUND;
3994
205k
}
3995
3996
void
3997
adopt_orphans(void)
3998
3.20k
{
3999
3.20k
    struct node    *np = NULL, *onp;
4000
3.20k
    struct tree    *tp;
4001
3.20k
    int             i, adopted = 1;
4002
4003
3.20k
    if (!orphan_nodes)
4004
4
        return;
4005
3.20k
    init_node_hash(orphan_nodes);
4006
3.20k
    orphan_nodes = NULL;
4007
4008
6.59k
    while (adopted) {
4009
3.39k
        adopted = 0;
4010
437k
        for (i = 0; i < NHASHSIZE; i++)
4011
434k
            if (nbuckets[i]) {
4012
163k
                for (np = nbuckets[i]; np != NULL; np = np->next) {
4013
98.3k
                    tp = find_tree_node(np->parent, -1);
4014
98.3k
        if (tp) {
4015
275
      do_subtree(tp, &np);
4016
275
      adopted = 1;
4017
                        /*
4018
                         * if do_subtree adopted the entire bucket, stop
4019
                         */
4020
275
                        if(NULL == nbuckets[i])
4021
257
                            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
43
                        for(onp = nbuckets[i]; onp; onp = onp->next)
4031
25
                            if(onp == np)
4032
0
                                break;
4033
18
                        if(NULL == onp) { /* not in the list */
4034
18
                            np = nbuckets[i]; /* start over */
4035
18
                        }
4036
18
        }
4037
98.3k
    }
4038
65.8k
            }
4039
3.39k
    }
4040
4041
    /*
4042
     * Report on outstanding orphans
4043
     *    and link them back into the orphan list
4044
     */
4045
412k
    for (i = 0; i < NHASHSIZE; i++)
4046
409k
        if (nbuckets[i]) {
4047
61.7k
            if (orphan_nodes)
4048
58.5k
                onp = np->next = nbuckets[i];
4049
3.20k
            else
4050
3.20k
                onp = orphan_nodes = nbuckets[i];
4051
61.7k
            nbuckets[i] = NULL;
4052
154k
            while (onp) {
4053
92.4k
                char            modbuf[256];
4054
92.4k
                snmp_log(LOG_WARNING,
4055
92.4k
                         "Cannot resolve OID in %s: %s ::= { %s %ld } at line %d in %s\n",
4056
92.4k
                         module_name(onp->modid, modbuf),
4057
92.4k
                         (onp->label ? onp->label : "<no label>"),
4058
92.4k
                         (onp->parent ? onp->parent : "<no parent>"),
4059
92.4k
                         onp->subid, onp->lineno, onp->filename);
4060
92.4k
                np = onp;
4061
92.4k
                onp = onp->next;
4062
92.4k
            }
4063
61.7k
        }
4064
3.20k
}
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
198k
{
4077
198k
    int status = 0;
4078
198k
    status = read_module_internal(name);
4079
4080
198k
    if (status == MODULE_NOT_FOUND) {
4081
188k
        if (!read_module_replacements(name))
4082
186k
            print_module_not_found(name);
4083
188k
    } else if (status == MODULE_SYNTAX_ERROR) {
4084
4.33k
        gMibError = 0;
4085
4.33k
        gLoop = 1;
4086
4087
4.33k
        strncat(gMibNames, " ", sizeof(gMibNames) - strlen(gMibNames) - 1);
4088
4.33k
        strncat(gMibNames, name, sizeof(gMibNames) - strlen(gMibNames) - 1);
4089
4.33k
    }
4090
4091
198k
    return tree_head;
4092
198k
}
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
11.9k
{
4102
11.9k
    struct tree    *tp, *next;
4103
11.9k
    int             i;
4104
4105
39.2k
    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
27.3k
        int             nmod = tp->number_modules;
4114
27.3k
        if (nmod > 0) {         /* in some module */
4115
            /*
4116
             * Remove all copies of this module ID
4117
             */
4118
27.3k
            int             cnt = 0, *pi1, *pi2 = tp->module_list;
4119
55.4k
            for (i = 0, pi1 = pi2; i < nmod; i++, pi2++) {
4120
28.1k
                if (*pi2 == modID)
4121
20.1k
                    continue;
4122
7.94k
                cnt++;
4123
7.94k
                *pi1++ = *pi2;
4124
7.94k
            }
4125
27.3k
            if (nmod != cnt) {  /* in this module */
4126
                /*
4127
                 * if ( (nmod - cnt) > 1)
4128
                 * printf("Dup modid %d,  %d times, '%s'\n", tp->modid, (nmod-cnt), tp->label); fflush(stdout); ?* XXDEBUG 
4129
                 */
4130
19.4k
                tp->number_modules = cnt;
4131
19.4k
                switch (cnt) {
4132
19.4k
                case 0:
4133
19.4k
                    tp->module_list[0] = -1;    /* Mark unused, */
4134
19.4k
        NETSNMP_FALLTHROUGH;
4135
4136
19.4k
                case 1:        /* save the remaining module */
4137
19.4k
                    if (&(tp->modid) != tp->module_list) {
4138
437
                        tp->modid = tp->module_list[0];
4139
437
                        free(tp->module_list);
4140
437
                        tp->module_list = &(tp->modid);
4141
437
                    }
4142
19.4k
                    break;
4143
4144
0
                default:
4145
0
                    break;
4146
19.4k
                }
4147
19.4k
            }                   /* if tree node is in this module */
4148
27.3k
        }
4149
        /*
4150
         * if tree node is in some module 
4151
         */
4152
27.3k
        next = tp->next_peer;
4153
4154
4155
        /*
4156
         *  OK - that's dealt with *this* node.
4157
         *    Now let's look at the children.
4158
         *    (Isn't recursion wonderful!)
4159
         */
4160
27.3k
        if (tp->child_list)
4161
6.30k
            unload_module_by_ID(modID, tp->child_list);
4162
4163
4164
27.3k
        if (tp->number_modules == 0) {
4165
            /*
4166
             * This node isn't needed any more (except perhaps
4167
             * for the sake of the children) 
4168
             */
4169
19.4k
            if (tp->child_list == NULL) {
4170
19.4k
                unlink_tree(tp);
4171
19.4k
                free_tree(tp);
4172
19.4k
            } else {
4173
33
                free_partial_tree(tp, TRUE);
4174
33
            }
4175
19.4k
        }
4176
27.3k
    }
4177
11.9k
}
4178
4179
#ifndef NETSNMP_NO_LEGACY_DEFINITIONS
4180
int
4181
unload_module(const char *name)
4182
0
{
4183
0
    return netsnmp_unload_module(name);
4184
0
}
4185
#endif
4186
4187
int
4188
netsnmp_unload_module(const char *name)
4189
0
{
4190
0
    struct module  *mp;
4191
0
    int             modID = -1;
4192
4193
0
    for (mp = module_head; mp; mp = mp->next)
4194
0
        if (!label_compare(mp->name, name)) {
4195
0
            modID = mp->modid;
4196
0
            break;
4197
0
        }
4198
4199
0
    if (modID == -1) {
4200
0
        DEBUGMSGTL(("unload-mib", "Module %s not found to unload\n",
4201
0
                    name));
4202
0
        return MODULE_NOT_FOUND;
4203
0
    }
4204
0
    unload_module_by_ID(modID, tree_head);
4205
0
    mp->no_imports = -1;        /* mark as unloaded */
4206
0
    return MODULE_LOADED_OK;    /* Well, you know what I mean! */
4207
0
}
4208
4209
/*
4210
 * Clear module map, tree nodes, textual convention table.
4211
 */
4212
void
4213
unload_all_mibs(void)
4214
3.20k
{
4215
3.20k
    struct module  *mp;
4216
3.20k
    struct module_compatability *mcp;
4217
3.20k
    struct tc      *ptc;
4218
3.20k
    unsigned int    i;
4219
4220
3.20k
    for (mcp = module_map_head; mcp; mcp = module_map_head) {
4221
3.20k
        if (mcp == module_map)
4222
3.20k
            break;
4223
0
        module_map_head = mcp->next;
4224
0
        if (mcp->tag) free(NETSNMP_REMOVE_CONST(char *, mcp->tag));
4225
0
        free(NETSNMP_REMOVE_CONST(char *, mcp->old_module));
4226
0
        free(NETSNMP_REMOVE_CONST(char *, mcp->new_module));
4227
0
        free(mcp);
4228
0
    }
4229
4230
5.66k
    for (mp = module_head; mp; mp = module_head) {
4231
2.46k
        struct module_import *mi = mp->imports;
4232
2.46k
        if (mi) {
4233
7.05k
            for (i = 0; i < (unsigned int)mp->no_imports; ++i) {
4234
5.77k
                SNMP_FREE((mi + i)->label);
4235
5.77k
            }
4236
1.27k
            mp->no_imports = 0;
4237
1.27k
            if (mi == root_imports)
4238
908
                memset(mi, 0, sizeof(*mi));
4239
368
            else
4240
368
                free(mi);
4241
1.27k
        }
4242
4243
2.46k
        unload_module_by_ID(mp->modid, tree_head);
4244
2.46k
        module_head = mp->next;
4245
2.46k
        free(mp->name);
4246
2.46k
        free(mp->file);
4247
2.46k
        free(mp);
4248
2.46k
    }
4249
3.20k
    unload_module_by_ID(-1, tree_head);
4250
    /*
4251
     * tree nodes are cleared 
4252
     */
4253
4254
323k
    for (i = 0, ptc = tclist; i < tc_alloc; i++, ptc++) {
4255
320k
        if (ptc->type == 0)
4256
319k
            continue;
4257
360
        free_enums(&ptc->enums);
4258
360
        free_ranges(&ptc->ranges);
4259
360
        free(ptc->descriptor);
4260
360
        if (ptc->hint)
4261
2
            free(ptc->hint);
4262
360
        if (ptc->description)
4263
0
            free(ptc->description);
4264
360
    }
4265
3.20k
    SNMP_FREE(tclist);
4266
3.20k
    tc_alloc = 0;
4267
4268
3.20k
    memset(buckets, 0, sizeof(buckets));
4269
3.20k
    memset(nbuckets, 0, sizeof(nbuckets));
4270
3.20k
    memset(tbuckets, 0, sizeof(tbuckets));
4271
4272
12.8k
    for (i = 0; i < sizeof(root_imports) / sizeof(root_imports[0]); i++) {
4273
9.60k
        SNMP_FREE(root_imports[i].label);
4274
9.60k
    }
4275
4276
3.20k
    max_module = 0;
4277
3.20k
    current_module = 0;
4278
3.20k
    module_map_head = NULL;
4279
3.20k
    SNMP_FREE(last_err_module);
4280
3.20k
}
4281
4282
static void
4283
new_module(const char *name, const char *file)
4284
12.6k
{
4285
12.6k
    struct module  *mp;
4286
4287
26.2M
    for (mp = module_head; mp; mp = mp->next)
4288
26.2M
        if (!label_compare(mp->name, name)) {
4289
2.66k
            DEBUGMSGTL(("parse-mibs", "  Module %s already noted\n", name));
4290
            /*
4291
             * Not the same file 
4292
             */
4293
2.66k
            if (label_compare(mp->file, file)) {
4294
2.23k
                DEBUGMSGTL(("parse-mibs", "    %s is now in %s\n",
4295
2.23k
                            name, file));
4296
2.23k
                if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
4297
2.23k
               NETSNMP_DS_LIB_MIB_WARNINGS)) {
4298
0
                    snmp_log(LOG_WARNING,
4299
0
                             "Warning: Module %s was in %s now is %s\n",
4300
0
                             name, mp->file, file);
4301
0
    }
4302
4303
                /*
4304
                 * Use the new one in preference 
4305
                 */
4306
2.23k
                free(mp->file);
4307
2.23k
                mp->file = strdup(file);
4308
2.23k
            }
4309
2.66k
            return;
4310
2.66k
        }
4311
4312
    /*
4313
     * Add this module to the list 
4314
     */
4315
9.96k
    DEBUGMSGTL(("parse-mibs", "  Module %d %s is in %s\n", max_module,
4316
9.96k
                name, file));
4317
9.96k
    mp = calloc(1, sizeof(struct module));
4318
9.96k
    if (mp == NULL)
4319
0
        return;
4320
9.96k
    mp->name = strdup(name);
4321
9.96k
    mp->file = strdup(file);
4322
9.96k
    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
9.96k
    mp->imports = NULL;
4329
9.96k
    mp->no_imports = -1;        /* Not yet loaded */
4330
9.96k
    mp->modid = max_module;
4331
9.96k
    ++max_module;
4332
4333
9.96k
    mp->next = module_head;     /* Or add to the *end* of the list? */
4334
9.96k
    module_head = mp;
4335
9.96k
}
4336
4337
4338
static void
4339
scan_objlist(struct node *root, struct module *mp, struct objgroup *list, const char *error)
4340
31.8k
{
4341
31.8k
    int             oLine = mibLine;
4342
4343
35.7k
    while (list) {
4344
3.89k
        struct objgroup *gp = list;
4345
3.89k
        struct node    *np;
4346
3.89k
        list = list->next;
4347
3.89k
        np = root;
4348
81.0k
        while (np)
4349
78.0k
            if (label_compare(np->label, gp->name))
4350
77.1k
                np = np->next;
4351
904
            else
4352
904
                break;
4353
3.89k
        if (!np) {
4354
2.98k
      int i;
4355
2.98k
      struct module_import *mip;
4356
      /* if not local, check if it was IMPORTed */
4357
71.3k
      for (i = 0, mip = mp->imports; i < mp->no_imports; i++, mip++)
4358
68.5k
    if (strcmp(mip->label, gp->name) == 0)
4359
124
        break;
4360
2.98k
      if (i == mp->no_imports) {
4361
2.75k
    mibLine = gp->line;
4362
2.75k
    print_error(error, gp->name, QUOTESTRING);
4363
2.75k
      }
4364
2.98k
        }
4365
3.89k
        free(gp->name);
4366
3.89k
        free(gp);
4367
3.89k
    }
4368
31.8k
    mibLine = oLine;
4369
31.8k
}
4370
4371
static void free_objgroup(struct objgroup *o)
4372
12.7k
{
4373
29.4k
    while (o) {
4374
16.7k
        struct objgroup *next = o->next;
4375
4376
16.7k
        free(o->name);
4377
16.7k
        free(o);
4378
16.7k
        o = next;
4379
16.7k
    }
4380
12.7k
}
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
9.69k
{
4389
#ifdef TEST
4390
    extern void     xmalloc_stats(FILE *);
4391
#endif
4392
9.69k
    char            token[MAXTOKEN];
4393
9.69k
    char            name[MAXTOKEN+1];
4394
9.69k
    int             type = LABEL;
4395
9.69k
    int             lasttype = LABEL;
4396
4397
32.6k
#define BETWEEN_MIBS          1
4398
22.9k
#define IN_MIB                2
4399
9.69k
    int             state = BETWEEN_MIBS;
4400
9.69k
    struct node    *np = NULL, *root = NULL;
4401
9.69k
    struct objgroup *oldgroups = NULL, *oldobjects = NULL, *oldnotifs =
4402
9.69k
        NULL;
4403
4404
9.69k
    DEBUGMSGTL(("parse-file", "Parsing file:  %s...\n", File));
4405
4406
9.69k
    if (last_err_module)
4407
2.67k
        free(last_err_module);
4408
9.69k
    last_err_module = NULL;
4409
4410
157k
    while (type != ENDOFFILE) {
4411
152k
        struct node *nnp;
4412
4413
152k
        if (lasttype == CONTINUE)
4414
40.3k
            lasttype = type;
4415
111k
        else
4416
111k
            type = lasttype = get_token(fp, token, MAXTOKEN);
4417
4418
152k
        switch (type) {
4419
10.6k
        case END:
4420
10.6k
            if (state != IN_MIB) {
4421
24
                print_error("Error, END before start of MIB", NULL, type);
4422
24
                gMibError = MODULE_SYNTAX_ERROR;
4423
24
                goto free_mib;
4424
10.6k
            } else {
4425
10.6k
                struct module  *mp;
4426
#ifdef TEST
4427
                printf("\nNodes for Module %s:\n", name);
4428
                print_nodes(stdout, root);
4429
#endif
4430
52.6M
                for (mp = module_head; mp; mp = mp->next)
4431
52.6M
                    if (mp->modid == current_module)
4432
10.6k
                        break;
4433
10.6k
                scan_objlist(root, mp, objgroups, "Undefined OBJECT-GROUP");
4434
10.6k
                scan_objlist(root, mp, objects, "Undefined OBJECT");
4435
10.6k
                scan_objlist(root, mp, notifs, "Undefined NOTIFICATION");
4436
10.6k
                objgroups = oldgroups;
4437
10.6k
                objects = oldobjects;
4438
10.6k
                notifs = oldnotifs;
4439
10.6k
                do_linkup(mp, root);
4440
10.6k
                np = root = NULL;
4441
10.6k
            }
4442
10.6k
            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
10.6k
            continue;
4450
2.82k
        case IMPORTS:
4451
2.82k
            parse_imports(fp);
4452
2.82k
            continue;
4453
96
        case EXPORTS:
4454
579
            while (type != SEMI && type != ENDOFFILE)
4455
483
                type = get_token(fp, token, MAXTOKEN);
4456
96
            continue;
4457
99.4k
        case LABEL:
4458
99.5k
        case INTEGER:
4459
100k
        case INTEGER32:
4460
100k
        case UINTEGER32:
4461
100k
        case UNSIGNED32:
4462
101k
        case COUNTER:
4463
101k
        case COUNTER64:
4464
101k
        case GAUGE:
4465
102k
        case IPADDR:
4466
102k
        case NETADDR:
4467
103k
        case NSAPADDRESS:
4468
104k
        case OBJSYNTAX:
4469
104k
        case APPSYNTAX:
4470
104k
        case SIMPLESYNTAX:
4471
104k
        case OBJNAME:
4472
105k
        case NOTIFNAME:
4473
106k
        case KW_OPAQUE:
4474
106k
        case TIMETICKS:
4475
106k
            break;
4476
2.94k
        case ENDOFFILE:
4477
2.94k
            continue;
4478
28.9k
        default:
4479
28.9k
            strlcpy(name, token, sizeof(name));
4480
28.9k
            type = get_token(fp, token, MAXTOKEN);
4481
28.9k
            nnp = NULL;
4482
28.9k
            if (type == MACRO) {
4483
801
                nnp = parse_macro(fp, name);
4484
801
                if (nnp == NULL) {
4485
21
                    print_error("Bad parse of MACRO", NULL, type);
4486
21
                    gMibError = MODULE_SYNTAX_ERROR;
4487
21
                }
4488
801
                free_node(nnp); /* IGNORE */
4489
801
                nnp = NULL;
4490
801
            } else
4491
28.1k
                print_error(name, "is a reserved word", lasttype);
4492
28.9k
            continue;           /* see if we can parse the rest of the file */
4493
152k
        }
4494
106k
        strlcpy(name, token, sizeof(name));
4495
106k
        type = get_token(fp, token, MAXTOKEN);
4496
106k
        nnp = NULL;
4497
4498
        /*
4499
         * Handle obsolete method to assign an object identifier to a
4500
         * module
4501
         */
4502
106k
        if (lasttype == LABEL && type == LEFTBRACKET) {
4503
327k
            while (type != RIGHTBRACKET && type != ENDOFFILE)
4504
326k
                type = get_token(fp, token, MAXTOKEN);
4505
910
            if (type == ENDOFFILE) {
4506
298
                print_error("Expected \"}\"", token, type);
4507
298
                gMibError = MODULE_SYNTAX_ERROR;
4508
298
                goto free_mib;
4509
298
            }
4510
612
            type = get_token(fp, token, MAXTOKEN);
4511
612
        }
4512
4513
106k
        switch (type) {
4514
12.3k
        case DEFINITIONS:
4515
12.3k
            if (state != BETWEEN_MIBS) {
4516
13
                print_error("Error, nested MIBS", NULL, type);
4517
13
                gMibError = MODULE_SYNTAX_ERROR;
4518
13
                goto free_mib;
4519
13
            }
4520
12.3k
            state = IN_MIB;
4521
12.3k
            current_module = which_module(name);
4522
12.3k
            oldgroups = objgroups;
4523
12.3k
            objgroups = NULL;
4524
12.3k
            oldobjects = objects;
4525
12.3k
            objects = NULL;
4526
12.3k
            oldnotifs = notifs;
4527
12.3k
            notifs = NULL;
4528
12.3k
            if (current_module == -1) {
4529
275
                new_module(name, File);
4530
275
                current_module = which_module(name);
4531
275
            }
4532
12.3k
            DEBUGMSGTL(("parse-mibs", "Parsing MIB: %d %s\n",
4533
12.3k
                        current_module, name));
4534
180k
            while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE)
4535
179k
                if (type == BEGIN)
4536
12.0k
                    break;
4537
12.3k
            break;
4538
16.5k
        case OBJTYPE:
4539
16.5k
            nnp = parse_objecttype(fp, name);
4540
16.5k
            if (nnp == NULL) {
4541
577
                print_error("Bad parse of OBJECT-TYPE", NULL, type);
4542
577
                gMibError = MODULE_SYNTAX_ERROR;
4543
577
                goto free_mib;
4544
577
            }
4545
16.0k
            break;
4546
16.0k
        case OBJGROUP:
4547
2.39k
            nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
4548
2.39k
            if (nnp == NULL) {
4549
83
                print_error("Bad parse of OBJECT-GROUP", NULL, type);
4550
83
                gMibError = MODULE_SYNTAX_ERROR;
4551
83
                goto free_mib;
4552
83
            }
4553
2.30k
            break;
4554
2.30k
        case NOTIFGROUP:
4555
470
            nnp = parse_objectgroup(fp, name, NOTIFICATIONS, &notifs);
4556
470
            if (nnp == NULL) {
4557
34
                print_error("Bad parse of NOTIFICATION-GROUP", NULL, type);
4558
34
                gMibError = MODULE_SYNTAX_ERROR;
4559
34
                goto free_mib;
4560
34
            }
4561
436
            break;
4562
528
        case TRAPTYPE:
4563
528
            nnp = parse_trapDefinition(fp, name);
4564
528
            if (nnp == NULL) {
4565
174
                print_error("Bad parse of TRAP-TYPE", NULL, type);
4566
174
                gMibError = MODULE_SYNTAX_ERROR;
4567
174
                goto free_mib;
4568
174
            }
4569
354
            break;
4570
2.71k
        case NOTIFTYPE:
4571
2.71k
            nnp = parse_notificationDefinition(fp, name);
4572
2.71k
            if (nnp == NULL) {
4573
130
                print_error("Bad parse of NOTIFICATION-TYPE", NULL, type);
4574
130
                gMibError = MODULE_SYNTAX_ERROR;
4575
130
                goto free_mib;
4576
130
            }
4577
2.58k
            break;
4578
12.8k
        case COMPLIANCE:
4579
12.8k
            nnp = parse_compliance(fp, name);
4580
12.8k
            if (nnp == NULL) {
4581
708
                print_error("Bad parse of MODULE-COMPLIANCE", NULL, type);
4582
708
                gMibError = MODULE_SYNTAX_ERROR;
4583
708
                goto free_mib;
4584
708
            }
4585
12.1k
            break;
4586
12.1k
        case AGENTCAP:
4587
5.44k
            nnp = parse_capabilities(fp, name);
4588
5.44k
            if (nnp == NULL) {
4589
227
                print_error("Bad parse of AGENT-CAPABILITIES", NULL, type);
4590
227
                gMibError = MODULE_SYNTAX_ERROR;
4591
227
                goto free_mib;
4592
227
            }
4593
5.21k
            break;
4594
5.21k
        case MACRO:
4595
320
            nnp = parse_macro(fp, name);
4596
320
            if (nnp == NULL) {
4597
76
                print_error("Bad parse of MACRO", NULL, type);
4598
76
                gMibError = MODULE_SYNTAX_ERROR;
4599
76
            }
4600
320
            free_node(nnp);     /* IGNORE */
4601
320
            nnp = NULL;
4602
320
            break;
4603
5.77k
        case MODULEIDENTITY:
4604
5.77k
            nnp = parse_moduleIdentity(fp, name);
4605
5.77k
            if (nnp == NULL) {
4606
358
                print_error("Bad parse of MODULE-IDENTITY", NULL, type);
4607
358
                gMibError = MODULE_SYNTAX_ERROR;
4608
358
                goto free_mib;
4609
358
            }
4610
5.41k
            break;
4611
5.41k
        case OBJIDENTITY:
4612
1.14k
            nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
4613
1.14k
            if (nnp == NULL) {
4614
87
                print_error("Bad parse of OBJECT-IDENTITY", NULL, type);
4615
87
                gMibError = MODULE_SYNTAX_ERROR;
4616
87
                goto free_mib;
4617
87
            }
4618
1.05k
            break;
4619
2.39k
        case OBJECT:
4620
2.39k
            type = get_token(fp, token, MAXTOKEN);
4621
2.39k
            if (type != IDENTIFIER) {
4622
19
                print_error("Expected IDENTIFIER", token, type);
4623
19
                gMibError = MODULE_SYNTAX_ERROR;
4624
19
                goto free_mib;
4625
19
            }
4626
2.37k
            type = get_token(fp, token, MAXTOKEN);
4627
2.37k
            if (type != EQUALS) {
4628
5
                print_error("Expected \"::=\"", token, type);
4629
5
                gMibError = MODULE_SYNTAX_ERROR;
4630
5
                goto free_mib;
4631
5
            }
4632
2.37k
            nnp = parse_objectid(fp, name);
4633
2.37k
            if (nnp == NULL) {
4634
3
                print_error("Bad parse of OBJECT IDENTIFIER", NULL, type);
4635
3
                gMibError = MODULE_SYNTAX_ERROR;
4636
3
                goto free_mib;
4637
3
            }
4638
2.36k
            break;
4639
40.6k
        case EQUALS:
4640
40.6k
            nnp = parse_asntype(fp, name, &type, token);
4641
40.6k
            lasttype = CONTINUE;
4642
40.6k
            break;
4643
1.15k
        case ENDOFFILE:
4644
1.15k
            break;
4645
1.50k
        default:
4646
1.50k
            print_error("Bad operator", token, type);
4647
1.50k
            gMibError = MODULE_SYNTAX_ERROR;
4648
1.50k
            goto free_mib;
4649
106k
        }
4650
102k
        if (nnp) {
4651
59.6k
            struct node *op;
4652
59.6k
            if (np)
4653
48.1k
                np->next = nnp;
4654
11.5k
            else
4655
11.5k
                np = root = nnp;
4656
313k
            while (np->next)
4657
253k
                np = np->next;
4658
59.6k
            if (np->type == TYPE_OTHER)
4659
43.6k
                np->type = type;
4660
59.6k
            op = root;
4661
11.3M
            while (op != nnp) {
4662
11.3M
                if (strcmp(nnp->label, op->label) == 0 && nnp->subid != op->subid) {
4663
211k
                    snmp_log(LOG_ERR, 
4664
211k
                        "Duplicate Object '%s' at line %d in %s. First at line %d\n",
4665
211k
                        op->label, mibLine, File, op->lineno);
4666
211k
        erroneousMibs++;
4667
211k
    }
4668
11.3M
                op = op->next;
4669
11.3M
            }
4670
59.6k
        }
4671
102k
    }
4672
5.45k
    DEBUGMSGTL(("parse-file", "End of file (%s)\n", File));
4673
5.45k
    return root;
4674
4675
4.24k
free_mib:
4676
82.1k
    for (; root; root = np) {
4677
77.8k
        np = root->next;
4678
77.8k
        free_node(root);
4679
77.8k
    }
4680
4.24k
    free_objgroup(objgroups);
4681
4.24k
    objgroups = NULL;
4682
4.24k
    free_objgroup(objects);
4683
4.24k
    objects = NULL;
4684
4.24k
    free_objgroup(notifs);
4685
4.24k
    notifs = NULL;
4686
4.24k
    return NULL;
4687
9.69k
}
4688
4689
/*
4690
 * return zero if character is not a label character. 
4691
 */
4692
static int
4693
is_labelchar(int ich)
4694
17.1M
{
4695
17.1M
    netsnmp_assert(ich == EOF || (0 <= ich && ich < 256));
4696
17.1M
    if ((isalnum(ich)) || (ich == '-'))
4697
12.7M
        return 1;
4698
4.36M
    if (ich == '_' && netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
4699
5.30k
               NETSNMP_DS_LIB_MIB_PARSE_LABEL)) {
4700
0
        return 1;
4701
0
    }
4702
4703
4.36M
    return 0;
4704
4.36M
}
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
57.6M
{
4714
57.6M
#ifdef HAVE_FGETC_UNLOCKED
4715
57.6M
    return fgetc_unlocked(stream);
4716
#else
4717
    return getc(stream);
4718
#endif
4719
57.6M
}
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
8.71M
{
4729
8.71M
    int             ch, ch_next;
4730
8.71M
    char           *cp;
4731
8.71M
    int             hash;
4732
8.71M
    struct tok     *tp;
4733
8.71M
    int             too_long;
4734
8.71M
    enum { bdigits, xdigits, other } seenSymbols;
4735
4736
9.82M
fetch_next_token:
4737
9.82M
    cp = token;
4738
9.82M
    hash = 0;
4739
9.82M
    too_long = 0;
4740
    /*
4741
     * skip all white space 
4742
     */
4743
14.7M
    do {
4744
14.7M
        ch = netsnmp_getc(fp);
4745
14.7M
        if (ch == '\n')
4746
430k
            mibLine++;
4747
14.7M
    }
4748
14.7M
    while (isspace(ch) && ch != EOF);
4749
9.82M
    *cp++ = ch;
4750
9.82M
    *cp = '\0';
4751
9.82M
    switch (ch) {
4752
10.7k
    case EOF:
4753
10.7k
        return ENDOFFILE;
4754
250k
    case '"':
4755
250k
        return parseQuoteString(fp, token, maxtlen);
4756
384k
    case '\'':                 /* binary or hex constant */
4757
384k
        seenSymbols = bdigits;
4758
4.95M
        while ((ch = netsnmp_getc(fp)) != EOF && ch != '\'') {
4759
4.57M
            switch (seenSymbols) {
4760
28.4k
            case bdigits:
4761
28.4k
                if (ch == '0' || ch == '1')
4762
5.54k
                    break;
4763
22.8k
                seenSymbols = xdigits;
4764
22.8k
                NETSNMP_FALLTHROUGH;
4765
31.0k
            case xdigits:
4766
31.0k
                if (isxdigit(ch))
4767
9.48k
                    break;
4768
21.5k
                seenSymbols = other;
4769
21.5k
                NETSNMP_FALLTHROUGH;
4770
4.55M
            case other:
4771
4.55M
                break;
4772
4.57M
            }
4773
4.57M
            if (cp - token < maxtlen - 2)
4774
1.11M
                *cp++ = ch;
4775
4.57M
        }
4776
384k
        if (ch == '\'') {
4777
383k
            unsigned long   val = 0;
4778
383k
            char           *run = token + 1;
4779
383k
            ch = netsnmp_getc(fp);
4780
383k
            switch (ch) {
4781
19
            case EOF:
4782
19
                return ENDOFFILE;
4783
921
            case 'b':
4784
1.56k
            case 'B':
4785
1.56k
                if (seenSymbols > bdigits) {
4786
872
                    *cp++ = '\'';
4787
872
                    *cp = 0;
4788
872
                    return LABEL;
4789
872
                }
4790
1.47k
                while (run != cp)
4791
776
                    val = val * 2 + *run++ - '0';
4792
697
                break;
4793
1.22k
            case 'h':
4794
3.51k
            case 'H':
4795
3.51k
                if (seenSymbols > xdigits) {
4796
1.33k
                    *cp++ = '\'';
4797
1.33k
                    *cp = 0;
4798
1.33k
                    return LABEL;
4799
1.33k
                }
4800
6.33k
                while (run != cp) {
4801
4.15k
                    ch = *run++;
4802
4.15k
                    if ('0' <= ch && ch <= '9')
4803
1.58k
                        val = val * 16 + ch - '0';
4804
2.56k
                    else if ('a' <= ch && ch <= 'f')
4805
1.10k
                        val = val * 16 + ch - 'a' + 10;
4806
1.45k
                    else if ('A' <= ch && ch <= 'F')
4807
1.45k
                        val = val * 16 + ch - 'A' + 10;
4808
4.15k
                }
4809
2.18k
                break;
4810
378k
            default:
4811
378k
                *cp++ = '\'';
4812
378k
                *cp = 0;
4813
378k
                return LABEL;
4814
383k
            }
4815
2.87k
            sprintf(token, "%ld", val);
4816
2.87k
            return NUMBER;
4817
383k
        } else
4818
1.04k
            return LABEL;
4819
36.9k
    case '(':
4820
36.9k
        return LEFTPAREN;
4821
31.3k
    case ')':
4822
31.3k
        return RIGHTPAREN;
4823
1.79M
    case '{':
4824
1.79M
        return LEFTBRACKET;
4825
326k
    case '}':
4826
326k
        return RIGHTBRACKET;
4827
12.6k
    case '[':
4828
12.6k
        return LEFTSQBRACK;
4829
12.7k
    case ']':
4830
12.7k
        return RIGHTSQBRACK;
4831
11.8k
    case ';':
4832
11.8k
        return SEMI;
4833
38.5k
    case ',':
4834
38.5k
        return COMMA;
4835
12.3k
    case '|':
4836
12.3k
        return BAR;
4837
201k
    case '.':
4838
201k
        ch_next = netsnmp_getc(fp);
4839
201k
        if (ch_next == '.')
4840
187k
            return RANGE;
4841
13.3k
        ungetc(ch_next, fp);
4842
13.3k
        return LABEL;
4843
1.22M
    case ':':
4844
1.22M
        ch_next = netsnmp_getc(fp);
4845
1.22M
        if (ch_next != ':') {
4846
17.8k
            ungetc(ch_next, fp);
4847
17.8k
            return LABEL;
4848
17.8k
        }
4849
1.21M
        ch_next = netsnmp_getc(fp);
4850
1.21M
        if (ch_next != '=') {
4851
1.10M
            ungetc(ch_next, fp);
4852
1.10M
            return LABEL;
4853
1.10M
        }
4854
104k
        return EQUALS;
4855
1.17M
    case '-':
4856
1.17M
        ch_next = netsnmp_getc(fp);
4857
1.17M
        if (ch_next == '-') {
4858
1.10M
            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
4859
1.10M
               NETSNMP_DS_LIB_MIB_COMMENT_TERM)) {
4860
                /*
4861
                 * Treat the rest of this line as a comment. 
4862
                 */
4863
0
                while ((ch_next != EOF) && (ch_next != '\n'))
4864
0
                    ch_next = netsnmp_getc(fp);
4865
1.10M
            } else {
4866
                /*
4867
                 * Treat the rest of the line or until another '--' as a comment 
4868
                 */
4869
                /*
4870
                 * (this is the "technically" correct way to parse comments) 
4871
                 */
4872
1.10M
                ch = ' ';
4873
1.10M
                ch_next = netsnmp_getc(fp);
4874
11.3M
                while (ch_next != EOF && ch_next != '\n' &&
4875
11.3M
                       (ch != '-' || ch_next != '-')) {
4876
10.2M
                    ch = ch_next;
4877
10.2M
                    ch_next = netsnmp_getc(fp);
4878
10.2M
                }
4879
1.10M
            }
4880
1.10M
            if (ch_next == EOF)
4881
111
                return ENDOFFILE;
4882
1.10M
            if (ch_next == '\n')
4883
164k
                mibLine++;
4884
1.10M
            goto fetch_next_token;
4885
1.10M
        }
4886
61.8k
        ungetc(ch_next, fp);
4887
61.8k
  NETSNMP_FALLTHROUGH;
4888
4.35M
    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
4.35M
        if (!is_labelchar(ch))
4895
3.11M
            return LABEL;
4896
1.23M
        hash += tolower(ch);
4897
1.24M
      more:
4898
12.7M
        while (is_labelchar(ch_next = netsnmp_getc(fp))) {
4899
11.5M
            hash += tolower(ch_next);
4900
11.5M
            if (cp - token < maxtlen - 1)
4901
8.62M
                *cp++ = ch_next;
4902
2.89M
            else
4903
2.89M
                too_long = 1;
4904
11.5M
        }
4905
1.24M
        ungetc(ch_next, fp);
4906
1.24M
        *cp = '\0';
4907
4908
1.24M
        if (too_long)
4909
1.48k
            print_error("Warning: token too long", token, CONTINUE);
4910
4.00M
        for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
4911
3.25M
            if ((tp->hash == hash) && (!label_compare(tp->name, token)))
4912
485k
                break;
4913
3.25M
        }
4914
1.24M
        if (tp) {
4915
485k
            if (tp->token != CONTINUE)
4916
478k
                return (tp->token);
4917
7.26k
            while (isspace((ch_next = netsnmp_getc(fp))))
4918
1.89M
                if (ch_next == '\n')
4919
67.7k
                    mibLine++;
4920
7.26k
            if (ch_next == EOF)
4921
16
                return ENDOFFILE;
4922
7.25k
            if (isalnum(ch_next)) {
4923
6.13k
                *cp++ = ch_next;
4924
6.13k
                hash += tolower(ch_next);
4925
6.13k
                goto more;
4926
6.13k
            }
4927
7.25k
        }
4928
760k
        if (token[0] == '-' || isdigit((unsigned char)(token[0]))) {
4929
568k
            for (cp = token + 1; *cp; cp++)
4930
410k
                if (!isdigit((unsigned char)(*cp)))
4931
37.1k
                    return LABEL;
4932
158k
            return NUMBER;
4933
195k
        }
4934
565k
        return LABEL;
4935
9.82M
    }
4936
9.82M
}
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
23.5k
{
4950
23.5k
    FILE           *fp;
4951
23.5k
    char            token[MAXTOKEN], token2[MAXTOKEN];
4952
4953
    /*
4954
     * which module is this 
4955
     */
4956
23.5k
    if ((fp = fopen(tmpstr, "r")) == NULL) {
4957
17
        snmp_log_perror(tmpstr);
4958
17
        return 1;
4959
17
    }
4960
23.5k
    DEBUGMSGTL(("parse-mibs", "Checking file: %s...\n",
4961
23.5k
                tmpstr));
4962
23.5k
    mibLine = 1;
4963
23.5k
    File = tmpstr;
4964
23.5k
    if (get_token(fp, token, MAXTOKEN) != LABEL) {
4965
14.2k
      fclose(fp);
4966
14.2k
      return 1;
4967
14.2k
    }
4968
    /*
4969
     * simple test for this being a MIB 
4970
     */
4971
9.30k
    if (get_token(fp, token2, MAXTOKEN) == DEFINITIONS) {
4972
4.49k
        new_module(token, tmpstr);
4973
4.49k
        fclose(fp);
4974
4.49k
        return 0;
4975
4.81k
    } else {
4976
4.81k
        fclose(fp);
4977
4.81k
        return 1;
4978
4.81k
    }
4979
9.30k
}
4980
4981
static int elemcmp(const void *a, const void *b)
4982
34.4k
{
4983
34.4k
    const char *const *s1 = a, *const *s2 = b;
4984
4985
34.4k
    return strcmp(*s1, *s2);
4986
34.4k
}
4987
4988
/*
4989
 * Scan a directory and return all filenames found as an array of pointers to
4990
 * directory entries (@result).
4991
 */
4992
static int scan_directory(char ***result, const char *dirname)
4993
3.20k
{
4994
3.20k
    DIR            *dir, *dir2;
4995
3.20k
    struct dirent  *file;
4996
3.20k
    char          **filenames = NULL;
4997
3.20k
    int             fname_len, i, filename_count = 0, array_size = 0;
4998
3.20k
    char           *tmpstr;
4999
5000
3.20k
    *result = NULL;
5001
5002
3.20k
    dir = opendir(dirname);
5003
3.20k
    if (!dir)
5004
8
        return -1;
5005
5006
29.9k
    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
26.7k
        fname_len = strlen(file->d_name);
5013
26.7k
        if (fname_len > 0 && file->d_name[0] != '.'
5014
26.7k
            && file->d_name[0] != '#'
5015
26.7k
            && file->d_name[fname_len-1] != '#'
5016
26.7k
            && file->d_name[fname_len-1] != '~') {
5017
20.3k
            if (asprintf(&tmpstr, "%s/%s", dirname, file->d_name) < 0)
5018
0
                continue;
5019
20.3k
            dir2 = opendir(tmpstr);
5020
20.3k
            if (dir2) {
5021
                /* file is a directory, don't read it */
5022
0
                closedir(dir2);
5023
20.3k
            } else {
5024
20.3k
                if (filename_count >= array_size) {
5025
3.20k
                    char **new_filenames;
5026
5027
3.20k
                    array_size = (array_size + 16) * 2;
5028
3.20k
                    new_filenames = realloc(filenames,
5029
3.20k
                                        array_size * sizeof(filenames[0]));
5030
3.20k
                    if (!new_filenames) {
5031
0
                        free(tmpstr);
5032
0
                        for (i = 0; i < filename_count; i++)
5033
0
                            free(filenames[i]);
5034
0
                        free(filenames);
5035
0
                        closedir(dir);
5036
0
                        return -1;
5037
0
                    }
5038
3.20k
                    filenames = new_filenames;
5039
3.20k
                }
5040
20.3k
                filenames[filename_count++] = tmpstr;
5041
20.3k
                tmpstr = NULL;
5042
20.3k
            }
5043
20.3k
            free(tmpstr);
5044
20.3k
        }
5045
26.7k
    }
5046
3.20k
    closedir(dir);
5047
5048
3.20k
    if (filenames)
5049
3.20k
        qsort(filenames, filename_count, sizeof(filenames[0]), elemcmp);
5050
3.20k
    *result = filenames;
5051
5052
3.20k
    return filename_count;
5053
3.20k
}
5054
5055
/* For Win32 platforms, the directory does not maintain a last modification
5056
 * date that we can compare with the modification date of the .index file.
5057
 * Therefore there is no way to know whether any .index file is valid.
5058
 * This is the reason for the #if !(defined(WIN32) || defined(cygwin))
5059
 * in the add_mibdir function
5060
 */
5061
int
5062
add_mibdir(const char *dirname)
5063
3.20k
{
5064
3.20k
    const char     *oldFile = File;
5065
3.20k
    char          **filenames;
5066
3.20k
    int             count = 0;
5067
3.20k
    int             filename_count, i;
5068
5069
3.20k
    DEBUGMSGTL(("parse-mibs", "Scanning directory %s\n", dirname));
5070
5071
3.20k
    filename_count = scan_directory(&filenames, dirname);
5072
5073
3.20k
    if (filename_count >= 0) {
5074
23.5k
        for (i = 0; i < filename_count; i++) {
5075
20.3k
            if (add_mibfile(filenames[i], strrchr(filenames[i], '/')) == 0)
5076
2.25k
                count++;
5077
20.3k
      free(filenames[i]);
5078
20.3k
        }
5079
3.20k
        File = oldFile;
5080
3.20k
        free(filenames);
5081
3.20k
        return (count);
5082
3.20k
    }
5083
8
    else
5084
8
        DEBUGMSGTL(("parse-mibs","cannot open MIB directory %s\n", dirname));
5085
5086
8
    return (-1);
5087
3.20k
}
5088
5089
5090
/*
5091
 * Returns the root of the whole tree
5092
 *   (for backwards compatability)
5093
 */
5094
struct tree    *
5095
read_mib(const char *filename)
5096
8.65k
{
5097
8.65k
    FILE           *fp;
5098
8.65k
    char            token[MAXTOKEN];
5099
5100
8.65k
    fp = fopen(filename, "r");
5101
8.65k
    if (fp == NULL) {
5102
303
        snmp_log_perror(filename);
5103
303
        return NULL;
5104
303
    }
5105
8.35k
    mibLine = 1;
5106
8.35k
    File = filename;
5107
8.35k
    DEBUGMSGTL(("parse-mibs", "Parsing file: %s...\n", filename));
5108
8.35k
    if (get_token(fp, token, MAXTOKEN) != LABEL) {
5109
494
      snmp_log(LOG_ERR, "Failed to parse MIB file %s\n", filename);
5110
494
      fclose(fp);
5111
494
      return NULL;
5112
494
    }
5113
7.85k
    fclose(fp);
5114
7.85k
    new_module(token, filename);
5115
7.85k
    (void) netsnmp_read_module(token);
5116
5117
7.85k
    return tree_head;
5118
8.35k
}
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
250k
{
5176
250k
    register int    ch;
5177
250k
    int             count = 0;
5178
250k
    int             too_long = 0;
5179
250k
    char           *token_start = token;
5180
5181
7.80M
    for (ch = netsnmp_getc(fp); ch != EOF; ch = netsnmp_getc(fp)) {
5182
7.80M
        if (ch == '\r')
5183
2.67k
            continue;
5184
7.80M
        if (ch == '\n') {
5185
112k
            mibLine++;
5186
7.68M
        } else if (ch == '"') {
5187
250k
            netsnmp_assert(token - token_start < maxtlen);
5188
250k
            *token = '\0';
5189
250k
            if (too_long && netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
5190
1.76k
             NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
5191
                /*
5192
                 * show short form for brevity sake 
5193
                 */
5194
4
                int             truncate_at = SNMP_MIN(50, maxtlen - 1);
5195
4
                char            ch_save = *(token_start + truncate_at);
5196
5197
4
                *(token_start + truncate_at) = '\0';
5198
4
                print_error("Warning: string too long",
5199
4
                            token_start, QUOTESTRING);
5200
4
                *(token_start + truncate_at) = ch_save;
5201
4
            }
5202
250k
            return QUOTESTRING;
5203
250k
        }
5204
        /*
5205
         * maximum description length check.  If greater, keep parsing
5206
         * but truncate the string 
5207
         */
5208
7.55M
        if (++count < maxtlen)
5209
6.39M
            *token++ = ch;
5210
1.15M
        else
5211
1.15M
            too_long = 1;
5212
7.55M
    }
5213
5214
549
    return 0;
5215
250k
}
5216
5217
/*
5218
 * struct index_list *
5219
 * getIndexes(FILE *fp):
5220
 *   This routine parses a string like  { blah blah blah } and returns a
5221
 *   list of the strings enclosed within it.
5222
 *
5223
 */
5224
static struct index_list *
5225
getIndexes(FILE * fp, struct index_list **retp)
5226
3.58k
{
5227
3.58k
    int             type;
5228
3.58k
    char            token[MAXTOKEN];
5229
3.58k
    char            nextIsImplied = 0;
5230
5231
3.58k
    struct index_list *mylist = NULL;
5232
3.58k
    struct index_list **mypp = &mylist;
5233
5234
3.58k
    free_indexes(retp);
5235
5236
3.58k
    type = get_token(fp, token, MAXTOKEN);
5237
5238
3.58k
    if (type != LEFTBRACKET) {
5239
8
        return NULL;
5240
8
    }
5241
5242
3.57k
    type = get_token(fp, token, MAXTOKEN);
5243
159k
    while (type != RIGHTBRACKET && type != ENDOFFILE) {
5244
155k
        if ((type == LABEL) || (type & SYNTAX_MASK)) {
5245
137k
            *mypp = calloc(1, sizeof(struct index_list));
5246
137k
            if (*mypp) {
5247
137k
                (*mypp)->ilabel = strdup(token);
5248
137k
                (*mypp)->isimplied = nextIsImplied;
5249
137k
                mypp = &(*mypp)->next;
5250
137k
                nextIsImplied = 0;
5251
137k
            }
5252
137k
        } else if (type == IMPLIED) {
5253
532
            nextIsImplied = 1;
5254
532
        }
5255
155k
        type = get_token(fp, token, MAXTOKEN);
5256
155k
    }
5257
5258
3.57k
    *retp = mylist;
5259
3.57k
    return mylist;
5260
3.58k
}
5261
5262
static struct varbind_list *
5263
getVarbinds(FILE * fp, struct varbind_list **retp)
5264
2.62k
{
5265
2.62k
    int             type;
5266
2.62k
    char            token[MAXTOKEN];
5267
5268
2.62k
    struct varbind_list *mylist = NULL;
5269
2.62k
    struct varbind_list **mypp = &mylist;
5270
5271
2.62k
    free_varbinds(retp);
5272
5273
2.62k
    type = get_token(fp, token, MAXTOKEN);
5274
5275
2.62k
    if (type != LEFTBRACKET) {
5276
23
        return NULL;
5277
23
    }
5278
5279
2.60k
    type = get_token(fp, token, MAXTOKEN);
5280
480k
    while (type != RIGHTBRACKET && type != ENDOFFILE) {
5281
477k
        if ((type == LABEL) || (type & SYNTAX_MASK)) {
5282
444k
            *mypp = calloc(1, sizeof(struct varbind_list));
5283
444k
            if (*mypp) {
5284
444k
                (*mypp)->vblabel = strdup(token);
5285
444k
                mypp = &(*mypp)->next;
5286
444k
            }
5287
444k
        }
5288
477k
        type = get_token(fp, token, MAXTOKEN);
5289
477k
    }
5290
5291
2.60k
    *retp = mylist;
5292
2.60k
    return mylist;
5293
2.62k
}
5294
5295
static void
5296
free_indexes(struct index_list **spp)
5297
403k
{
5298
403k
    if (spp && *spp) {
5299
3.30k
        struct index_list *pp, *npp;
5300
5301
3.30k
        pp = *spp;
5302
3.30k
        *spp = NULL;
5303
5304
129k
        while (pp) {
5305
126k
            npp = pp->next;
5306
126k
            if (pp->ilabel)
5307
126k
                free(pp->ilabel);
5308
126k
            free(pp);
5309
126k
            pp = npp;
5310
126k
        }
5311
3.30k
    }
5312
403k
}
5313
5314
static void
5315
free_varbinds(struct varbind_list **spp)
5316
402k
{
5317
402k
    if (spp && *spp) {
5318
2.32k
        struct varbind_list *pp, *npp;
5319
5320
2.32k
        pp = *spp;
5321
2.32k
        *spp = NULL;
5322
5323
332k
        while (pp) {
5324
330k
            npp = pp->next;
5325
330k
            if (pp->vblabel)
5326
330k
                free(pp->vblabel);
5327
330k
            free(pp);
5328
330k
            pp = npp;
5329
330k
        }
5330
2.32k
    }
5331
402k
}
5332
5333
static void
5334
free_ranges(struct range_list **spp)
5335
405k
{
5336
405k
    if (spp && *spp) {
5337
3.55k
        struct range_list *pp, *npp;
5338
5339
3.55k
        pp = *spp;
5340
3.55k
        *spp = NULL;
5341
5342
8.44k
        while (pp) {
5343
4.89k
            npp = pp->next;
5344
4.89k
            free(pp);
5345
4.89k
            pp = npp;
5346
4.89k
        }
5347
3.55k
    }
5348
405k
}
5349
5350
static void
5351
free_enums(struct enum_list **spp)
5352
409k
{
5353
409k
    if (spp && *spp) {
5354
2.39k
        struct enum_list *pp, *npp;
5355
5356
2.39k
        pp = *spp;
5357
2.39k
        *spp = NULL;
5358
5359
9.98k
        while (pp) {
5360
7.58k
            npp = pp->next;
5361
7.58k
            if (pp->label)
5362
7.58k
                free(pp->label);
5363
7.58k
            free(pp);
5364
7.58k
            pp = npp;
5365
7.58k
        }
5366
2.39k
    }
5367
409k
}
5368
5369
static struct enum_list *
5370
copy_enums(struct enum_list *sp)
5371
506
{
5372
506
    struct enum_list *xp = NULL, **spp = &xp;
5373
5374
1.28k
    while (sp) {
5375
781
        *spp = calloc(1, sizeof(struct enum_list));
5376
781
        if (!*spp)
5377
0
            break;
5378
781
        (*spp)->label = strdup(sp->label);
5379
781
        (*spp)->value = sp->value;
5380
781
        spp = &(*spp)->next;
5381
781
        sp = sp->next;
5382
781
    }
5383
506
    return (xp);
5384
506
}
5385
5386
static struct range_list *
5387
copy_ranges(struct range_list *sp)
5388
506
{
5389
506
    struct range_list *xp = NULL, **spp = &xp;
5390
5391
1.10k
    while (sp) {
5392
594
        *spp = calloc(1, sizeof(struct range_list));
5393
594
        if (!*spp)
5394
0
            break;
5395
594
        (*spp)->low = sp->low;
5396
594
        (*spp)->high = sp->high;
5397
594
        spp = &(*spp)->next;
5398
594
        sp = sp->next;
5399
594
    }
5400
506
    return (xp);
5401
506
}
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.15M
    while ((type != RIGHTBRACKET || bracketcount > 0) && type != ENDOFFILE) {
5419
1.15M
        type = get_token(fp, token, MAXTOKEN);
5420
1.15M
        if (type == LEFTBRACKET)
5421
1.13M
            bracketcount++;
5422
20.8k
        else if (type == RIGHTBRACKET)
5423
381
            bracketcount--;
5424
1.15M
    }
5425
5426
41
    if (type == RIGHTBRACKET)
5427
10
        return OBJID;
5428
31
    else
5429
31
        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
46.7k
{
5695
46.7k
    struct node    *nnp;
5696
    /*
5697
     * printf("merge defval --> %s\n",np->defaultValue); 
5698
     */
5699
46.7k
    nnp = parse_objectid(fp, name);
5700
46.7k
    if (nnp) {
5701
5702
        /*
5703
         * apply last OID sub-identifier data to the information 
5704
         */
5705
        /*
5706
         * already collected for this node. 
5707
         */
5708
45.1k
        struct node    *headp, *nextp;
5709
45.1k
        int             ncount = 0;
5710
45.1k
        nextp = headp = nnp;
5711
135k
        while (nnp->next) {
5712
89.9k
            nextp = nnp;
5713
89.9k
            ncount++;
5714
89.9k
            nnp = nnp->next;
5715
89.9k
        }
5716
5717
45.1k
        np->label = nnp->label;
5718
45.1k
        np->subid = nnp->subid;
5719
45.1k
        np->modid = nnp->modid;
5720
45.1k
        np->parent = nnp->parent;
5721
45.1k
  if (nnp->filename != NULL) {
5722
45.1k
    free(nnp->filename);
5723
45.1k
  }
5724
45.1k
        free(nnp);
5725
5726
45.1k
        if (ncount) {
5727
16.9k
            nextp->next = np;
5728
16.9k
            np = headp;
5729
16.9k
        }
5730
45.1k
    } else {
5731
1.58k
        free_node(np);
5732
1.58k
        np = NULL;
5733
1.58k
    }
5734
5735
46.7k
    return np;
5736
46.7k
}
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
106k
{
5752
106k
    free_partial_tree(tp, FALSE);
5753
5754
106k
    tp->label = np->label;
5755
106k
    np->label = NULL;
5756
106k
    tp->enums = np->enums;
5757
106k
    np->enums = NULL;
5758
106k
    tp->ranges = np->ranges;
5759
106k
    np->ranges = NULL;
5760
106k
    tp->indexes = np->indexes;
5761
106k
    np->indexes = NULL;
5762
106k
    tp->augments = np->augments;
5763
106k
    np->augments = NULL;
5764
106k
    tp->varbinds = np->varbinds;
5765
106k
    np->varbinds = NULL;
5766
106k
    tp->hint = np->hint;
5767
106k
    np->hint = NULL;
5768
106k
    tp->units = np->units;
5769
106k
    np->units = NULL;
5770
106k
    tp->description = np->description;
5771
106k
    np->description = NULL;
5772
106k
    tp->reference = np->reference;
5773
106k
    np->reference = NULL;
5774
106k
    tp->defaultValue = np->defaultValue;
5775
106k
    np->defaultValue = NULL;
5776
106k
    tp->subid = np->subid;
5777
106k
    tp->tc_index = np->tc_index;
5778
106k
    tp->type = translation_table[np->type];
5779
106k
    tp->access = np->access;
5780
106k
    tp->status = np->status;
5781
5782
106k
    set_function(tp);
5783
106k
}
5784
5785
#endif /* NETSNMP_DISABLE_MIB_LOADING */