Coverage Report

Created: 2026-01-21 06:21

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