Coverage Report

Created: 2023-06-07 06:43

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