Coverage Report

Created: 2025-05-08 06:18

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