00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <net-snmp/net-snmp-config.h>
00036
00037 #ifndef NETSNMP_DISABLE_MIB_LOADING
00038
00039 #if HAVE_LIMITS_H
00040 #include <limits.h>
00041 #endif
00042 #include <stdio.h>
00043 #if HAVE_STDLIB_H
00044 #include <stdlib.h>
00045 #endif
00046 #if HAVE_STRING_H
00047 #include <string.h>
00048 #else
00049 #include <strings.h>
00050 #endif
00051 #include <ctype.h>
00052 #include <sys/types.h>
00053 #if HAVE_SYS_STAT_H
00054 #include <sys/stat.h>
00055 #endif
00056
00057
00058
00059
00060 #if HAVE_DIRENT_H
00061 # include <dirent.h>
00062 # define NAMLEN(dirent) strlen((dirent)->d_name)
00063 #else
00064 # define dirent direct
00065 # define NAMLEN(dirent) (dirent)->d_namlen
00066 # if HAVE_SYS_NDIR_H
00067 # include <sys/ndir.h>
00068 # endif
00069 # if HAVE_SYS_DIR_H
00070 # include <sys/dir.h>
00071 # endif
00072 # if HAVE_NDIR_H
00073 # include <ndir.h>
00074 # endif
00075 #endif
00076 #if TIME_WITH_SYS_TIME
00077 # ifdef WIN32
00078 # include <sys/timeb.h>
00079 # else
00080 # include <sys/time.h>
00081 # endif
00082 # include <time.h>
00083 #else
00084 # if HAVE_SYS_TIME_H
00085 # include <sys/time.h>
00086 # else
00087 # include <time.h>
00088 # endif
00089 #endif
00090 #if HAVE_WINSOCK_H
00091 #include <winsock.h>
00092 #endif
00093 #if HAVE_NETINET_IN_H
00094 #include <netinet/in.h>
00095 #endif
00096 #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
00097 #include <regex.h>
00098 #endif
00099 #if HAVE_DMALLOC_H
00100 #include <dmalloc.h>
00101 #endif
00102
00103 #include <errno.h>
00104
00105 #include <net-snmp/types.h>
00106 #include <net-snmp/output_api.h>
00107 #include <net-snmp/config_api.h>
00108 #include <net-snmp/utilities.h>
00109
00110 #include <net-snmp/library/parse.h>
00111 #include <net-snmp/library/mib.h>
00112 #include <net-snmp/library/snmp_api.h>
00113
00114
00115
00116
00117
00118
00119 struct subid_s {
00120 int subid;
00121 int modid;
00122 char *label;
00123 };
00124
00125 #define MAXTC 4096
00126 struct tc {
00127 int type;
00128 int modid;
00129 char *descriptor;
00130 char *hint;
00131 struct enum_list *enums;
00132 struct range_list *ranges;
00133 char *description;
00134 } tclist[MAXTC];
00135
00136 int mibLine = 0;
00137 const char *File = "(none)";
00138 static int anonymous = 0;
00139
00140 struct objgroup {
00141 char *name;
00142 int line;
00143 struct objgroup *next;
00144 } *objgroups = NULL, *objects = NULL, *notifs = NULL;
00145
00146 #define SYNTAX_MASK 0x80
00147
00148
00149
00150
00151 #define CONTINUE -1
00152 #define ENDOFFILE 0
00153 #define LABEL 1
00154 #define SUBTREE 2
00155 #define SYNTAX 3
00156 #define OBJID (4 | SYNTAX_MASK)
00157 #define OCTETSTR (5 | SYNTAX_MASK)
00158 #define INTEGER (6 | SYNTAX_MASK)
00159 #define NETADDR (7 | SYNTAX_MASK)
00160 #define IPADDR (8 | SYNTAX_MASK)
00161 #define COUNTER (9 | SYNTAX_MASK)
00162 #define GAUGE (10 | SYNTAX_MASK)
00163 #define TIMETICKS (11 | SYNTAX_MASK)
00164 #define KW_OPAQUE (12 | SYNTAX_MASK)
00165 #define NUL (13 | SYNTAX_MASK)
00166 #define SEQUENCE 14
00167 #define OF 15
00168 #define OBJTYPE 16
00169 #define ACCESS 17
00170 #define READONLY 18
00171 #define READWRITE 19
00172 #define WRITEONLY 20
00173 #ifdef NOACCESS
00174 #undef NOACCESS
00175 #endif
00176 #define NOACCESS 21
00177 #define STATUS 22
00178 #define MANDATORY 23
00179 #define KW_OPTIONAL 24
00180 #define OBSOLETE 25
00181
00182
00183
00184 #define PUNCT 27
00185 #define EQUALS 28
00186 #define NUMBER 29
00187 #define LEFTBRACKET 30
00188 #define RIGHTBRACKET 31
00189 #define LEFTPAREN 32
00190 #define RIGHTPAREN 33
00191 #define COMMA 34
00192 #define DESCRIPTION 35
00193 #define QUOTESTRING 36
00194 #define INDEX 37
00195 #define DEFVAL 38
00196 #define DEPRECATED 39
00197 #define SIZE 40
00198 #define BITSTRING (41 | SYNTAX_MASK)
00199 #define NSAPADDRESS (42 | SYNTAX_MASK)
00200 #define COUNTER64 (43 | SYNTAX_MASK)
00201 #define OBJGROUP 44
00202 #define NOTIFTYPE 45
00203 #define AUGMENTS 46
00204 #define COMPLIANCE 47
00205 #define READCREATE 48
00206 #define UNITS 49
00207 #define REFERENCE 50
00208 #define NUM_ENTRIES 51
00209 #define MODULEIDENTITY 52
00210 #define LASTUPDATED 53
00211 #define ORGANIZATION 54
00212 #define CONTACTINFO 55
00213 #define UINTEGER32 (56 | SYNTAX_MASK)
00214 #define CURRENT 57
00215 #define DEFINITIONS 58
00216 #define END 59
00217 #define SEMI 60
00218 #define TRAPTYPE 61
00219 #define ENTERPRISE 62
00220
00221
00222
00223 #define BEGIN 64
00224 #define IMPORTS 65
00225 #define EXPORTS 66
00226 #define ACCNOTIFY 67
00227 #define BAR 68
00228 #define RANGE 69
00229 #define CONVENTION 70
00230 #define DISPLAYHINT 71
00231 #define FROM 72
00232 #define AGENTCAP 73
00233 #define MACRO 74
00234 #define IMPLIED 75
00235 #define SUPPORTS 76
00236 #define INCLUDES 77
00237 #define VARIATION 78
00238 #define REVISION 79
00239 #define NOTIMPL 80
00240 #define OBJECTS 81
00241 #define NOTIFICATIONS 82
00242 #define MODULE 83
00243 #define MINACCESS 84
00244 #define PRODREL 85
00245 #define WRSYNTAX 86
00246 #define CREATEREQ 87
00247 #define NOTIFGROUP 88
00248 #define MANDATORYGROUPS 89
00249 #define GROUP 90
00250 #define OBJECT 91
00251 #define IDENTIFIER 92
00252 #define CHOICE 93
00253 #define LEFTSQBRACK 95
00254 #define RIGHTSQBRACK 96
00255 #define IMPLICIT 97
00256 #define APPSYNTAX (98 | SYNTAX_MASK)
00257 #define OBJSYNTAX (99 | SYNTAX_MASK)
00258 #define SIMPLESYNTAX (100 | SYNTAX_MASK)
00259 #define OBJNAME (101 | SYNTAX_MASK)
00260 #define NOTIFNAME (102 | SYNTAX_MASK)
00261 #define VARIABLES 103
00262 #define UNSIGNED32 (104 | SYNTAX_MASK)
00263 #define INTEGER32 (105 | SYNTAX_MASK)
00264 #define OBJIDENTITY 106
00265
00266
00267
00268
00269 struct tok {
00270 const char *name;
00271 int len;
00272 int token;
00273 int hash;
00274 struct tok *next;
00275 };
00276
00277
00278 static struct tok tokens[] = {
00279 {"obsolete", sizeof("obsolete") - 1, OBSOLETE}
00280 ,
00281 {"Opaque", sizeof("Opaque") - 1, KW_OPAQUE}
00282 ,
00283 {"optional", sizeof("optional") - 1, KW_OPTIONAL}
00284 ,
00285 {"LAST-UPDATED", sizeof("LAST-UPDATED") - 1, LASTUPDATED}
00286 ,
00287 {"ORGANIZATION", sizeof("ORGANIZATION") - 1, ORGANIZATION}
00288 ,
00289 {"CONTACT-INFO", sizeof("CONTACT-INFO") - 1, CONTACTINFO}
00290 ,
00291 {"MODULE-IDENTITY", sizeof("MODULE-IDENTITY") - 1, MODULEIDENTITY}
00292 ,
00293 {"MODULE-COMPLIANCE", sizeof("MODULE-COMPLIANCE") - 1, COMPLIANCE}
00294 ,
00295 {"DEFINITIONS", sizeof("DEFINITIONS") - 1, DEFINITIONS}
00296 ,
00297 {"END", sizeof("END") - 1, END}
00298 ,
00299 {"AUGMENTS", sizeof("AUGMENTS") - 1, AUGMENTS}
00300 ,
00301 {"not-accessible", sizeof("not-accessible") - 1, NOACCESS}
00302 ,
00303 {"write-only", sizeof("write-only") - 1, WRITEONLY}
00304 ,
00305 {"NsapAddress", sizeof("NsapAddress") - 1, NSAPADDRESS}
00306 ,
00307 {"UNITS", sizeof("Units") - 1, UNITS}
00308 ,
00309 {"REFERENCE", sizeof("REFERENCE") - 1, REFERENCE}
00310 ,
00311 {"NUM-ENTRIES", sizeof("NUM-ENTRIES") - 1, NUM_ENTRIES}
00312 ,
00313 {"BITSTRING", sizeof("BITSTRING") - 1, BITSTRING}
00314 ,
00315 {"BIT", sizeof("BIT") - 1, CONTINUE}
00316 ,
00317 {"BITS", sizeof("BITS") - 1, BITSTRING}
00318 ,
00319 {"Counter64", sizeof("Counter64") - 1, COUNTER64}
00320 ,
00321 {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS}
00322 ,
00323 {"NOTIFICATION-TYPE", sizeof("NOTIFICATION-TYPE") - 1, NOTIFTYPE}
00324 ,
00325 {"OBJECT-GROUP", sizeof("OBJECT-GROUP") - 1, OBJGROUP}
00326 ,
00327 {"OBJECT-IDENTITY", sizeof("OBJECT-IDENTITY") - 1, OBJIDENTITY}
00328 ,
00329 {"IDENTIFIER", sizeof("IDENTIFIER") - 1, IDENTIFIER}
00330 ,
00331 {"OBJECT", sizeof("OBJECT") - 1, OBJECT}
00332 ,
00333 {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR}
00334 ,
00335 {"Gauge", sizeof("Gauge") - 1, GAUGE}
00336 ,
00337 {"Gauge32", sizeof("Gauge32") - 1, GAUGE}
00338 ,
00339 {"Unsigned32", sizeof("Unsigned32") - 1, UNSIGNED32}
00340 ,
00341 {"read-write", sizeof("read-write") - 1, READWRITE}
00342 ,
00343 {"read-create", sizeof("read-create") - 1, READCREATE}
00344 ,
00345 {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR}
00346 ,
00347 {"OCTET", sizeof("OCTET") - 1, CONTINUE}
00348 ,
00349 {"OF", sizeof("OF") - 1, OF}
00350 ,
00351 {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE}
00352 ,
00353 {"NULL", sizeof("NULL") - 1, NUL}
00354 ,
00355 {"IpAddress", sizeof("IpAddress") - 1, IPADDR}
00356 ,
00357 {"UInteger32", sizeof("UInteger32") - 1, UINTEGER32}
00358 ,
00359 {"INTEGER", sizeof("INTEGER") - 1, INTEGER}
00360 ,
00361 {"Integer32", sizeof("Integer32") - 1, INTEGER32}
00362 ,
00363 {"Counter", sizeof("Counter") - 1, COUNTER}
00364 ,
00365 {"Counter32", sizeof("Counter32") - 1, COUNTER}
00366 ,
00367 {"read-only", sizeof("read-only") - 1, READONLY}
00368 ,
00369 {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION}
00370 ,
00371 {"INDEX", sizeof("INDEX") - 1, INDEX}
00372 ,
00373 {"DEFVAL", sizeof("DEFVAL") - 1, DEFVAL}
00374 ,
00375 {"deprecated", sizeof("deprecated") - 1, DEPRECATED}
00376 ,
00377 {"SIZE", sizeof("SIZE") - 1, SIZE}
00378 ,
00379 {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS}
00380 ,
00381 {"ACCESS", sizeof("ACCESS") - 1, ACCESS}
00382 ,
00383 {"mandatory", sizeof("mandatory") - 1, MANDATORY}
00384 ,
00385 {"current", sizeof("current") - 1, CURRENT}
00386 ,
00387 {"STATUS", sizeof("STATUS") - 1, STATUS}
00388 ,
00389 {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX}
00390 ,
00391 {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE}
00392 ,
00393 {"TRAP-TYPE", sizeof("TRAP-TYPE") - 1, TRAPTYPE}
00394 ,
00395 {"ENTERPRISE", sizeof("ENTERPRISE") - 1, ENTERPRISE}
00396 ,
00397 {"BEGIN", sizeof("BEGIN") - 1, BEGIN}
00398 ,
00399 {"IMPORTS", sizeof("IMPORTS") - 1, IMPORTS}
00400 ,
00401 {"EXPORTS", sizeof("EXPORTS") - 1, EXPORTS}
00402 ,
00403 {"accessible-for-notify", sizeof("accessible-for-notify") - 1,
00404 ACCNOTIFY}
00405 ,
00406 {"TEXTUAL-CONVENTION", sizeof("TEXTUAL-CONVENTION") - 1, CONVENTION}
00407 ,
00408 {"NOTIFICATION-GROUP", sizeof("NOTIFICATION-GROUP") - 1, NOTIFGROUP}
00409 ,
00410 {"DISPLAY-HINT", sizeof("DISPLAY-HINT") - 1, DISPLAYHINT}
00411 ,
00412 {"FROM", sizeof("FROM") - 1, FROM}
00413 ,
00414 {"AGENT-CAPABILITIES", sizeof("AGENT-CAPABILITIES") - 1, AGENTCAP}
00415 ,
00416 {"MACRO", sizeof("MACRO") - 1, MACRO}
00417 ,
00418 {"IMPLIED", sizeof("IMPLIED") - 1, IMPLIED}
00419 ,
00420 {"SUPPORTS", sizeof("SUPPORTS") - 1, SUPPORTS}
00421 ,
00422 {"INCLUDES", sizeof("INCLUDES") - 1, INCLUDES}
00423 ,
00424 {"VARIATION", sizeof("VARIATION") - 1, VARIATION}
00425 ,
00426 {"REVISION", sizeof("REVISION") - 1, REVISION}
00427 ,
00428 {"not-implemented", sizeof("not-implemented") - 1, NOTIMPL}
00429 ,
00430 {"OBJECTS", sizeof("OBJECTS") - 1, OBJECTS}
00431 ,
00432 {"NOTIFICATIONS", sizeof("NOTIFICATIONS") - 1, NOTIFICATIONS}
00433 ,
00434 {"MODULE", sizeof("MODULE") - 1, MODULE}
00435 ,
00436 {"MIN-ACCESS", sizeof("MIN-ACCESS") - 1, MINACCESS}
00437 ,
00438 {"PRODUCT-RELEASE", sizeof("PRODUCT-RELEASE") - 1, PRODREL}
00439 ,
00440 {"WRITE-SYNTAX", sizeof("WRITE-SYNTAX") - 1, WRSYNTAX}
00441 ,
00442 {"CREATION-REQUIRES", sizeof("CREATION-REQUIRES") - 1, CREATEREQ}
00443 ,
00444 {"MANDATORY-GROUPS", sizeof("MANDATORY-GROUPS") - 1, MANDATORYGROUPS}
00445 ,
00446 {"GROUP", sizeof("GROUP") - 1, GROUP}
00447 ,
00448 {"CHOICE", sizeof("CHOICE") - 1, CHOICE}
00449 ,
00450 {"IMPLICIT", sizeof("IMPLICIT") - 1, IMPLICIT}
00451 ,
00452 {"ObjectSyntax", sizeof("ObjectSyntax") - 1, OBJSYNTAX}
00453 ,
00454 {"SimpleSyntax", sizeof("SimpleSyntax") - 1, SIMPLESYNTAX}
00455 ,
00456 {"ApplicationSyntax", sizeof("ApplicationSyntax") - 1, APPSYNTAX}
00457 ,
00458 {"ObjectName", sizeof("ObjectName") - 1, OBJNAME}
00459 ,
00460 {"NotificationName", sizeof("NotificationName") - 1, NOTIFNAME}
00461 ,
00462 {"VARIABLES", sizeof("VARIABLES") - 1, VARIABLES}
00463 ,
00464 {NULL}
00465 };
00466
00467 static struct module_compatability *module_map_head;
00468 static struct module_compatability module_map[] = {
00469 {"RFC1065-SMI", "RFC1155-SMI", NULL, 0},
00470 {"RFC1066-MIB", "RFC1156-MIB", NULL, 0},
00471
00472
00473
00474 {"RFC1156-MIB", "RFC1158-MIB", NULL, 0},
00475
00476
00477
00478 {"RFC1158-MIB", "RFC1213-MIB", NULL, 0},
00479
00480
00481
00482 {"RFC1155-SMI", "SNMPv2-SMI", NULL, 0},
00483 {"RFC1213-MIB", "SNMPv2-SMI", "mib-2", 0},
00484 {"RFC1213-MIB", "SNMPv2-MIB", "sys", 3},
00485 {"RFC1213-MIB", "IF-MIB", "if", 2},
00486 {"RFC1213-MIB", "IP-MIB", "ip", 2},
00487 {"RFC1213-MIB", "IP-MIB", "icmp", 4},
00488 {"RFC1213-MIB", "TCP-MIB", "tcp", 3},
00489 {"RFC1213-MIB", "UDP-MIB", "udp", 3},
00490 {"RFC1213-MIB", "SNMPv2-SMI", "transmission", 0},
00491 {"RFC1213-MIB", "SNMPv2-MIB", "snmp", 4},
00492 {"RFC1231-MIB", "TOKENRING-MIB", NULL, 0},
00493 {"RFC1271-MIB", "RMON-MIB", NULL, 0},
00494 {"RFC1286-MIB", "SOURCE-ROUTING-MIB", "dot1dSr", 7},
00495 {"RFC1286-MIB", "BRIDGE-MIB", NULL, 0},
00496 {"RFC1315-MIB", "FRAME-RELAY-DTE-MIB", NULL, 0},
00497 {"RFC1316-MIB", "CHARACTER-MIB", NULL, 0},
00498 {"RFC1406-MIB", "DS1-MIB", NULL, 0},
00499 {"RFC-1213", "RFC1213-MIB", NULL, 0},
00500 };
00501
00502 #define MODULE_NOT_FOUND 0
00503 #define MODULE_LOADED_OK 1
00504 #define MODULE_ALREADY_LOADED 2
00505
00506
00507
00508 #define MODULE_LOAD_FAILED MODULE_NOT_FOUND
00509
00510
00511 #define HASHSIZE 32
00512 #define BUCKET(x) (x & (HASHSIZE-1))
00513
00514 #define NHASHSIZE 128
00515 #define NBUCKET(x) (x & (NHASHSIZE-1))
00516
00517 static struct tok *buckets[HASHSIZE];
00518
00519 static struct node *nbuckets[NHASHSIZE];
00520 static struct tree *tbuckets[NHASHSIZE];
00521 static struct module *module_head = NULL;
00522
00523 struct node *orphan_nodes = NULL;
00524 struct tree *tree_head = NULL;
00525
00526 #define NUMBER_OF_ROOT_NODES 3
00527 static struct module_import root_imports[NUMBER_OF_ROOT_NODES];
00528
00529 static int current_module = 0;
00530 static int max_module = 0;
00531 static char *last_err_module = 0;
00532
00533 static void tree_from_node(struct tree *tp, struct node *np);
00534 static void do_subtree(struct tree *, struct node **);
00535 static void do_linkup(struct module *, struct node *);
00536 static void dump_module_list(void);
00537 static int get_token(FILE *, char *, int);
00538 static int parseQuoteString(FILE *, char *, int);
00539 static int tossObjectIdentifier(FILE *);
00540 static int name_hash(const char *);
00541 static void init_node_hash(struct node *);
00542 static void print_error(const char *, const char *, int);
00543 static void free_tree(struct tree *);
00544 static void free_partial_tree(struct tree *, int);
00545 static void free_node(struct node *);
00546 static void build_translation_table(void);
00547 static void init_tree_roots(void);
00548 static void merge_anon_children(struct tree *, struct tree *);
00549 static void unlink_tbucket(struct tree *);
00550 static void unlink_tree(struct tree *);
00551 static int getoid(FILE *, struct subid_s *, int);
00552 static struct node *parse_objectid(FILE *, char *);
00553 static int get_tc(const char *, int, int *, struct enum_list **,
00554 struct range_list **, char **);
00555 static int get_tc_index(const char *, int);
00556 static struct enum_list *parse_enumlist(FILE *, struct enum_list **);
00557 static struct range_list *parse_ranges(FILE * fp, struct range_list **);
00558 static struct node *parse_asntype(FILE *, char *, int *, char *);
00559 static struct node *parse_objecttype(FILE *, char *);
00560 static struct node *parse_objectgroup(FILE *, char *, int,
00561 struct objgroup **);
00562 static struct node *parse_notificationDefinition(FILE *, char *);
00563 static struct node *parse_trapDefinition(FILE *, char *);
00564 static struct node *parse_compliance(FILE *, char *);
00565 static struct node *parse_capabilities(FILE *, char *);
00566 static struct node *parse_moduleIdentity(FILE *, char *);
00567 static struct node *parse_macro(FILE *, char *);
00568 static void parse_imports(FILE *);
00569 static struct node *parse(FILE *, struct node *);
00570
00571 static int read_module_internal(const char *);
00572 static int read_module_replacements(const char *);
00573 static int read_import_replacements(const char *,
00574 struct module_import *);
00575
00576 static void new_module(const char *, const char *);
00577
00578 static struct node *merge_parse_objectid(struct node *, FILE *, char *);
00579 static struct index_list *getIndexes(FILE * fp, struct index_list **);
00580 static struct varbind_list *getVarbinds(FILE * fp, struct varbind_list **);
00581 static void free_indexes(struct index_list **);
00582 static void free_varbinds(struct varbind_list **);
00583 static void free_ranges(struct range_list **);
00584 static void free_enums(struct enum_list **);
00585 static struct range_list *copy_ranges(struct range_list *);
00586 static struct enum_list *copy_enums(struct enum_list *);
00587
00588 static u_int compute_match(const char *search_base, const char *key);
00589
00590 void
00591 snmp_mib_toggle_options_usage(const char *lead, FILE * outf)
00592 {
00593 fprintf(outf, "%su: %sallow the use of underlines in MIB symbols\n",
00594 lead, ((netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00595 NETSNMP_DS_LIB_MIB_PARSE_LABEL)) ?
00596 "dis" : ""));
00597 fprintf(outf, "%sc: %sallow the use of \"--\" to terminate comments\n",
00598 lead, ((netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00599 NETSNMP_DS_LIB_MIB_COMMENT_TERM)) ?
00600 "" : "dis"));
00601
00602 fprintf(outf, "%sd: %ssave the DESCRIPTIONs of the MIB objects\n",
00603 lead, ((netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00604 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) ?
00605 "do not " : ""));
00606
00607 fprintf(outf, "%se: disable errors when MIB symbols conflict\n", lead);
00608
00609 fprintf(outf, "%sw: enable warnings when MIB symbols conflict\n", lead);
00610
00611 fprintf(outf, "%sW: enable detailed warnings when MIB symbols conflict\n",
00612 lead);
00613
00614 fprintf(outf, "%sR: replace MIB symbols from latest module\n", lead);
00615 }
00616
00617 char *
00618 snmp_mib_toggle_options(char *options)
00619 {
00620 if (options) {
00621 while (*options) {
00622 switch (*options) {
00623 case 'u':
00624 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_PARSE_LABEL,
00625 !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
00626 NETSNMP_DS_LIB_MIB_PARSE_LABEL));
00627 break;
00628
00629 case 'c':
00630 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
00631 NETSNMP_DS_LIB_MIB_COMMENT_TERM);
00632 break;
00633
00634 case 'e':
00635 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
00636 NETSNMP_DS_LIB_MIB_ERRORS);
00637 break;
00638
00639 case 'w':
00640 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00641 NETSNMP_DS_LIB_MIB_WARNINGS, 1);
00642 break;
00643
00644 case 'W':
00645 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
00646 NETSNMP_DS_LIB_MIB_WARNINGS, 2);
00647 break;
00648
00649 case 'd':
00650 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
00651 NETSNMP_DS_LIB_SAVE_MIB_DESCRS);
00652 break;
00653
00654 case 'R':
00655 netsnmp_ds_toggle_boolean(NETSNMP_DS_LIBRARY_ID,
00656 NETSNMP_DS_LIB_MIB_REPLACE);
00657 break;
00658
00659 default:
00660
00661
00662
00663 return options;
00664 }
00665 options++;
00666 }
00667 }
00668 return NULL;
00669 }
00670
00671 static int
00672 name_hash(const char *name)
00673 {
00674 int hash = 0;
00675 const char *cp;
00676
00677 if (!name)
00678 return 0;
00679 for (cp = name; *cp; cp++)
00680 hash += tolower(*cp);
00681 return (hash);
00682 }
00683
00684 void
00685 netsnmp_init_mib_internals(void)
00686 {
00687 register struct tok *tp;
00688 register int b, i;
00689 int max_modc;
00690
00691 if (tree_head)
00692 return;
00693
00694
00695
00696
00697 memset(buckets, 0, sizeof(buckets));
00698 for (tp = tokens; tp->name; tp++) {
00699 tp->hash = name_hash(tp->name);
00700 b = BUCKET(tp->hash);
00701 if (buckets[b])
00702 tp->next = buckets[b];
00703 buckets[b] = tp;
00704 }
00705
00706
00707
00708
00709
00710 max_modc = sizeof(module_map) / sizeof(module_map[0]) - 1;
00711 for (i = 0; i < max_modc; ++i)
00712 module_map[i].next = &(module_map[i + 1]);
00713 module_map[max_modc].next = NULL;
00714 module_map_head = module_map;
00715
00716 memset(nbuckets, 0, sizeof(nbuckets));
00717 memset(tbuckets, 0, sizeof(tbuckets));
00718 memset(tclist, 0, MAXTC * sizeof(struct tc));
00719 build_translation_table();
00720 init_tree_roots();
00721
00722
00723
00724 }
00725
00726 #ifndef NETSNMP_CLEAN_NAMESPACE
00727 void
00728 init_mib_internals(void)
00729 {
00730 netsnmp_init_mib_internals();
00731 }
00732 #endif
00733
00734 static void
00735 init_node_hash(struct node *nodes)
00736 {
00737 struct node *np, *nextp;
00738 int hash;
00739
00740 memset(nbuckets, 0, sizeof(nbuckets));
00741 for (np = nodes; np;) {
00742 nextp = np->next;
00743 hash = NBUCKET(name_hash(np->parent));
00744 np->next = nbuckets[hash];
00745 nbuckets[hash] = np;
00746 np = nextp;
00747 }
00748 }
00749
00750 static int erroneousMibs = 0;
00751
00752 int
00753 get_mib_parse_error_count(void)
00754 {
00755 return erroneousMibs;
00756 }
00757
00758
00759 static void
00760 print_error(const char *str, const char *token, int type)
00761 {
00762 erroneousMibs++;
00763 DEBUGMSGTL(("parse-mibs", "\n"));
00764 if (type == ENDOFFILE)
00765 snmp_log(LOG_ERR, "%s (EOF): At line %d in %s\n", str, mibLine,
00766 File);
00767 else if (token && *token)
00768 snmp_log(LOG_ERR, "%s (%s): At line %d in %s\n", str, token,
00769 mibLine, File);
00770 else
00771 snmp_log(LOG_ERR, "%s: At line %d in %s\n", str, mibLine, File);
00772 }
00773
00774 static void
00775 print_module_not_found(const char *cp)
00776 {
00777 if (!last_err_module || strcmp(cp, last_err_module))
00778 print_error("Cannot find module", cp, CONTINUE);
00779 if (last_err_module)
00780 free(last_err_module);
00781 last_err_module = strdup(cp);
00782 }
00783
00784 static struct node *
00785 alloc_node(int modid)
00786 {
00787 struct node *np;
00788 np = (struct node *) calloc(1, sizeof(struct node));
00789 if (np) {
00790 np->tc_index = -1;
00791 np->modid = modid;
00792 np->filename = strdup(File);
00793 np->lineno = mibLine;
00794 }
00795 return np;
00796 }
00797
00798 static void
00799 unlink_tbucket(struct tree *tp)
00800 {
00801 int hash = NBUCKET(name_hash(tp->label));
00802 struct tree *otp = NULL, *ntp = tbuckets[hash];
00803
00804 while (ntp && ntp != tp) {
00805 otp = ntp;
00806 ntp = ntp->next;
00807 }
00808 if (!ntp)
00809 snmp_log(LOG_EMERG, "Can't find %s in tbuckets\n", tp->label);
00810 else if (otp)
00811 otp->next = ntp->next;
00812 else
00813 tbuckets[hash] = tp->next;
00814 }
00815
00816 static void
00817 unlink_tree(struct tree *tp)
00818 {
00819 struct tree *otp = NULL, *ntp = tp->parent;
00820
00821 if (!ntp) {
00822 DEBUGMSGTL(("unlink_tree", "Tree node %s has no parent\n",
00823 tp->label));
00824 } else {
00825 ntp = ntp->child_list;
00826
00827 while (ntp && ntp != tp) {
00828 otp = ntp;
00829 ntp = ntp->next_peer;
00830 }
00831 if (!ntp)
00832 snmp_log(LOG_EMERG, "Can't find %s in %s's children\n",
00833 tp->label, tp->parent->label);
00834 else if (otp)
00835 otp->next_peer = ntp->next_peer;
00836 else
00837 tp->parent->child_list = tp->next_peer;
00838 }
00839
00840 if (tree_head == tp)
00841 tree_head = tp->next_peer;
00842 }
00843
00844 static void
00845 free_partial_tree(struct tree *tp, int keep_label)
00846 {
00847 if (!tp)
00848 return;
00849
00850
00851
00852
00853 free_enums(&tp->enums);
00854 free_ranges(&tp->ranges);
00855 free_indexes(&tp->indexes);
00856 free_varbinds(&tp->varbinds);
00857 if (!keep_label)
00858 SNMP_FREE(tp->label);
00859 SNMP_FREE(tp->hint);
00860 SNMP_FREE(tp->units);
00861 SNMP_FREE(tp->description);
00862 SNMP_FREE(tp->reference);
00863 SNMP_FREE(tp->augments);
00864 SNMP_FREE(tp->defaultValue);
00865 }
00866
00867
00868
00869
00870
00871 static void
00872 free_tree(struct tree *Tree)
00873 {
00874 if (!Tree)
00875 return;
00876
00877 unlink_tbucket(Tree);
00878 free_partial_tree(Tree, FALSE);
00879 if (Tree->number_modules > 1)
00880 free((char *) Tree->module_list);
00881 free((char *) Tree);
00882 }
00883
00884 static void
00885 free_node(struct node *np)
00886 {
00887 if (!np)
00888 return;
00889
00890 free_enums(&np->enums);
00891 free_ranges(&np->ranges);
00892 free_indexes(&np->indexes);
00893 free_varbinds(&np->varbinds);
00894 if (np->label)
00895 free(np->label);
00896 if (np->hint)
00897 free(np->hint);
00898 if (np->units)
00899 free(np->units);
00900 if (np->description)
00901 free(np->description);
00902 if (np->reference)
00903 free(np->reference);
00904 if (np->defaultValue)
00905 free(np->defaultValue);
00906 if (np->parent)
00907 free(np->parent);
00908 if (np->augments)
00909 free(np->augments);
00910 if (np->filename)
00911 free(np->filename);
00912 free((char *) np);
00913 }
00914
00915 #ifdef TEST
00916 static void
00917 print_nodes(FILE * fp, struct node *root)
00918 {
00919 extern void xmalloc_stats(FILE *);
00920 struct enum_list *ep;
00921 struct index_list *ip;
00922 struct range_list *rp;
00923 struct varbind_list *vp;
00924 struct node *np;
00925
00926 for (np = root; np; np = np->next) {
00927 fprintf(fp, "%s ::= { %s %ld } (%d)\n", np->label, np->parent,
00928 np->subid, np->type);
00929 if (np->tc_index >= 0)
00930 fprintf(fp, " TC = %s\n", tclist[np->tc_index].descriptor);
00931 if (np->enums) {
00932 fprintf(fp, " Enums: \n");
00933 for (ep = np->enums; ep; ep = ep->next) {
00934 fprintf(fp, " %s(%d)\n", ep->label, ep->value);
00935 }
00936 }
00937 if (np->ranges) {
00938 fprintf(fp, " Ranges: \n");
00939 for (rp = np->ranges; rp; rp = rp->next) {
00940 fprintf(fp, " %d..%d\n", rp->low, rp->high);
00941 }
00942 }
00943 if (np->indexes) {
00944 fprintf(fp, " Indexes: \n");
00945 for (ip = np->indexes; ip; ip = ip->next) {
00946 fprintf(fp, " %s\n", ip->ilabel);
00947 }
00948 }
00949 if (np->augments)
00950 fprintf(fp, " Augments: %s\n", np->augments);
00951 if (np->varbinds) {
00952 fprintf(fp, " Varbinds: \n");
00953 for (vp = np->varbinds; vp; vp = vp->next) {
00954 fprintf(fp, " %s\n", vp->vblabel);
00955 }
00956 }
00957 if (np->hint)
00958 fprintf(fp, " Hint: %s\n", np->hint);
00959 if (np->units)
00960 fprintf(fp, " Units: %s\n", np->units);
00961 if (np->defaultValue)
00962 fprintf(fp, " DefaultValue: %s\n", np->defaultValue);
00963 }
00964 }
00965 #endif
00966
00967 void
00968 print_subtree(FILE * f, struct tree *tree, int count)
00969 {
00970 struct tree *tp;
00971 int i;
00972 char modbuf[256];
00973
00974 for (i = 0; i < count; i++)
00975 fprintf(f, " ");
00976 fprintf(f, "Children of %s(%ld):\n", tree->label, tree->subid);
00977 count++;
00978 for (tp = tree->child_list; tp; tp = tp->next_peer) {
00979 for (i = 0; i < count; i++)
00980 fprintf(f, " ");
00981 fprintf(f, "%s:%s(%ld) type=%d",
00982 module_name(tp->module_list[0], modbuf),
00983 tp->label, tp->subid, tp->type);
00984 if (tp->tc_index != -1)
00985 fprintf(f, " tc=%d", tp->tc_index);
00986 if (tp->hint)
00987 fprintf(f, " hint=%s", tp->hint);
00988 if (tp->units)
00989 fprintf(f, " units=%s", tp->units);
00990 if (tp->number_modules > 1) {
00991 fprintf(f, " modules:");
00992 for (i = 1; i < tp->number_modules; i++)
00993 fprintf(f, " %s", module_name(tp->module_list[i], modbuf));
00994 }
00995 fprintf(f, "\n");
00996 }
00997 for (tp = tree->child_list; tp; tp = tp->next_peer) {
00998 if (tp->child_list)
00999 print_subtree(f, tp, count);
01000 }
01001 }
01002
01003 void
01004 print_ascii_dump_tree(FILE * f, struct tree *tree, int count)
01005 {
01006 struct tree *tp;
01007
01008 count++;
01009 for (tp = tree->child_list; tp; tp = tp->next_peer) {
01010 fprintf(f, "%s OBJECT IDENTIFIER ::= { %s %ld }\n", tp->label,
01011 tree->label, tp->subid);
01012 }
01013 for (tp = tree->child_list; tp; tp = tp->next_peer) {
01014 if (tp->child_list)
01015 print_ascii_dump_tree(f, tp, count);
01016 }
01017 }
01018
01019 static int translation_table[256];
01020
01021 static void
01022 build_translation_table()
01023 {
01024 int count;
01025
01026 for (count = 0; count < 256; count++) {
01027 switch (count) {
01028 case OBJID:
01029 translation_table[count] = TYPE_OBJID;
01030 break;
01031 case OCTETSTR:
01032 translation_table[count] = TYPE_OCTETSTR;
01033 break;
01034 case INTEGER:
01035 translation_table[count] = TYPE_INTEGER;
01036 break;
01037 case NETADDR:
01038 translation_table[count] = TYPE_NETADDR;
01039 break;
01040 case IPADDR:
01041 translation_table[count] = TYPE_IPADDR;
01042 break;
01043 case COUNTER:
01044 translation_table[count] = TYPE_COUNTER;
01045 break;
01046 case GAUGE:
01047 translation_table[count] = TYPE_GAUGE;
01048 break;
01049 case TIMETICKS:
01050 translation_table[count] = TYPE_TIMETICKS;
01051 break;
01052 case KW_OPAQUE:
01053 translation_table[count] = TYPE_OPAQUE;
01054 break;
01055 case NUL:
01056 translation_table[count] = TYPE_NULL;
01057 break;
01058 case COUNTER64:
01059 translation_table[count] = TYPE_COUNTER64;
01060 break;
01061 case BITSTRING:
01062 translation_table[count] = TYPE_BITSTRING;
01063 break;
01064 case NSAPADDRESS:
01065 translation_table[count] = TYPE_NSAPADDRESS;
01066 break;
01067 case INTEGER32:
01068 translation_table[count] = TYPE_INTEGER32;
01069 break;
01070 case UINTEGER32:
01071 translation_table[count] = TYPE_UINTEGER;
01072 break;
01073 case UNSIGNED32:
01074 translation_table[count] = TYPE_UNSIGNED32;
01075 break;
01076 case TRAPTYPE:
01077 translation_table[count] = TYPE_TRAPTYPE;
01078 break;
01079 case NOTIFTYPE:
01080 translation_table[count] = TYPE_NOTIFTYPE;
01081 break;
01082 case NOTIFGROUP:
01083 translation_table[count] = TYPE_NOTIFGROUP;
01084 break;
01085 case OBJGROUP:
01086 translation_table[count] = TYPE_OBJGROUP;
01087 break;
01088 case MODULEIDENTITY:
01089 translation_table[count] = TYPE_MODID;
01090 break;
01091 case OBJIDENTITY:
01092 translation_table[count] = TYPE_OBJIDENTITY;
01093 break;
01094 case AGENTCAP:
01095 translation_table[count] = TYPE_AGENTCAP;
01096 break;
01097 case COMPLIANCE:
01098 translation_table[count] = TYPE_MODCOMP;
01099 break;
01100 default:
01101 translation_table[count] = TYPE_OTHER;
01102 break;
01103 }
01104 }
01105 }
01106
01107 static void
01108 init_tree_roots()
01109 {
01110 struct tree *tp, *lasttp;
01111 int base_modid;
01112 int hash;
01113
01114 base_modid = which_module("SNMPv2-SMI");
01115 if (base_modid == -1)
01116 base_modid = which_module("RFC1155-SMI");
01117 if (base_modid == -1)
01118 base_modid = which_module("RFC1213-MIB");
01119
01120
01121
01122
01123 tp = (struct tree *) calloc(1, sizeof(struct tree));
01124 if (tp == NULL)
01125 return;
01126 tp->label = strdup("joint-iso-ccitt");
01127 tp->modid = base_modid;
01128 tp->number_modules = 1;
01129 tp->module_list = &(tp->modid);
01130 tp->subid = 2;
01131 tp->tc_index = -1;
01132 set_function(tp);
01133 hash = NBUCKET(name_hash(tp->label));
01134 tp->next = tbuckets[hash];
01135 tbuckets[hash] = tp;
01136 lasttp = tp;
01137 root_imports[0].label = strdup(tp->label);
01138 root_imports[0].modid = base_modid;
01139
01140
01141
01142
01143 tp = (struct tree *) calloc(1, sizeof(struct tree));
01144 if (tp == NULL)
01145 return;
01146 tp->next_peer = lasttp;
01147 tp->label = strdup("ccitt");
01148 tp->modid = base_modid;
01149 tp->number_modules = 1;
01150 tp->module_list = &(tp->modid);
01151 tp->subid = 0;
01152 tp->tc_index = -1;
01153 set_function(tp);
01154 hash = NBUCKET(name_hash(tp->label));
01155 tp->next = tbuckets[hash];
01156 tbuckets[hash] = tp;
01157 lasttp = tp;
01158 root_imports[1].label = strdup(tp->label);
01159 root_imports[1].modid = base_modid;
01160
01161
01162
01163
01164 tp = (struct tree *) calloc(1, sizeof(struct tree));
01165 if (tp == NULL)
01166 return;
01167 tp->next_peer = lasttp;
01168 tp->label = strdup("iso");
01169 tp->modid = base_modid;
01170 tp->number_modules = 1;
01171 tp->module_list = &(tp->modid);
01172 tp->subid = 1;
01173 tp->tc_index = -1;
01174 set_function(tp);
01175 hash = NBUCKET(name_hash(tp->label));
01176 tp->next = tbuckets[hash];
01177 tbuckets[hash] = tp;
01178 lasttp = tp;
01179 root_imports[2].label = strdup(tp->label);
01180 root_imports[2].modid = base_modid;
01181
01182 tree_head = tp;
01183 }
01184
01185 #ifdef STRICT_MIB_PARSEING
01186 #define label_compare strcasecmp
01187 #else
01188 #define label_compare strcmp
01189 #endif
01190
01191
01192 struct tree *
01193 find_tree_node(const char *name, int modid)
01194 {
01195 struct tree *tp, *headtp;
01196 int count, *int_p;
01197
01198 if (!name || !*name)
01199 return (NULL);
01200
01201 headtp = tbuckets[NBUCKET(name_hash(name))];
01202 for (tp = headtp; tp; tp = tp->next) {
01203 if (tp->label && !label_compare(tp->label, name)) {
01204
01205 if (modid == -1)
01206 return (tp);
01207
01208 for (int_p = tp->module_list, count = 0;
01209 count < tp->number_modules; ++count, ++int_p)
01210 if (*int_p == modid)
01211 return (tp);
01212 }
01213 }
01214
01215 return (NULL);
01216 }
01217
01218
01219
01220
01221
01222
01223 #define MAX_BAD 0xffffff
01224
01225 static u_int
01226 compute_match(const char *search_base, const char *key)
01227 {
01228 #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
01229 int rc;
01230 regex_t parsetree;
01231 regmatch_t pmatch;
01232 rc = regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED);
01233 if (rc == 0)
01234 rc = regexec(&parsetree, search_base, 1, &pmatch, 0);
01235 regfree(&parsetree);
01236 if (rc == 0) {
01237
01238
01239
01240 return pmatch.rm_so;
01241 }
01242 #else
01243
01244
01245
01246 char *first = NULL, *result = NULL, *entry;
01247 const char *position;
01248 char *newkey = strdup(key);
01249 char *st;
01250
01251
01252 entry = strtok_r(newkey, "*", &st);
01253 position = search_base;
01254 while (entry) {
01255 result = strcasestr(position, entry);
01256
01257 if (result == NULL) {
01258 free(newkey);
01259 return MAX_BAD;
01260 }
01261
01262 if (first == NULL)
01263 first = result;
01264
01265 position = result + strlen(entry);
01266 entry = strtok_r(NULL, "*", &st);
01267 }
01268 free(newkey);
01269 if (result)
01270 return (first - search_base);
01271 #endif
01272
01273
01274
01275
01276 return MAX_BAD;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 struct tree *
01292 find_best_tree_node(const char *pattrn, struct tree *tree_top,
01293 u_int * match)
01294 {
01295 struct tree *tp, *best_so_far = NULL, *retptr;
01296 u_int old_match = MAX_BAD, new_match = MAX_BAD;
01297
01298 if (!pattrn || !*pattrn)
01299 return (NULL);
01300
01301 if (!tree_top)
01302 tree_top = get_tree_head();
01303
01304 for (tp = tree_top; tp; tp = tp->next_peer) {
01305 if (!tp->reported && tp->label)
01306 new_match = compute_match(tp->label, pattrn);
01307 tp->reported = 1;
01308
01309 if (new_match < old_match) {
01310 best_so_far = tp;
01311 old_match = new_match;
01312 }
01313 if (new_match == 0)
01314 break;
01315 if (tp->child_list) {
01316 retptr =
01317 find_best_tree_node(pattrn, tp->child_list, &new_match);
01318 if (new_match < old_match) {
01319 best_so_far = retptr;
01320 old_match = new_match;
01321 }
01322 if (new_match == 0)
01323 break;
01324 }
01325 }
01326 if (match)
01327 *match = old_match;
01328 return (best_so_far);
01329 }
01330
01331
01332 static void
01333 merge_anon_children(struct tree *tp1, struct tree *tp2)
01334
01335
01336
01337 {
01338 struct tree *child1, *child2, *previous;
01339
01340 for (child1 = tp1->child_list; child1;) {
01341
01342 for (child2 = tp2->child_list, previous = NULL;
01343 child2; previous = child2, child2 = child2->next_peer) {
01344
01345 if (child1->subid == child2->subid) {
01346
01347
01348
01349
01350 if (!strncmp(child1->label, ANON, ANON_LEN)) {
01351 merge_anon_children(child1, child2);
01352
01353 child1->child_list = NULL;
01354 previous = child1;
01355 child1 = child1->next_peer;
01356 free_tree(previous);
01357 goto next;
01358 }
01359
01360 else if (!strncmp(child2->label, ANON, ANON_LEN)) {
01361 merge_anon_children(child2, child1);
01362
01363 if (previous)
01364 previous->next_peer = child2->next_peer;
01365 else
01366 tp2->child_list = child2->next_peer;
01367 free_tree(child2);
01368
01369 previous = child1;
01370 child1 = child1->next_peer;
01371 previous->next_peer = tp2->child_list;
01372 tp2->child_list = previous;
01373 for (previous = tp2->child_list;
01374 previous; previous = previous->next_peer)
01375 previous->parent = tp2;
01376 goto next;
01377 } else if (!label_compare(child1->label, child2->label)) {
01378 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
01379 NETSNMP_DS_LIB_MIB_WARNINGS)) {
01380 snmp_log(LOG_WARNING,
01381 "Warning: %s.%ld is both %s and %s (%s)\n",
01382 tp2->label, child1->subid, child1->label,
01383 child2->label, File);
01384 }
01385 continue;
01386 } else {
01387
01388
01389
01390
01391
01392 if (child2->child_list) {
01393 for (previous = child2->child_list; previous->next_peer; previous = previous->next_peer);
01394 previous->next_peer = child1->child_list;
01395 } else
01396 child2->child_list = child1->child_list;
01397 for (previous = child1->child_list;
01398 previous; previous = previous->next_peer)
01399 previous->parent = child2;
01400 child1->child_list = NULL;
01401
01402 previous = child1;
01403 child1 = child1->next_peer;
01404 free_tree(previous);
01405 goto next;
01406 }
01407 }
01408 }
01409
01410
01411
01412 if (child1) {
01413 previous = child1;
01414 child1 = child1->next_peer;
01415 previous->parent = tp2;
01416 previous->next_peer = tp2->child_list;
01417 tp2->child_list = previous;
01418 }
01419 next:;
01420 }
01421 }
01422
01423
01424
01425
01426
01427
01428 static void
01429 do_subtree(struct tree *root, struct node **nodes)
01430 {
01431 struct tree *tp, *anon_tp = NULL;
01432 struct tree *xroot = root;
01433 struct node *np, **headp;
01434 struct node *oldnp = NULL, *child_list = NULL, *childp = NULL;
01435 int hash;
01436 int *int_p;
01437
01438 while (xroot->next_peer && xroot->next_peer->subid == root->subid) {
01439 #if 0
01440 printf("xroot: %s.%s => %s\n", xroot->parent->label, xroot->label,
01441 xroot->next_peer->label);
01442 #endif
01443 xroot = xroot->next_peer;
01444 }
01445
01446 tp = root;
01447 headp = &nbuckets[NBUCKET(name_hash(tp->label))];
01448
01449
01450
01451
01452 for (np = *headp; np; np = np->next) {
01453 if (!label_compare(tp->label, np->parent)) {
01454
01455
01456
01457 if (oldnp == NULL) {
01458 *headp = np->next;
01459 } else {
01460 oldnp->next = np->next;
01461 }
01462 if (child_list)
01463 childp->next = np;
01464 else
01465 child_list = np;
01466 childp = np;
01467 } else {
01468 oldnp = np;
01469 }
01470
01471 }
01472 if (childp)
01473 childp->next = NULL;
01474
01475
01476
01477 for (np = child_list; np; np = np->next) {
01478 struct tree *otp = NULL;
01479 struct tree *xxroot = xroot;
01480 anon_tp = NULL;
01481 tp = xroot->child_list;
01482
01483 if (np->subid == -1) {
01484
01485
01486
01487 np->subid = xroot->subid;
01488 tp = xroot;
01489 xxroot = xroot->parent;
01490 }
01491
01492 while (tp) {
01493 if (tp->subid == np->subid)
01494 break;
01495 else {
01496 otp = tp;
01497 tp = tp->next_peer;
01498 }
01499 }
01500 if (tp) {
01501 if (!label_compare(tp->label, np->label)) {
01502
01503
01504
01505 int_p =
01506 (int *) malloc((tp->number_modules + 1) * sizeof(int));
01507 if (int_p == NULL)
01508 return;
01509 memcpy(int_p, tp->module_list,
01510 tp->number_modules * sizeof(int));
01511 int_p[tp->number_modules] = np->modid;
01512 if (tp->number_modules > 1)
01513 free((char *) tp->module_list);
01514 ++tp->number_modules;
01515 tp->module_list = int_p;
01516
01517 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
01518 NETSNMP_DS_LIB_MIB_REPLACE)) {
01519
01520
01521
01522 tree_from_node(tp, np);
01523 }
01524
01525
01526
01527 do_subtree(tp, nodes);
01528 continue;
01529 }
01530 if (!strncmp(np->label, ANON, ANON_LEN) ||
01531 !strncmp(tp->label, ANON, ANON_LEN)) {
01532 anon_tp = tp;
01533 } else if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
01534 NETSNMP_DS_LIB_MIB_WARNINGS)) {
01535 snmp_log(LOG_WARNING,
01536 "Warning: %s.%ld is both %s and %s (%s)\n",
01537 root->label, np->subid, tp->label, np->label,
01538 File);
01539 }
01540 }
01541
01542 tp = (struct tree *) calloc(1, sizeof(struct tree));
01543 if (tp == NULL)
01544 return;
01545 tp->parent = xxroot;
01546 tp->modid = np->modid;
01547 tp->number_modules = 1;
01548 tp->module_list = &(tp->modid);
01549 tree_from_node(tp, np);
01550 tp->next_peer = otp ? otp->next_peer : xxroot->child_list;
01551 if (otp)
01552 otp->next_peer = tp;
01553 else
01554 xxroot->child_list = tp;
01555 hash = NBUCKET(name_hash(tp->label));
01556 tp->next = tbuckets[hash];
01557 tbuckets[hash] = tp;
01558 do_subtree(tp, nodes);
01559
01560 if (anon_tp) {
01561 if (!strncmp(tp->label, ANON, ANON_LEN)) {
01562
01563
01564
01565
01566 merge_anon_children(tp, anon_tp);
01567
01568
01569
01570
01571 unlink_tree(tp);
01572 free_tree(tp);
01573 } else if (!strncmp(anon_tp->label, ANON, ANON_LEN)) {
01574 struct tree *ntp;
01575
01576
01577
01578
01579
01580 merge_anon_children(anon_tp, tp);
01581
01582
01583
01584
01585 unlink_tbucket(anon_tp);
01586
01587
01588
01589
01590 free_partial_tree(anon_tp, FALSE);
01591
01592
01593
01594
01595 anon_tp->label = tp->label;
01596 anon_tp->child_list = tp->child_list;
01597 anon_tp->modid = tp->modid;
01598 anon_tp->tc_index = tp->tc_index;
01599 anon_tp->type = tp->type;
01600 anon_tp->enums = tp->enums;
01601 anon_tp->indexes = tp->indexes;
01602 anon_tp->augments = tp->augments;
01603 anon_tp->varbinds = tp->varbinds;
01604 anon_tp->ranges = tp->ranges;
01605 anon_tp->hint = tp->hint;
01606 anon_tp->units = tp->units;
01607 anon_tp->description = tp->description;
01608 anon_tp->reference = tp->reference;
01609 anon_tp->defaultValue = tp->defaultValue;
01610 anon_tp->parent = tp->parent;
01611
01612 set_function(anon_tp);
01613
01614
01615
01616
01617 ntp = anon_tp->child_list;
01618 while (ntp) {
01619 ntp->parent = anon_tp;
01620 ntp = ntp->next_peer;
01621 }
01622
01623
01624
01625
01626 hash = NBUCKET(name_hash(anon_tp->label));
01627 anon_tp->next = tbuckets[hash];
01628 tbuckets[hash] = anon_tp;
01629
01630
01631
01632
01633 unlink_tbucket(tp);
01634 unlink_tree(tp);
01635 free(tp);
01636 } else {
01637
01638
01639
01640 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
01641 NETSNMP_DS_LIB_MIB_WARNINGS)) {
01642 snmp_log(LOG_WARNING,
01643 "Warning: expected anonymous node (either %s or %s) in %s\n",
01644 tp->label, anon_tp->label, File);
01645 }
01646 }
01647 anon_tp = NULL;
01648 }
01649 }
01650
01651
01652
01653 oldnp = NULL;
01654 for (np = child_list; np; np = np->next) {
01655 if (oldnp)
01656 free_node(oldnp);
01657 oldnp = np;
01658 }
01659 if (oldnp)
01660 free_node(oldnp);
01661 }
01662
01663 static void
01664 do_linkup(struct module *mp, struct node *np)
01665 {
01666 struct module_import *mip;
01667 struct node *onp, *oldp, *newp;
01668 struct tree *tp;
01669 int i, more;
01670
01671
01672
01673
01674 if (snmp_get_do_debugging() > 1)
01675 dump_module_list();
01676 DEBUGMSGTL(("parse-mibs", "Processing IMPORTS for module %d %s\n",
01677 mp->modid, mp->name));
01678 if (mp->no_imports == 0) {
01679 mp->no_imports = NUMBER_OF_ROOT_NODES;
01680 mp->imports = root_imports;
01681 }
01682
01683
01684
01685
01686 init_node_hash(np);
01687 for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
01688 char modbuf[256];
01689 DEBUGMSGTL(("parse-mibs", " Processing import: %s\n",
01690 mip->label));
01691 if (get_tc_index(mip->label, mip->modid) != -1)
01692 continue;
01693 tp = find_tree_node(mip->label, mip->modid);
01694 if (!tp) {
01695 snmp_log(LOG_WARNING,
01696 "Did not find '%s' in module %s (%s)\n",
01697 mip->label, module_name(mip->modid, modbuf),
01698 File);
01699 continue;
01700 }
01701 do_subtree(tp, &np);
01702 }
01703
01704
01705
01706
01707
01708
01709
01710 if (!np)
01711 return;
01712 for (tp = tree_head; tp; tp = tp->next_peer)
01713 do_subtree(tp, &np);
01714 if (!np)
01715 return;
01716
01717
01718
01719
01720 oldp = orphan_nodes;
01721 do {
01722 for (i = 0; i < NHASHSIZE; i++)
01723 for (onp = nbuckets[i]; onp; onp = onp->next) {
01724 struct node *op = NULL;
01725 int hash = NBUCKET(name_hash(onp->label));
01726 np = nbuckets[hash];
01727 while (np) {
01728 if (label_compare(onp->label, np->parent)) {
01729 op = np;
01730 np = np->next;
01731 } else {
01732 if (op)
01733 op->next = np->next;
01734 else
01735 nbuckets[hash] = np->next;
01736 np->next = orphan_nodes;
01737 orphan_nodes = np;
01738 op = NULL;
01739 np = nbuckets[hash];
01740 }
01741 }
01742 }
01743 newp = orphan_nodes;
01744 more = 0;
01745 for (onp = orphan_nodes; onp != oldp; onp = onp->next) {
01746 struct node *op = NULL;
01747 int hash = NBUCKET(name_hash(onp->label));
01748 np = nbuckets[hash];
01749 while (np) {
01750 if (label_compare(onp->label, np->parent)) {
01751 op = np;
01752 np = np->next;
01753 } else {
01754 if (op)
01755 op->next = np->next;
01756 else
01757 nbuckets[hash] = np->next;
01758 np->next = orphan_nodes;
01759 orphan_nodes = np;
01760 op = NULL;
01761 np = nbuckets[hash];
01762 more = 1;
01763 }
01764 }
01765 }
01766 oldp = newp;
01767 } while (more);
01768
01769
01770
01771
01772 for (np = orphan_nodes; np && np->next; np = np->next);
01773 for (i = 0; i < NHASHSIZE; i++)
01774 if (nbuckets[i]) {
01775 if (orphan_nodes)
01776 onp = np->next = nbuckets[i];
01777 else
01778 onp = orphan_nodes = nbuckets[i];
01779 nbuckets[i] = NULL;
01780 while (onp) {
01781 snmp_log(LOG_WARNING,
01782 "Unlinked OID in %s: %s ::= { %s %ld }\n",
01783 (mp->name ? mp->name : "<no module>"),
01784 (onp->label ? onp->label : "<no label>"),
01785 (onp->parent ? onp->parent : "<no parent>"),
01786 onp->subid);
01787 snmp_log(LOG_WARNING,
01788 "Undefined identifier: %s near line %d of %s\n",
01789 (onp->parent ? onp->parent : "<no parent>"),
01790 onp->lineno, onp->filename);
01791 np = onp;
01792 onp = onp->next;
01793 }
01794 }
01795 return;
01796 }
01797
01798
01799
01800
01801
01802
01803
01804
01805 static int
01806 getoid(FILE * fp, struct subid_s *id,
01807 int length)
01808 {
01809 register int count;
01810 int type;
01811 char token[MAXTOKEN];
01812
01813 if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET) {
01814 print_error("Expected \"{\"", token, type);
01815 return 0;
01816 }
01817 type = get_token(fp, token, MAXTOKEN);
01818 for (count = 0; count < length; count++, id++) {
01819 id->label = NULL;
01820 id->modid = current_module;
01821 id->subid = -1;
01822 if (type == RIGHTBRACKET)
01823 return count;
01824 if (type == LABEL) {
01825
01826
01827
01828 id->label = strdup(token);
01829 type = get_token(fp, token, MAXTOKEN);
01830 if (type == LEFTPAREN) {
01831 type = get_token(fp, token, MAXTOKEN);
01832 if (type == NUMBER) {
01833 id->subid = strtoul(token, NULL, 10);
01834 if ((type =
01835 get_token(fp, token, MAXTOKEN)) != RIGHTPAREN) {
01836 print_error("Expected a closing parenthesis",
01837 token, type);
01838 return 0;
01839 }
01840 } else {
01841 print_error("Expected a number", token, type);
01842 return 0;
01843 }
01844 } else {
01845 continue;
01846 }
01847 } else if (type == NUMBER) {
01848
01849
01850
01851 id->subid = strtoul(token, NULL, 10);
01852 } else {
01853 print_error("Expected label or number", token, type);
01854 return 0;
01855 }
01856 type = get_token(fp, token, MAXTOKEN);
01857 }
01858 print_error("Too long OID", token, type);
01859 return 0;
01860 }
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 static struct node *
01885 parse_objectid(FILE * fp, char *name)
01886 {
01887 register int count;
01888 register struct subid_s *op, *nop;
01889 int length;
01890 struct subid_s loid[32];
01891 struct node *np, *root = NULL, *oldnp = NULL;
01892 struct tree *tp;
01893
01894 if ((length = getoid(fp, loid, 32)) == 0) {
01895 print_error("Bad object identifier", NULL, CONTINUE);
01896 return NULL;
01897 }
01898
01899
01900
01901
01902
01903 op = loid;
01904 if (!op->label) {
01905 if (length == 1) {
01906 print_error("Attempt to define a root oid", name, OBJECT);
01907 return NULL;
01908 }
01909 for (tp = tree_head; tp; tp = tp->next_peer)
01910 if ((int) tp->subid == op->subid) {
01911 op->label = strdup(tp->label);
01912 break;
01913 }
01914 }
01915
01916
01917
01918
01919 if (length == 1) {
01920 op = loid;
01921 np = alloc_node(op->modid);
01922 if (np == NULL)
01923 return (NULL);
01924 np->subid = op->subid;
01925 np->label = strdup(name);
01926 np->parent = op->label;
01927 return np;
01928 }
01929
01930
01931
01932
01933
01934 for (count = 0, op = loid, nop = loid + 1; count < (length - 1);
01935 count++, op++, nop++) {
01936
01937
01938
01939
01940
01941
01942 if (op->label && (nop->label || (nop->subid != -1))) {
01943 np = alloc_node(nop->modid);
01944 if (np == NULL)
01945 return (NULL);
01946 if (root == NULL)
01947 root = np;
01948
01949 np->parent = strdup(op->label);
01950 if (count == (length - 2)) {
01951
01952
01953
01954 np->label = strdup(name);
01955 } else {
01956 if (!nop->label) {
01957 nop->label = (char *) malloc(20 + ANON_LEN);
01958 if (nop->label == NULL)
01959 return (NULL);
01960 sprintf(nop->label, "%s%d", ANON, anonymous++);
01961 }
01962 np->label = strdup(nop->label);
01963 }
01964 if (nop->subid != -1)
01965 np->subid = nop->subid;
01966 else
01967 print_error("Warning: This entry is pretty silly",
01968 np->label, CONTINUE);
01969
01970
01971
01972
01973 if (oldnp)
01974 oldnp->next = np;
01975 oldnp = np;
01976 }
01977 }
01978
01979
01980
01981
01982 for (count = 0, op = loid; count < length; count++, op++) {
01983 if (op->label)
01984 free(op->label);
01985 }
01986
01987 return root;
01988 }
01989
01990 static int
01991 get_tc(const char *descriptor,
01992 int modid,
01993 int *tc_index,
01994 struct enum_list **ep, struct range_list **rp, char **hint)
01995 {
01996 int i;
01997 struct tc *tcp;
01998
01999 i = get_tc_index(descriptor, modid);
02000 if (tc_index)
02001 *tc_index = i;
02002 if (i != -1) {
02003 tcp = &tclist[i];
02004 if (ep) {
02005 free_enums(ep);
02006 *ep = copy_enums(tcp->enums);
02007 }
02008 if (rp) {
02009 free_ranges(rp);
02010 *rp = copy_ranges(tcp->ranges);
02011 }
02012 if (hint) {
02013 if (*hint)
02014 free(*hint);
02015 *hint = (tcp->hint ? strdup(tcp->hint) : NULL);
02016 }
02017 return tcp->type;
02018 }
02019 return LABEL;
02020 }
02021
02022
02023
02024
02025
02026 static int
02027 get_tc_index(const char *descriptor, int modid)
02028 {
02029 int i;
02030 struct tc *tcp;
02031 struct module *mp;
02032 struct module_import *mip;
02033
02034
02035
02036
02037
02038
02039 for (mp = module_head; mp; mp = mp->next)
02040 if (mp->modid == modid)
02041 break;
02042 if (mp)
02043 for (i = 0, mip = mp->imports; i < mp->no_imports; ++i, ++mip) {
02044 if (!label_compare(mip->label, descriptor)) {
02045
02046
02047
02048 modid = mip->modid;
02049 break;
02050 }
02051 }
02052
02053
02054 for (i = 0, tcp = tclist; i < MAXTC; i++, tcp++) {
02055 if (tcp->type == 0)
02056 break;
02057 if (!label_compare(descriptor, tcp->descriptor) &&
02058 ((modid == tcp->modid) || (modid == -1))) {
02059 return i;
02060 }
02061 }
02062 return -1;
02063 }
02064
02065
02066
02067
02068
02069
02070 const char *
02071 get_tc_descriptor(int tc_index)
02072 {
02073 if (tc_index < 0 || tc_index >= MAXTC)
02074 return NULL;
02075 return (tclist[tc_index].descriptor);
02076 }
02077
02078 const char *
02079 get_tc_description(int tc_index)
02080 {
02081 if (tc_index < 0 || tc_index >= MAXTC)
02082 return NULL;
02083 return (tclist[tc_index].description);
02084 }
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094 static struct enum_list *
02095 parse_enumlist(FILE * fp, struct enum_list **retp)
02096 {
02097 register int type;
02098 char token[MAXTOKEN];
02099 struct enum_list *ep = NULL, **epp = &ep;
02100
02101 free_enums(retp);
02102
02103 while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
02104 if (type == RIGHTBRACKET)
02105 break;
02106
02107
02108 if (type == LABEL || type == DEPRECATED) {
02109
02110
02111
02112 *epp =
02113 (struct enum_list *) calloc(1, sizeof(struct enum_list));
02114 if (*epp == NULL)
02115 return (NULL);
02116
02117
02118
02119 (*epp)->label = strdup(token);
02120 type = get_token(fp, token, MAXTOKEN);
02121 if (type != LEFTPAREN) {
02122 print_error("Expected \"(\"", token, type);
02123 return NULL;
02124 }
02125 type = get_token(fp, token, MAXTOKEN);
02126 if (type != NUMBER) {
02127 print_error("Expected integer", token, type);
02128 return NULL;
02129 }
02130 (*epp)->value = strtol(token, NULL, 10);
02131 type = get_token(fp, token, MAXTOKEN);
02132 if (type != RIGHTPAREN) {
02133 print_error("Expected \")\"", token, type);
02134 return NULL;
02135 }
02136 epp = &(*epp)->next;
02137 }
02138 }
02139 if (type == ENDOFFILE) {
02140 print_error("Expected \"}\"", token, type);
02141 return NULL;
02142 }
02143 *retp = ep;
02144 return ep;
02145 }
02146
02147 static struct range_list *
02148 parse_ranges(FILE * fp, struct range_list **retp)
02149 {
02150 int low, high;
02151 char nexttoken[MAXTOKEN];
02152 int nexttype;
02153 struct range_list *rp = NULL, **rpp = &rp;
02154 int size = 0, taken = 1;
02155
02156 free_ranges(retp);
02157
02158 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02159 if (nexttype == SIZE) {
02160 size = 1;
02161 taken = 0;
02162 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02163 if (nexttype != LEFTPAREN)
02164 print_error("Expected \"(\" after SIZE", nexttoken, nexttype);
02165 }
02166
02167 do {
02168 if (!taken)
02169 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02170 else
02171 taken = 0;
02172 high = low = strtol(nexttoken, NULL, 10);
02173 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02174 if (nexttype == RANGE) {
02175 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02176 errno = 0;
02177 high = strtol(nexttoken, NULL, 10);
02178 if ( errno == ERANGE ) {
02179 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
02180 NETSNMP_DS_LIB_MIB_WARNINGS))
02181 snmp_log(LOG_WARNING,
02182 "Warning: Upper bound not handled correctly (%s != %d): At line %d in %s\n",
02183 nexttoken, high, mibLine, File);
02184 }
02185 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02186 }
02187 *rpp = (struct range_list *) calloc(1, sizeof(struct range_list));
02188 if (*rpp == NULL)
02189 break;
02190 (*rpp)->low = low;
02191 (*rpp)->high = high;
02192 rpp = &(*rpp)->next;
02193
02194 } while (nexttype == BAR);
02195 if (size) {
02196 if (nexttype != RIGHTPAREN)
02197 print_error("Expected \")\" after SIZE", nexttoken, nexttype);
02198 nexttype = get_token(fp, nexttoken, nexttype);
02199 }
02200 if (nexttype != RIGHTPAREN)
02201 print_error("Expected \")\"", nexttoken, nexttype);
02202
02203 *retp = rp;
02204 return rp;
02205 }
02206
02207
02208
02209
02210
02211 static struct node *
02212 parse_asntype(FILE * fp, char *name, int *ntype, char *ntoken)
02213 {
02214 int type, i;
02215 char token[MAXTOKEN];
02216 char quoted_string_buffer[MAXQUOTESTR];
02217 char *hint = NULL;
02218 char *descr = NULL;
02219 struct tc *tcp;
02220 int level;
02221
02222 type = get_token(fp, token, MAXTOKEN);
02223 if (type == SEQUENCE || type == CHOICE) {
02224 level = 0;
02225 while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE) {
02226 if (type == LEFTBRACKET) {
02227 level++;
02228 } else if (type == RIGHTBRACKET && --level == 0) {
02229 *ntype = get_token(fp, ntoken, MAXTOKEN);
02230 return NULL;
02231 }
02232 }
02233 print_error("Expected \"}\"", token, type);
02234 return NULL;
02235 } else if (type == LEFTBRACKET) {
02236 struct node *np;
02237 int ch_next = '{';
02238 ungetc(ch_next, fp);
02239 np = parse_objectid(fp, name);
02240 if (np != NULL) {
02241 *ntype = get_token(fp, ntoken, MAXTOKEN);
02242 return np;
02243 }
02244 return NULL;
02245 } else if (type == LEFTSQBRACK) {
02246 int size = 0;
02247 do {
02248 type = get_token(fp, token, MAXTOKEN);
02249 } while (type != ENDOFFILE && type != RIGHTSQBRACK);
02250 if (type != RIGHTSQBRACK) {
02251 print_error("Expected \"]\"", token, type);
02252 return NULL;
02253 }
02254 type = get_token(fp, token, MAXTOKEN);
02255 if (type == IMPLICIT)
02256 type = get_token(fp, token, MAXTOKEN);
02257 *ntype = get_token(fp, ntoken, MAXTOKEN);
02258 if (*ntype == LEFTPAREN) {
02259 switch (type) {
02260 case OCTETSTR:
02261 *ntype = get_token(fp, ntoken, MAXTOKEN);
02262 if (*ntype != SIZE) {
02263 print_error("Expected SIZE", ntoken, *ntype);
02264 return NULL;
02265 }
02266 size = 1;
02267 *ntype = get_token(fp, ntoken, MAXTOKEN);
02268 if (*ntype != LEFTPAREN) {
02269 print_error("Expected \"(\" after SIZE", ntoken,
02270 *ntype);
02271 return NULL;
02272 }
02273
02274
02275
02276 case INTEGER:
02277 *ntype = get_token(fp, ntoken, MAXTOKEN);
02278 do {
02279 if (*ntype != NUMBER)
02280 print_error("Expected NUMBER", ntoken, *ntype);
02281 *ntype = get_token(fp, ntoken, MAXTOKEN);
02282 if (*ntype == RANGE) {
02283 *ntype = get_token(fp, ntoken, MAXTOKEN);
02284 if (*ntype != NUMBER)
02285 print_error("Expected NUMBER", ntoken, *ntype);
02286 *ntype = get_token(fp, ntoken, MAXTOKEN);
02287 }
02288 } while (*ntype == BAR);
02289 if (*ntype != RIGHTPAREN) {
02290 print_error("Expected \")\"", ntoken, *ntype);
02291 return NULL;
02292 }
02293 *ntype = get_token(fp, ntoken, MAXTOKEN);
02294 if (size) {
02295 if (*ntype != RIGHTPAREN) {
02296 print_error("Expected \")\" to terminate SIZE",
02297 ntoken, *ntype);
02298 return NULL;
02299 }
02300 *ntype = get_token(fp, ntoken, MAXTOKEN);
02301 }
02302 }
02303 }
02304 return NULL;
02305 } else {
02306 if (type == CONVENTION) {
02307 while (type != SYNTAX && type != ENDOFFILE) {
02308 if (type == DISPLAYHINT) {
02309 type = get_token(fp, token, MAXTOKEN);
02310 if (type != QUOTESTRING)
02311 print_error("DISPLAY-HINT must be string", token,
02312 type);
02313 else
02314 hint = strdup(token);
02315 } else if (type == DESCRIPTION &&
02316 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
02317 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
02318 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02319 if (type != QUOTESTRING)
02320 print_error("DESCRIPTION must be string", token,
02321 type);
02322 else
02323 descr = strdup(quoted_string_buffer);
02324 } else
02325 type =
02326 get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02327 }
02328 type = get_token(fp, token, MAXTOKEN);
02329 if (type == OBJECT) {
02330 type = get_token(fp, token, MAXTOKEN);
02331 if (type != IDENTIFIER) {
02332 print_error("Expected IDENTIFIER", token, type);
02333 SNMP_FREE(hint);
02334 return NULL;
02335 }
02336 type = OBJID;
02337 }
02338 } else if (type == OBJECT) {
02339 type = get_token(fp, token, MAXTOKEN);
02340 if (type != IDENTIFIER) {
02341 print_error("Expected IDENTIFIER", token, type);
02342 return NULL;
02343 }
02344 type = OBJID;
02345 }
02346
02347 if (type == LABEL) {
02348 type = get_tc(token, current_module, NULL, NULL, NULL, NULL);
02349 }
02350
02351
02352
02353
02354 for (i = 0; i < MAXTC; i++) {
02355 if (tclist[i].type == 0)
02356 break;
02357 }
02358
02359 if (i == MAXTC) {
02360 print_error("Too many textual conventions", token, type);
02361 SNMP_FREE(hint);
02362 return NULL;
02363 }
02364 if (!(type & SYNTAX_MASK)) {
02365 print_error("Textual convention doesn't map to real type",
02366 token, type);
02367 SNMP_FREE(hint);
02368 return NULL;
02369 }
02370 tcp = &tclist[i];
02371 tcp->modid = current_module;
02372 tcp->descriptor = strdup(name);
02373 tcp->hint = hint;
02374 tcp->description = descr;
02375 tcp->type = type;
02376 *ntype = get_token(fp, ntoken, MAXTOKEN);
02377 if (*ntype == LEFTPAREN) {
02378 tcp->ranges = parse_ranges(fp, &tcp->ranges);
02379 *ntype = get_token(fp, ntoken, MAXTOKEN);
02380 } else if (*ntype == LEFTBRACKET) {
02381
02382
02383
02384 tcp->enums = parse_enumlist(fp, &tcp->enums);
02385 *ntype = get_token(fp, ntoken, MAXTOKEN);
02386 }
02387 return NULL;
02388 }
02389 }
02390
02391
02392
02393
02394
02395
02396 static struct node *
02397 parse_objecttype(FILE * fp, char *name)
02398 {
02399 register int type;
02400 char token[MAXTOKEN];
02401 char nexttoken[MAXTOKEN];
02402 char quoted_string_buffer[MAXQUOTESTR];
02403 int nexttype, tctype;
02404 register struct node *np;
02405
02406 type = get_token(fp, token, MAXTOKEN);
02407 if (type != SYNTAX) {
02408 print_error("Bad format for OBJECT-TYPE", token, type);
02409 return NULL;
02410 }
02411 np = alloc_node(current_module);
02412 if (np == NULL)
02413 return (NULL);
02414 type = get_token(fp, token, MAXTOKEN);
02415 if (type == OBJECT) {
02416 type = get_token(fp, token, MAXTOKEN);
02417 if (type != IDENTIFIER) {
02418 print_error("Expected IDENTIFIER", token, type);
02419 free_node(np);
02420 return NULL;
02421 }
02422 type = OBJID;
02423 }
02424 if (type == LABEL) {
02425 int tmp_index;
02426 tctype = get_tc(token, current_module, &tmp_index,
02427 &np->enums, &np->ranges, &np->hint);
02428 if (tctype == LABEL &&
02429 netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
02430 NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
02431 print_error("Warning: No known translation for type", token,
02432 type);
02433 }
02434 type = tctype;
02435 np->tc_index = tmp_index;
02436 }
02437 np->type = type;
02438 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02439 switch (type) {
02440 case SEQUENCE:
02441 if (nexttype == OF) {
02442 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02443 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02444
02445 }
02446 break;
02447 case INTEGER:
02448 case INTEGER32:
02449 case UINTEGER32:
02450 case UNSIGNED32:
02451 case COUNTER:
02452 case GAUGE:
02453 case BITSTRING:
02454 case LABEL:
02455 if (nexttype == LEFTBRACKET) {
02456
02457
02458
02459 np->enums = parse_enumlist(fp, &np->enums);
02460 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02461 } else if (nexttype == LEFTPAREN) {
02462
02463
02464
02465 np->ranges = parse_ranges(fp, &np->ranges);
02466 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02467 }
02468 break;
02469 case OCTETSTR:
02470 case KW_OPAQUE:
02471
02472
02473
02474 if (nexttype == LEFTPAREN) {
02475 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02476 if (nexttype == SIZE) {
02477 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02478 if (nexttype == LEFTPAREN) {
02479 np->ranges = parse_ranges(fp, &np->ranges);
02480 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02481 if (nexttype == RIGHTPAREN) {
02482 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02483 break;
02484 }
02485 }
02486 }
02487 print_error("Bad SIZE syntax", token, type);
02488 free_node(np);
02489 return NULL;
02490 }
02491 break;
02492 case OBJID:
02493 case NETADDR:
02494 case IPADDR:
02495 case TIMETICKS:
02496 case NUL:
02497 case NSAPADDRESS:
02498 case COUNTER64:
02499 break;
02500 default:
02501 print_error("Bad syntax", token, type);
02502 free_node(np);
02503 return NULL;
02504 }
02505 if (nexttype == UNITS) {
02506 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02507 if (type != QUOTESTRING) {
02508 print_error("Bad UNITS", quoted_string_buffer, type);
02509 free_node(np);
02510 return NULL;
02511 }
02512 np->units = strdup(quoted_string_buffer);
02513 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02514 }
02515 if (nexttype != ACCESS) {
02516 print_error("Should be ACCESS", nexttoken, nexttype);
02517 free_node(np);
02518 return NULL;
02519 }
02520 type = get_token(fp, token, MAXTOKEN);
02521 if (type != READONLY && type != READWRITE && type != WRITEONLY
02522 && type != NOACCESS && type != READCREATE && type != ACCNOTIFY) {
02523 print_error("Bad ACCESS type", token, type);
02524 free_node(np);
02525 return NULL;
02526 }
02527 np->access = type;
02528 type = get_token(fp, token, MAXTOKEN);
02529 if (type != STATUS) {
02530 print_error("Should be STATUS", token, type);
02531 free_node(np);
02532 return NULL;
02533 }
02534 type = get_token(fp, token, MAXTOKEN);
02535 if (type != MANDATORY && type != CURRENT && type != KW_OPTIONAL &&
02536 type != OBSOLETE && type != DEPRECATED) {
02537 print_error("Bad STATUS", token, type);
02538 free_node(np);
02539 return NULL;
02540 }
02541 np->status = type;
02542
02543
02544
02545 type = get_token(fp, token, MAXTOKEN);
02546 while (type != EQUALS && type != ENDOFFILE) {
02547 switch (type) {
02548 case DESCRIPTION:
02549 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02550
02551 if (type != QUOTESTRING) {
02552 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
02553 free_node(np);
02554 return NULL;
02555 }
02556 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
02557 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
02558 np->description = strdup(quoted_string_buffer);
02559 }
02560 break;
02561
02562 case REFERENCE:
02563 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02564 if (type != QUOTESTRING) {
02565 print_error("Bad REFERENCE", quoted_string_buffer, type);
02566 free_node(np);
02567 return NULL;
02568 }
02569 np->reference = strdup(quoted_string_buffer);
02570 break;
02571 case INDEX:
02572 if (np->augments) {
02573 print_error("Cannot have both INDEX and AUGMENTS", token,
02574 type);
02575 free_node(np);
02576 return NULL;
02577 }
02578 np->indexes = getIndexes(fp, &np->indexes);
02579 if (np->indexes == NULL) {
02580 print_error("Bad INDEX list", token, type);
02581 free_node(np);
02582 return NULL;
02583 }
02584 break;
02585 case AUGMENTS:
02586 if (np->indexes) {
02587 print_error("Cannot have both INDEX and AUGMENTS", token,
02588 type);
02589 free_node(np);
02590 return NULL;
02591 }
02592 np->indexes = getIndexes(fp, &np->indexes);
02593 if (np->indexes == NULL) {
02594 print_error("Bad AUGMENTS list", token, type);
02595 free_node(np);
02596 return NULL;
02597 }
02598 np->augments = strdup(np->indexes->ilabel);
02599 free_indexes(&np->indexes);
02600 break;
02601 case DEFVAL:
02602
02603
02604
02605 type = get_token(fp, quoted_string_buffer, MAXTOKEN);
02606 if (type != LEFTBRACKET) {
02607 print_error("Bad DEFAULTVALUE", quoted_string_buffer,
02608 type);
02609 free_node(np);
02610 return NULL;
02611 }
02612
02613 {
02614 int level = 1;
02615 char defbuf[512];
02616
02617 defbuf[0] = 0;
02618 while (1) {
02619 type = get_token(fp, quoted_string_buffer, MAXTOKEN);
02620 if ((type == RIGHTBRACKET && --level == 0)
02621 || type == ENDOFFILE)
02622 break;
02623 else if (type == LEFTBRACKET)
02624 level++;
02625 if (type == QUOTESTRING) {
02626 if (strlen(defbuf)+2 < sizeof(defbuf)) {
02627 defbuf[ strlen(defbuf)+2 ] = 0;
02628 defbuf[ strlen(defbuf)+1 ] = '"';
02629 defbuf[ strlen(defbuf) ] = '\\';
02630 }
02631 defbuf[ sizeof(defbuf)-1 ] = 0;
02632 }
02633 strncat(defbuf, quoted_string_buffer,
02634 sizeof(defbuf)-strlen(defbuf));
02635 defbuf[ sizeof(defbuf)-1 ] = 0;
02636 if (type == QUOTESTRING) {
02637 if (strlen(defbuf)+2 < sizeof(defbuf)) {
02638 defbuf[ strlen(defbuf)+2 ] = 0;
02639 defbuf[ strlen(defbuf)+1 ] = '"';
02640 defbuf[ strlen(defbuf) ] = '\\';
02641 }
02642 defbuf[ sizeof(defbuf)-1 ] = 0;
02643 }
02644 if (strlen(defbuf)+1 < sizeof(defbuf)) {
02645 defbuf[ strlen(defbuf)+1 ] = 0;
02646 defbuf[ strlen(defbuf) ] = ' ';
02647 }
02648 }
02649
02650 if (type != RIGHTBRACKET) {
02651 print_error("Bad DEFAULTVALUE", quoted_string_buffer,
02652 type);
02653 free_node(np);
02654 return NULL;
02655 }
02656
02657 defbuf[strlen(defbuf) - 1] = 0;
02658 np->defaultValue = strdup(defbuf);
02659 }
02660
02661 break;
02662
02663 case NUM_ENTRIES:
02664 if (tossObjectIdentifier(fp) != OBJID) {
02665 print_error("Bad Object Identifier", token, type);
02666 free_node(np);
02667 return NULL;
02668 }
02669 break;
02670
02671 default:
02672 print_error("Bad format of optional clauses", token, type);
02673 free_node(np);
02674 return NULL;
02675
02676 }
02677 type = get_token(fp, token, MAXTOKEN);
02678 }
02679 if (type != EQUALS) {
02680 print_error("Bad format", token, type);
02681 free_node(np);
02682 return NULL;
02683 }
02684 return merge_parse_objectid(np, fp, name);
02685 }
02686
02687
02688
02689
02690
02691
02692
02693
02694 static struct node *
02695 parse_objectgroup(FILE * fp, char *name, int what, struct objgroup **ol)
02696 {
02697 int type;
02698 char token[MAXTOKEN];
02699 char quoted_string_buffer[MAXQUOTESTR];
02700 struct node *np;
02701
02702 np = alloc_node(current_module);
02703 if (np == NULL)
02704 return (NULL);
02705 type = get_token(fp, token, MAXTOKEN);
02706 if (type == what) {
02707 type = get_token(fp, token, MAXTOKEN);
02708 if (type != LEFTBRACKET) {
02709 print_error("Expected \"{\"", token, type);
02710 goto skip;
02711 }
02712 do {
02713 struct objgroup *o;
02714 type = get_token(fp, token, MAXTOKEN);
02715 if (type != LABEL) {
02716 print_error("Bad identifier", token, type);
02717 goto skip;
02718 }
02719 o = (struct objgroup *) malloc(sizeof(struct objgroup));
02720 if (!o) {
02721 print_error("Resource failure", token, type);
02722 goto skip;
02723 }
02724 o->line = mibLine;
02725 o->name = strdup(token);
02726 o->next = *ol;
02727 *ol = o;
02728 type = get_token(fp, token, MAXTOKEN);
02729 } while (type == COMMA);
02730 if (type != RIGHTBRACKET) {
02731 print_error("Expected \"}\" after list", token, type);
02732 goto skip;
02733 }
02734 type = get_token(fp, token, type);
02735 }
02736 if (type != STATUS) {
02737 print_error("Expected STATUS", token, type);
02738 goto skip;
02739 }
02740 type = get_token(fp, token, MAXTOKEN);
02741 if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
02742 print_error("Bad STATUS value", token, type);
02743 goto skip;
02744 }
02745 type = get_token(fp, token, MAXTOKEN);
02746 if (type != DESCRIPTION) {
02747 print_error("Expected DESCRIPTION", token, type);
02748 goto skip;
02749 }
02750 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02751 if (type != QUOTESTRING) {
02752 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
02753 free_node(np);
02754 return NULL;
02755 }
02756 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
02757 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
02758 np->description = strdup(quoted_string_buffer);
02759 }
02760 type = get_token(fp, token, MAXTOKEN);
02761 if (type == REFERENCE) {
02762 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02763 if (type != QUOTESTRING) {
02764 print_error("Bad REFERENCE", quoted_string_buffer, type);
02765 free_node(np);
02766 return NULL;
02767 }
02768 np->reference = strdup(quoted_string_buffer);
02769 type = get_token(fp, token, MAXTOKEN);
02770 }
02771 if (type != EQUALS)
02772 print_error("Expected \"::=\"", token, type);
02773 skip:
02774 while (type != EQUALS && type != ENDOFFILE)
02775 type = get_token(fp, token, MAXTOKEN);
02776
02777 return merge_parse_objectid(np, fp, name);
02778 }
02779
02780
02781
02782
02783
02784 static struct node *
02785 parse_notificationDefinition(FILE * fp, char *name)
02786 {
02787 register int type;
02788 char token[MAXTOKEN];
02789 char quoted_string_buffer[MAXQUOTESTR];
02790 register struct node *np;
02791
02792 np = alloc_node(current_module);
02793 if (np == NULL)
02794 return (NULL);
02795 type = get_token(fp, token, MAXTOKEN);
02796 while (type != EQUALS && type != ENDOFFILE) {
02797 switch (type) {
02798 case DESCRIPTION:
02799 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02800 if (type != QUOTESTRING) {
02801 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
02802 free_node(np);
02803 return NULL;
02804 }
02805 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
02806 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
02807 np->description = strdup(quoted_string_buffer);
02808 }
02809 break;
02810 case REFERENCE:
02811 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02812 if (type != QUOTESTRING) {
02813 print_error("Bad REFERENCE", quoted_string_buffer, type);
02814 free_node(np);
02815 return NULL;
02816 }
02817 np->reference = strdup(quoted_string_buffer);
02818 break;
02819 case OBJECTS:
02820 np->varbinds = getVarbinds(fp, &np->varbinds);
02821 if (!np->varbinds) {
02822 print_error("Bad OBJECTS list", token, type);
02823 free_node(np);
02824 return NULL;
02825 }
02826 break;
02827 default:
02828
02829
02830
02831 break;
02832 }
02833 type = get_token(fp, token, MAXTOKEN);
02834 }
02835 return merge_parse_objectid(np, fp, name);
02836 }
02837
02838
02839
02840
02841
02842 static struct node *
02843 parse_trapDefinition(FILE * fp, char *name)
02844 {
02845 register int type;
02846 char token[MAXTOKEN];
02847 char quoted_string_buffer[MAXQUOTESTR];
02848 register struct node *np;
02849
02850 np = alloc_node(current_module);
02851 if (np == NULL)
02852 return (NULL);
02853 type = get_token(fp, token, MAXTOKEN);
02854 while (type != EQUALS && type != ENDOFFILE) {
02855 switch (type) {
02856 case DESCRIPTION:
02857 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02858 if (type != QUOTESTRING) {
02859 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
02860 free_node(np);
02861 return NULL;
02862 }
02863 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
02864 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
02865 np->description = strdup(quoted_string_buffer);
02866 }
02867 break;
02868 case REFERENCE:
02869
02870 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
02871 if (type != QUOTESTRING) {
02872 print_error("Bad REFERENCE", quoted_string_buffer, type);
02873 free_node(np);
02874 return NULL;
02875 }
02876 np->reference = strdup(quoted_string_buffer);
02877 break;
02878 case ENTERPRISE:
02879 type = get_token(fp, token, MAXTOKEN);
02880 if (type == LEFTBRACKET) {
02881 type = get_token(fp, token, MAXTOKEN);
02882 if (type != LABEL) {
02883 print_error("Bad Trap Format", token, type);
02884 free_node(np);
02885 return NULL;
02886 }
02887 np->parent = strdup(token);
02888
02889
02890
02891 type = get_token(fp, token, MAXTOKEN);
02892 } else if (type == LABEL)
02893 np->parent = strdup(token);
02894 break;
02895 case VARIABLES:
02896 np->varbinds = getVarbinds(fp, &np->varbinds);
02897 if (!np->varbinds) {
02898 print_error("Bad VARIABLES list", token, type);
02899 free_node(np);
02900 return NULL;
02901 }
02902 break;
02903 default:
02904
02905
02906
02907 break;
02908 }
02909 type = get_token(fp, token, MAXTOKEN);
02910 }
02911 type = get_token(fp, token, MAXTOKEN);
02912
02913 np->label = strdup(name);
02914
02915 if (type != NUMBER) {
02916 print_error("Expected a Number", token, type);
02917 free_node(np);
02918 return NULL;
02919 }
02920 np->subid = strtoul(token, NULL, 10);
02921 np->next = alloc_node(current_module);
02922 if (np->next == NULL) {
02923 free_node(np);
02924 return (NULL);
02925 }
02926 np->next->parent = np->parent;
02927 np->parent = (char *) malloc(strlen(np->parent) + 2);
02928 if (np->parent == NULL) {
02929 free_node(np->next);
02930 free_node(np);
02931 return (NULL);
02932 }
02933 strcpy(np->parent, np->next->parent);
02934 strcat(np->parent, "#");
02935 np->next->label = strdup(np->parent);
02936 return np;
02937 }
02938
02939
02940
02941
02942
02943
02944 static int
02945 eat_syntax(FILE * fp, char *token, int maxtoken)
02946 {
02947 int type, nexttype;
02948 struct node *np = alloc_node(current_module);
02949 char nexttoken[MAXTOKEN];
02950
02951 type = get_token(fp, token, maxtoken);
02952 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02953 switch (type) {
02954 case INTEGER:
02955 case INTEGER32:
02956 case UINTEGER32:
02957 case UNSIGNED32:
02958 case COUNTER:
02959 case GAUGE:
02960 case BITSTRING:
02961 case LABEL:
02962 if (nexttype == LEFTBRACKET) {
02963
02964
02965
02966 np->enums = parse_enumlist(fp, &np->enums);
02967 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02968 } else if (nexttype == LEFTPAREN) {
02969
02970
02971
02972 np->ranges = parse_ranges(fp, &np->ranges);
02973 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02974 }
02975 break;
02976 case OCTETSTR:
02977 case KW_OPAQUE:
02978
02979
02980
02981 if (nexttype == LEFTPAREN) {
02982 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02983 if (nexttype == SIZE) {
02984 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02985 if (nexttype == LEFTPAREN) {
02986 np->ranges = parse_ranges(fp, &np->ranges);
02987 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02988 if (nexttype == RIGHTPAREN) {
02989 nexttype = get_token(fp, nexttoken, MAXTOKEN);
02990 break;
02991 }
02992 }
02993 }
02994 print_error("Bad SIZE syntax", token, type);
02995 free_node(np);
02996 return nexttype;
02997 }
02998 break;
02999 case OBJID:
03000 case NETADDR:
03001 case IPADDR:
03002 case TIMETICKS:
03003 case NUL:
03004 case NSAPADDRESS:
03005 case COUNTER64:
03006 break;
03007 default:
03008 print_error("Bad syntax", token, type);
03009 free_node(np);
03010 return nexttype;
03011 }
03012 free_node(np);
03013 return nexttype;
03014 }
03015
03016 static int
03017 compliance_lookup(const char *name, int modid)
03018 {
03019 if (modid == -1) {
03020 struct objgroup *op =
03021 (struct objgroup *) malloc(sizeof(struct objgroup));
03022 if (!op)
03023 return 0;
03024 op->next = objgroups;
03025 op->name = strdup(name);
03026 op->line = mibLine;
03027 objgroups = op;
03028 return 1;
03029 } else
03030 return find_tree_node(name, modid) != NULL;
03031 }
03032
03033 static struct node *
03034 parse_compliance(FILE * fp, char *name)
03035 {
03036 int type;
03037 char token[MAXTOKEN];
03038 char quoted_string_buffer[MAXQUOTESTR];
03039 struct node *np;
03040
03041 np = alloc_node(current_module);
03042 if (np == NULL)
03043 return (NULL);
03044 type = get_token(fp, token, MAXTOKEN);
03045 if (type != STATUS) {
03046 print_error("Expected STATUS", token, type);
03047 goto skip;
03048 }
03049 type = get_token(fp, token, MAXTOKEN);
03050 if (type != CURRENT && type != DEPRECATED && type != OBSOLETE) {
03051 print_error("Bad STATUS", token, type);
03052 goto skip;
03053 }
03054 type = get_token(fp, token, MAXTOKEN);
03055 if (type != DESCRIPTION) {
03056 print_error("Expected DESCRIPTION", token, type);
03057 goto skip;
03058 }
03059 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03060 if (type != QUOTESTRING) {
03061 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
03062 goto skip;
03063 }
03064 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
03065 NETSNMP_DS_LIB_SAVE_MIB_DESCRS))
03066 np->description = strdup(quoted_string_buffer);
03067 type = get_token(fp, token, MAXTOKEN);
03068 if (type == REFERENCE) {
03069 type = get_token(fp, quoted_string_buffer, MAXTOKEN);
03070 if (type != QUOTESTRING) {
03071 print_error("Bad REFERENCE", quoted_string_buffer, type);
03072 goto skip;
03073 }
03074 np->reference = strdup(quoted_string_buffer);
03075 type = get_token(fp, token, MAXTOKEN);
03076 }
03077 if (type != MODULE) {
03078 print_error("Expected MODULE", token, type);
03079 goto skip;
03080 }
03081 while (type == MODULE) {
03082 int modid = -1;
03083 char modname[MAXTOKEN];
03084 type = get_token(fp, token, MAXTOKEN);
03085 if (type == LABEL
03086 && strcmp(token, module_name(current_module, modname))) {
03087 modid = read_module_internal(token);
03088 if (modid != MODULE_LOADED_OK
03089 && modid != MODULE_ALREADY_LOADED) {
03090 print_error("Unknown module", token, type);
03091 goto skip;
03092 }
03093 modid = which_module(token);
03094 type = get_token(fp, token, MAXTOKEN);
03095 }
03096 if (type == MANDATORYGROUPS) {
03097 type = get_token(fp, token, MAXTOKEN);
03098 if (type != LEFTBRACKET) {
03099 print_error("Expected \"{\"", token, type);
03100 goto skip;
03101 }
03102 do {
03103 type = get_token(fp, token, MAXTOKEN);
03104 if (type != LABEL) {
03105 print_error("Bad group name", token, type);
03106 goto skip;
03107 }
03108 if (!compliance_lookup(token, modid))
03109 print_error("Unknown group", token, type);
03110 type = get_token(fp, token, MAXTOKEN);
03111 } while (type == COMMA);
03112 if (type != RIGHTBRACKET) {
03113 print_error("Expected \"}\"", token, type);
03114 goto skip;
03115 }
03116 type = get_token(fp, token, MAXTOKEN);
03117 }
03118 while (type == GROUP || type == OBJECT) {
03119 if (type == GROUP) {
03120 type = get_token(fp, token, MAXTOKEN);
03121 if (type != LABEL) {
03122 print_error("Bad group name", token, type);
03123 goto skip;
03124 }
03125 if (!compliance_lookup(token, modid))
03126 print_error("Unknown group", token, type);
03127 type = get_token(fp, token, MAXTOKEN);
03128 } else {
03129 type = get_token(fp, token, MAXTOKEN);
03130 if (type != LABEL) {
03131 print_error("Bad object name", token, type);
03132 goto skip;
03133 }
03134 if (!compliance_lookup(token, modid))
03135 print_error("Unknown group", token, type);
03136 type = get_token(fp, token, MAXTOKEN);
03137 if (type == SYNTAX)
03138 type = eat_syntax(fp, token, MAXTOKEN);
03139 if (type == WRSYNTAX)
03140 type = eat_syntax(fp, token, MAXTOKEN);
03141 if (type == MINACCESS) {
03142 type = get_token(fp, token, MAXTOKEN);
03143 if (type != NOACCESS && type != ACCNOTIFY
03144 && type != READONLY && type != WRITEONLY
03145 && type != READCREATE && type != READWRITE) {
03146 print_error("Bad MIN-ACCESS spec", token, type);
03147 goto skip;
03148 }
03149 type = get_token(fp, token, MAXTOKEN);
03150 }
03151 }
03152 if (type != DESCRIPTION) {
03153 print_error("Expected DESCRIPTION", token, type);
03154 goto skip;
03155 }
03156 type = get_token(fp, token, MAXTOKEN);
03157 if (type != QUOTESTRING) {
03158 print_error("Bad DESCRIPTION", token, type);
03159 goto skip;
03160 }
03161 type = get_token(fp, token, MAXTOKEN);
03162 }
03163 }
03164 skip:
03165 while (type != EQUALS && type != ENDOFFILE)
03166 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03167
03168 return merge_parse_objectid(np, fp, name);
03169 }
03170
03171
03172
03173
03174
03175
03176 static struct node *
03177 parse_capabilities(FILE * fp, char *name)
03178 {
03179 int type;
03180 char token[MAXTOKEN];
03181 char quoted_string_buffer[MAXQUOTESTR];
03182 struct node *np;
03183
03184 np = alloc_node(current_module);
03185 if (np == NULL)
03186 return (NULL);
03187 type = get_token(fp, token, MAXTOKEN);
03188 if (type != PRODREL) {
03189 print_error("Expected PRODUCT-RELEASE", token, type);
03190 goto skip;
03191 }
03192 type = get_token(fp, token, MAXTOKEN);
03193 if (type != QUOTESTRING) {
03194 print_error("Expected STRING after PRODUCT-RELEASE", token, type);
03195 goto skip;
03196 }
03197 type = get_token(fp, token, MAXTOKEN);
03198 if (type != STATUS) {
03199 print_error("Expected STATUS", token, type);
03200 goto skip;
03201 }
03202 type = get_token(fp, token, MAXTOKEN);
03203 if (type != CURRENT && type != OBSOLETE) {
03204 print_error("STATUS should be current or obsolete", token, type);
03205 goto skip;
03206 }
03207 type = get_token(fp, token, MAXTOKEN);
03208 if (type != DESCRIPTION) {
03209 print_error("Expected DESCRIPTION", token, type);
03210 goto skip;
03211 }
03212 type = get_token(fp, token, MAXTOKEN);
03213 if (type != QUOTESTRING) {
03214 print_error("Bad DESCRIPTION", token, type);
03215 goto skip;
03216 }
03217 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
03218 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
03219 np->description = strdup(token);
03220 }
03221 type = get_token(fp, token, MAXTOKEN);
03222 if (type == REFERENCE) {
03223 type = get_token(fp, token, MAXTOKEN);
03224 if (type != QUOTESTRING) {
03225 print_error("Bad REFERENCE", token, type);
03226 goto skip;
03227 }
03228 np->reference = strdup(token);
03229 type = get_token(fp, token, type);
03230 }
03231 while (type == SUPPORTS) {
03232 int modid;
03233 struct tree *tp;
03234
03235 type = get_token(fp, token, MAXTOKEN);
03236 if (type != LABEL) {
03237 print_error("Bad module name", token, type);
03238 goto skip;
03239 }
03240 modid = read_module_internal(token);
03241 if (modid != MODULE_LOADED_OK && modid != MODULE_ALREADY_LOADED) {
03242 print_error("Module not found", token, type);
03243 goto skip;
03244 }
03245 modid = which_module(token);
03246 type = get_token(fp, token, MAXTOKEN);
03247 if (type != INCLUDES) {
03248 print_error("Expected INCLUDES", token, type);
03249 goto skip;
03250 }
03251 type = get_token(fp, token, MAXTOKEN);
03252 if (type != LEFTBRACKET) {
03253 print_error("Expected \"{\"", token, type);
03254 goto skip;
03255 }
03256 do {
03257 type = get_token(fp, token, MAXTOKEN);
03258 if (type != LABEL) {
03259 print_error("Expected group name", token, type);
03260 goto skip;
03261 }
03262 tp = find_tree_node(token, modid);
03263 if (!tp)
03264 print_error("Group not found in module", token, type);
03265 type = get_token(fp, token, MAXTOKEN);
03266 } while (type == COMMA);
03267 if (type != RIGHTBRACKET) {
03268 print_error("Expected \"}\" after group list", token, type);
03269 goto skip;
03270 }
03271 type = get_token(fp, token, MAXTOKEN);
03272 while (type == VARIATION) {
03273 type = get_token(fp, token, MAXTOKEN);
03274 if (type != LABEL) {
03275 print_error("Bad object name", token, type);
03276 goto skip;
03277 }
03278 tp = find_tree_node(token, modid);
03279 if (!tp)
03280 print_error("Object not found in module", token, type);
03281 type = get_token(fp, token, MAXTOKEN);
03282 if (type == SYNTAX) {
03283 type = eat_syntax(fp, token, MAXTOKEN);
03284 }
03285 if (type == WRSYNTAX) {
03286 type = eat_syntax(fp, token, MAXTOKEN);
03287 }
03288 if (type == ACCESS) {
03289 type = get_token(fp, token, MAXTOKEN);
03290 if (type != ACCNOTIFY && type != READONLY
03291 && type != READWRITE && type != READCREATE
03292 && type != WRITEONLY && type != NOTIMPL) {
03293 print_error("Bad ACCESS", token, type);
03294 goto skip;
03295 }
03296 type = get_token(fp, token, MAXTOKEN);
03297 }
03298 if (type == CREATEREQ) {
03299 type = get_token(fp, token, MAXTOKEN);
03300 if (type != LEFTBRACKET) {
03301 print_error("Expected \"{\"", token, type);
03302 goto skip;
03303 }
03304 do {
03305 type = get_token(fp, token, MAXTOKEN);
03306 if (type != LABEL) {
03307 print_error("Bad object name in list", token,
03308 type);
03309 goto skip;
03310 }
03311 type = get_token(fp, token, MAXTOKEN);
03312 } while (type == COMMA);
03313 if (type != RIGHTBRACKET) {
03314 print_error("Expected \"}\" after list", token, type);
03315 goto skip;
03316 }
03317 type = get_token(fp, token, MAXTOKEN);
03318 }
03319 if (type == DEFVAL) {
03320 int level = 1;
03321 type = get_token(fp, token, MAXTOKEN);
03322 if (type != LEFTBRACKET) {
03323 print_error("Expected \"{\" after DEFVAL", token,
03324 type);
03325 goto skip;
03326 }
03327 do {
03328 type = get_token(fp, token, MAXTOKEN);
03329 if (type == LEFTBRACKET)
03330 level++;
03331 else if (type == RIGHTBRACKET)
03332 level--;
03333 } while (type != RIGHTBRACKET && type != ENDOFFILE
03334 && level != 0);
03335 if (type != RIGHTBRACKET) {
03336 print_error("Missing \"}\" after DEFVAL", token, type);
03337 goto skip;
03338 }
03339 type = get_token(fp, token, MAXTOKEN);
03340 }
03341 if (type != DESCRIPTION) {
03342 print_error("Expected DESCRIPTION", token, type);
03343 goto skip;
03344 }
03345 type = get_token(fp, token, MAXTOKEN);
03346 if (type != QUOTESTRING) {
03347 print_error("Bad DESCRIPTION", token, type);
03348 goto skip;
03349 }
03350 type = get_token(fp, token, MAXTOKEN);
03351 }
03352 }
03353 if (type != EQUALS)
03354 print_error("Expected \"::=\"", token, type);
03355 skip:
03356 while (type != EQUALS && type != ENDOFFILE) {
03357 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03358 }
03359 return merge_parse_objectid(np, fp, name);
03360 }
03361
03362
03363
03364
03365
03366 static void
03367 check_utc(const char *utc)
03368 {
03369 int len, year, month, day, hour, minute;
03370
03371 len = strlen(utc);
03372 if (utc[len - 1] != 'Z' && utc[len - 1] != 'z') {
03373 print_error("Timestamp should end with Z", utc, QUOTESTRING);
03374 return;
03375 }
03376 if (len == 11) {
03377 len =
03378 sscanf(utc, "%2d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
03379 &minute);
03380 year += 1900;
03381 } else if (len == 13)
03382 len =
03383 sscanf(utc, "%4d%2d%2d%2d%2dZ", &year, &month, &day, &hour,
03384 &minute);
03385 else {
03386 print_error("Bad timestamp format (11 or 13 characters)",
03387 utc, QUOTESTRING);
03388 return;
03389 }
03390 if (len != 5) {
03391 print_error("Bad timestamp format", utc, QUOTESTRING);
03392 return;
03393 }
03394 if (month < 1 || month > 12)
03395 print_error("Bad month in timestamp", utc, QUOTESTRING);
03396 if (day < 1 || day > 31)
03397 print_error("Bad day in timestamp", utc, QUOTESTRING);
03398 if (hour < 0 || hour > 23)
03399 print_error("Bad hour in timestamp", utc, QUOTESTRING);
03400 if (minute < 0 || minute > 59)
03401 print_error("Bad minute in timestamp", utc, QUOTESTRING);
03402 }
03403
03404 static struct node *
03405 parse_moduleIdentity(FILE * fp, char *name)
03406 {
03407 register int type;
03408 char token[MAXTOKEN];
03409 char quoted_string_buffer[MAXQUOTESTR];
03410 register struct node *np;
03411
03412 np = alloc_node(current_module);
03413 if (np == NULL)
03414 return (NULL);
03415 type = get_token(fp, token, MAXTOKEN);
03416 if (type != LASTUPDATED) {
03417 print_error("Expected LAST-UPDATED", token, type);
03418 goto skip;
03419 }
03420 type = get_token(fp, token, MAXTOKEN);
03421 if (type != QUOTESTRING) {
03422 print_error("Need STRING for LAST-UPDATED", token, type);
03423 goto skip;
03424 }
03425 check_utc(token);
03426 type = get_token(fp, token, MAXTOKEN);
03427 if (type != ORGANIZATION) {
03428 print_error("Expected ORGANIZATION", token, type);
03429 goto skip;
03430 }
03431 type = get_token(fp, token, MAXTOKEN);
03432 if (type != QUOTESTRING) {
03433 print_error("Bad ORGANIZATION", token, type);
03434 goto skip;
03435 }
03436 type = get_token(fp, token, MAXTOKEN);
03437 if (type != CONTACTINFO) {
03438 print_error("Expected CONTACT-INFO", token, type);
03439 goto skip;
03440 }
03441 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03442 if (type != QUOTESTRING) {
03443 print_error("Bad CONTACT-INFO", quoted_string_buffer, type);
03444 goto skip;
03445 }
03446 type = get_token(fp, token, MAXTOKEN);
03447 if (type != DESCRIPTION) {
03448 print_error("Expected DESCRIPTION", token, type);
03449 goto skip;
03450 }
03451 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03452 if (type != QUOTESTRING) {
03453 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
03454 goto skip;
03455 }
03456 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
03457 NETSNMP_DS_LIB_SAVE_MIB_DESCRS)) {
03458 np->description = strdup(quoted_string_buffer);
03459 }
03460 type = get_token(fp, token, MAXTOKEN);
03461 while (type == REVISION) {
03462 type = get_token(fp, token, MAXTOKEN);
03463 if (type != QUOTESTRING) {
03464 print_error("Bad REVISION", token, type);
03465 goto skip;
03466 }
03467 check_utc(token);
03468 type = get_token(fp, token, MAXTOKEN);
03469 if (type != DESCRIPTION) {
03470 print_error("Expected DESCRIPTION", token, type);
03471 goto skip;
03472 }
03473 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03474 if (type != QUOTESTRING) {
03475 print_error("Bad DESCRIPTION", quoted_string_buffer, type);
03476 goto skip;
03477 }
03478 type = get_token(fp, token, MAXTOKEN);
03479 }
03480 if (type != EQUALS)
03481 print_error("Expected \"::=\"", token, type);
03482 skip:
03483 while (type != EQUALS && type != ENDOFFILE) {
03484 type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
03485 }
03486 return merge_parse_objectid(np, fp, name);
03487 }
03488
03489
03490
03491
03492
03493
03494
03495 static struct node *
03496 parse_macro(FILE * fp, char *name)
03497 {
03498 register int type;
03499 char token[MAXTOKEN];
03500 struct node *np;
03501 int iLine = mibLine;
03502
03503 np = alloc_node(current_module);
03504 if (np == NULL)
03505 return (NULL);
03506 type = get_token(fp, token, sizeof(token));
03507 while (type != EQUALS && type != ENDOFFILE) {
03508 type = get_token(fp, token, sizeof(token));
03509 }
03510 if (type != EQUALS) {
03511 if (np)
03512 free_node(np);
03513 return NULL;
03514 }
03515 while (type != BEGIN && type != ENDOFFILE) {
03516 type = get_token(fp, token, sizeof(token));
03517 }
03518 if (type != BEGIN) {
03519 if (np)
03520 free_node(np);
03521 return NULL;
03522 }
03523 while (type != END && type != ENDOFFILE) {
03524 type = get_token(fp, token, sizeof(token));
03525 }
03526 if (type != END) {
03527 if (np)
03528 free_node(np);
03529 return NULL;
03530 }
03531
03532 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
03533 NETSNMP_DS_LIB_MIB_WARNINGS)) {
03534 snmp_log(LOG_WARNING,
03535 "%s MACRO (lines %d..%d parsed and ignored).\n", name,
03536 iLine, mibLine);
03537 }
03538
03539 return np;
03540 }
03541
03542
03543
03544
03545
03546 static void
03547 parse_imports(FILE * fp)
03548 {
03549 register int type;
03550 char token[MAXTOKEN];
03551 char modbuf[256];
03552 #define MAX_IMPORTS 256
03553 struct module_import import_list[MAX_IMPORTS];
03554 int this_module;
03555 struct module *mp;
03556
03557 int import_count = 0;
03558 int i = 0, old_i;
03559
03560 type = get_token(fp, token, MAXTOKEN);
03561
03562
03563
03564
03565 while (type != SEMI && type != ENDOFFILE) {
03566 if (type == LABEL) {
03567 if (import_count == MAX_IMPORTS) {
03568 print_error("Too many imported symbols", token, type);
03569 do {
03570 type = get_token(fp, token, MAXTOKEN);
03571 } while (type != SEMI && type != ENDOFFILE);
03572 return;
03573 }
03574 import_list[import_count++].label = strdup(token);
03575 } else if (type == FROM) {
03576 type = get_token(fp, token, MAXTOKEN);
03577 if (import_count == i) {
03578 type = get_token(fp, token, MAXTOKEN);
03579 continue;
03580 }
03581 this_module = which_module(token);
03582
03583 for (old_i = i; i < import_count; ++i)
03584 import_list[i].modid = this_module;
03585
03586
03587
03588
03589 if (read_module_internal(token) == MODULE_NOT_FOUND) {
03590 int found = 0;
03591 for (; old_i < import_count; ++old_i) {
03592 found += read_import_replacements(token, &import_list[old_i]);
03593 }
03594 if (!found)
03595 print_module_not_found(token);
03596 }
03597 }
03598 type = get_token(fp, token, MAXTOKEN);
03599 }
03600
03601
03602
03603
03604
03605 for (mp = module_head; mp; mp = mp->next)
03606 if (mp->modid == current_module) {
03607 if (import_count == 0)
03608 return;
03609 if (mp->imports && (mp->imports != root_imports)) {
03610
03611
03612
03613 for (i = 0; i < mp->no_imports; ++i) {
03614 DEBUGMSGTL(("parse-mibs",
03615 "#### freeing Module %d '%s' %d\n",
03616 mp->modid, mp->imports[i].label,
03617 mp->imports[i].modid));
03618 free((char *) mp->imports[i].label);
03619 }
03620 free((char *) mp->imports);
03621 }
03622 mp->imports = (struct module_import *)
03623 calloc(import_count, sizeof(struct module_import));
03624 if (mp->imports == NULL)
03625 return;
03626 for (i = 0; i < import_count; ++i) {
03627 mp->imports[i].label = import_list[i].label;
03628 mp->imports[i].modid = import_list[i].modid;
03629 DEBUGMSGTL(("parse-mibs",
03630 "#### adding Module %d '%s' %d\n", mp->modid,
03631 mp->imports[i].label, mp->imports[i].modid));
03632 }
03633 mp->no_imports = import_count;
03634 return;
03635 }
03636
03637
03638
03639
03640 print_module_not_found(module_name(current_module, modbuf));
03641 return;
03642 }
03643
03644
03645
03646
03647
03648
03649
03650 static void
03651 dump_module_list(void)
03652 {
03653 struct module *mp = module_head;
03654
03655 DEBUGMSGTL(("parse-mibs", "Module list:\n"));
03656 while (mp) {
03657 DEBUGMSGTL(("parse-mibs", " %s %d %s %d\n", mp->name, mp->modid,
03658 mp->file, mp->no_imports));
03659 mp = mp->next;
03660 }
03661 }
03662
03663 int
03664 which_module(const char *name)
03665 {
03666 struct module *mp;
03667
03668 for (mp = module_head; mp; mp = mp->next)
03669 if (!label_compare(mp->name, name))
03670 return (mp->modid);
03671
03672 DEBUGMSGTL(("parse-mibs", "Module %s not found\n", name));
03673 return (-1);
03674 }
03675
03676
03677
03678
03679 char *
03680 module_name(int modid, char *cp)
03681 {
03682 struct module *mp;
03683
03684 for (mp = module_head; mp; mp = mp->next)
03685 if (mp->modid == modid) {
03686 strcpy(cp, mp->name);
03687 return (cp);
03688 }
03689
03690 if (modid != -1) DEBUGMSGTL(("parse-mibs", "Module %d not found\n", modid));
03691 sprintf(cp, "#%d", modid);
03692 return (cp);
03693 }
03694
03695
03696
03697
03698
03699
03700
03701
03702 void
03703 add_module_replacement(const char *old_module,
03704 const char *new_module_name,
03705 const char *tag, int len)
03706 {
03707 struct module_compatability *mcp;
03708
03709 mcp = (struct module_compatability *)
03710 calloc(1, sizeof(struct module_compatability));
03711 if (mcp == NULL)
03712 return;
03713
03714 mcp->old_module = strdup(old_module);
03715 mcp->new_module = strdup(new_module_name);
03716 if (tag)
03717 mcp->tag = strdup(tag);
03718 mcp->tag_len = len;
03719
03720 mcp->next = module_map_head;
03721 module_map_head = mcp;
03722 }
03723
03724 static int
03725 read_module_replacements(const char *name)
03726 {
03727 struct module_compatability *mcp;
03728
03729 for (mcp = module_map_head; mcp; mcp = mcp->next) {
03730 if (!label_compare(mcp->old_module, name)) {
03731 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
03732 NETSNMP_DS_LIB_MIB_WARNINGS)) {
03733 snmp_log(LOG_WARNING,
03734 "Loading replacement module %s for %s (%s)\n",
03735 mcp->new_module, name, File);
03736 }
03737 (void) netsnmp_read_module(mcp->new_module);
03738 return 1;
03739 }
03740 }
03741 return 0;
03742 }
03743
03744 static int
03745 read_import_replacements(const char *old_module_name,
03746 struct module_import *identifier)
03747 {
03748 struct module_compatability *mcp;
03749
03750
03751
03752
03753 for (mcp = module_map_head; mcp; mcp = mcp->next) {
03754 if (!label_compare(mcp->old_module, old_module_name)) {
03755
03756 if (
03757 (mcp->tag_len == 0 &&
03758 (mcp->tag == NULL ||
03759 !label_compare(mcp->tag, identifier->label))) ||
03760
03761
03762
03763 (mcp->tag_len != 0 &&
03764 !strncmp(mcp->tag, identifier->label, mcp->tag_len))
03765 ) {
03766
03767 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
03768 NETSNMP_DS_LIB_MIB_WARNINGS)) {
03769 snmp_log(LOG_WARNING,
03770 "Importing %s from replacement module %s instead of %s (%s)\n",
03771 identifier->label, mcp->new_module,
03772 old_module_name, File);
03773 }
03774 (void) netsnmp_read_module(mcp->new_module);
03775 identifier->modid = which_module(mcp->new_module);
03776 return 1;
03777 }
03778 }
03779 }
03780
03781
03782
03783
03784 return read_module_replacements(old_module_name);
03785 }
03786
03787
03788
03789
03790
03791
03792
03793 static int
03794 read_module_internal(const char *name)
03795 {
03796 struct module *mp;
03797 FILE *fp;
03798 struct node *np;
03799
03800 netsnmp_init_mib_internals();
03801
03802 for (mp = module_head; mp; mp = mp->next)
03803 if (!label_compare(mp->name, name)) {
03804 const char *oldFile = File;
03805 int oldLine = mibLine;
03806 int oldModule = current_module;
03807
03808 if (mp->no_imports != -1) {
03809 DEBUGMSGTL(("parse-mibs", "Module %s already loaded\n",
03810 name));
03811 return MODULE_ALREADY_LOADED;
03812 }
03813 if ((fp = fopen(mp->file, "r")) == NULL) {
03814 snmp_log_perror(mp->file);
03815 return MODULE_LOAD_FAILED;
03816 }
03817 mp->no_imports = 0;
03818 File = mp->file;
03819 mibLine = 1;
03820 current_module = mp->modid;
03821
03822
03823
03824 np = parse(fp, NULL);
03825 fclose(fp);
03826 File = oldFile;
03827 mibLine = oldLine;
03828 current_module = oldModule;
03829 return MODULE_LOADED_OK;
03830 }
03831
03832 return MODULE_NOT_FOUND;
03833 }
03834
03835 void
03836 adopt_orphans(void)
03837 {
03838 struct node *np, *onp;
03839 struct tree *tp;
03840 int i, adopted = 1;
03841
03842 if (!orphan_nodes)
03843 return;
03844 init_node_hash(orphan_nodes);
03845 orphan_nodes = NULL;
03846
03847 while (adopted) {
03848 adopted = 0;
03849 for (i = 0; i < NHASHSIZE; i++)
03850 if (nbuckets[i]) {
03851 for (np = nbuckets[i]; np != NULL; np = np->next) {
03852 tp = find_tree_node(np->parent, -1);
03853 if (tp) {
03854 do_subtree(tp, &np);
03855 adopted = 1;
03856
03857
03858
03859 if(NULL == nbuckets[i])
03860 break;
03861
03862
03863
03864
03865
03866
03867
03868
03869 for(onp = nbuckets[i]; onp; onp = onp->next)
03870 if(onp == np)
03871 break;
03872 if(NULL == onp) {
03873 np = nbuckets[i];
03874 }
03875 }
03876 }
03877 }
03878 }
03879
03880
03881
03882
03883
03884 for (i = 0; i < NHASHSIZE; i++)
03885 if (nbuckets[i]) {
03886 if (orphan_nodes)
03887 onp = np->next = nbuckets[i];
03888 else
03889 onp = orphan_nodes = nbuckets[i];
03890 nbuckets[i] = NULL;
03891 while (onp) {
03892 char modbuf[256];
03893 snmp_log(LOG_WARNING,
03894 "Cannot adopt OID in %s: %s ::= { %s %ld }\n",
03895 module_name(onp->modid, modbuf),
03896 (onp->label ? onp->label : "<no label>"),
03897 (onp->parent ? onp->parent : "<no parent>"),
03898 onp->subid);
03899
03900 np = onp;
03901 onp = onp->next;
03902 }
03903 }
03904 }
03905
03906 #ifndef NETSNMP_CLEAN_NAMESPACE
03907 struct tree *
03908 read_module(const char *name)
03909 {
03910 return netsnmp_read_module(name);
03911 }
03912 #endif
03913
03914 struct tree *
03915 netsnmp_read_module(const char *name)
03916 {
03917 if (read_module_internal(name) == MODULE_NOT_FOUND)
03918 if (!read_module_replacements(name))
03919 print_module_not_found(name);
03920 return tree_head;
03921 }
03922
03923
03924
03925
03926 void unload_module_by_ID(int modID, struct tree *tree_top);
03927
03928 void
03929 unload_module_by_ID(int modID, struct tree *tree_top)
03930 {
03931 struct tree *tp, *next;
03932 int i;
03933
03934 for (tp = tree_top; tp; tp = next) {
03935
03936
03937
03938
03939
03940
03941
03942 int nmod = tp->number_modules;
03943 if (nmod > 0) {
03944
03945
03946
03947 int cnt = 0, *pi1, *pi2 = tp->module_list;
03948 for (i = 0, pi1 = pi2; i < nmod; i++, pi2++) {
03949 if (*pi2 == modID)
03950 continue;
03951 cnt++;
03952 *pi1++ = *pi2;
03953 }
03954 if (nmod != cnt) {
03955
03956
03957
03958
03959 tp->number_modules = cnt;
03960 switch (cnt) {
03961 case 0:
03962 tp->module_list[0] = -1;
03963
03964 case 1:
03965 if (&(tp->modid) != tp->module_list) {
03966 tp->modid = tp->module_list[0];
03967 free(tp->module_list);
03968 tp->module_list = &(tp->modid);
03969 }
03970 break;
03971
03972 default:
03973 break;
03974 }
03975 }
03976 }
03977
03978
03979
03980 next = tp->next_peer;
03981
03982
03983
03984
03985
03986
03987
03988 if (tp->child_list)
03989 unload_module_by_ID(modID, tp->child_list);
03990
03991
03992 if (tp->number_modules == 0) {
03993
03994
03995
03996
03997 if (tp->child_list == NULL) {
03998 unlink_tree(tp);
03999 free_tree(tp);
04000 } else {
04001 free_partial_tree(tp, TRUE);
04002 }
04003 }
04004 }
04005 }
04006
04007 #ifndef NETSNMP_CLEAN_NAMESPACE
04008 int
04009 unload_module(const char *name)
04010 {
04011 return netsnmp_unload_module(name);
04012 }
04013 #endif
04014
04015 int
04016 netsnmp_unload_module(const char *name)
04017 {
04018 struct module *mp;
04019 int modID = -1;
04020
04021 for (mp = module_head; mp; mp = mp->next)
04022 if (!label_compare(mp->name, name)) {
04023 modID = mp->modid;
04024 break;
04025 }
04026
04027 if (modID == -1) {
04028 DEBUGMSGTL(("unload-mib", "Module %s not found to unload\n",
04029 name));
04030 return MODULE_NOT_FOUND;
04031 }
04032 unload_module_by_ID(modID, tree_head);
04033 mp->no_imports = -1;
04034 return MODULE_LOADED_OK;
04035 }
04036
04037
04038
04039
04040 void
04041 unload_all_mibs()
04042 {
04043 struct module *mp;
04044 struct module_compatability *mcp;
04045 struct tc *ptc;
04046 int i;
04047
04048 for (mcp = module_map_head; mcp; mcp = module_map_head) {
04049 if (mcp == module_map)
04050 break;
04051 module_map_head = mcp->next;
04052 if (mcp->tag) free((char *) mcp->tag);
04053 free((char *) mcp->old_module);
04054 free((char *) mcp->new_module);
04055 free(mcp);
04056 }
04057
04058 for (mp = module_head; mp; mp = module_head) {
04059 struct module_import *mi = mp->imports;
04060 if (mi) {
04061 for (i = 0; i < mp->no_imports; ++i) {
04062 SNMP_FREE((mi + i)->label);
04063 }
04064 mp->no_imports = 0;
04065 if (mi == root_imports)
04066 memset(mi, 0, sizeof(*mi));
04067 else
04068 free(mi);
04069 }
04070
04071 unload_module_by_ID(mp->modid, tree_head);
04072 module_head = mp->next;
04073 free(mp->name);
04074 free(mp->file);
04075 free(mp);
04076 }
04077 unload_module_by_ID(-1, tree_head);
04078
04079
04080
04081
04082 for (i = 0, ptc = tclist; i < MAXTC; i++, ptc++) {
04083 if (ptc->type == 0)
04084 continue;
04085 free_enums(&ptc->enums);
04086 free_ranges(&ptc->ranges);
04087 free(ptc->descriptor);
04088 if (ptc->hint)
04089 free(ptc->hint);
04090 }
04091 memset(tclist, 0, MAXTC * sizeof(struct tc));
04092
04093 memset(buckets, 0, sizeof(buckets));
04094 memset(nbuckets, 0, sizeof(nbuckets));
04095 memset(tbuckets, 0, sizeof(tbuckets));
04096
04097 for (i = 0; i < sizeof(root_imports) / sizeof(root_imports[0]); i++) {
04098 SNMP_FREE(root_imports[i].label);
04099 }
04100
04101 max_module = 0;
04102 current_module = 0;
04103 module_map_head = NULL;
04104 SNMP_FREE(last_err_module);
04105 }
04106
04107 static void
04108 new_module(const char *name, const char *file)
04109 {
04110 struct module *mp;
04111
04112 for (mp = module_head; mp; mp = mp->next)
04113 if (!label_compare(mp->name, name)) {
04114 DEBUGMSGTL(("parse-mibs", " Module %s already noted\n", name));
04115
04116
04117
04118 if (label_compare(mp->file, file)) {
04119 DEBUGMSGTL(("parse-mibs", " %s is now in %s\n",
04120 name, file));
04121 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
04122 NETSNMP_DS_LIB_MIB_WARNINGS)) {
04123 snmp_log(LOG_WARNING,
04124 "Warning: Module %s was in %s now is %s\n",
04125 name, mp->file, file);
04126 }
04127
04128
04129
04130
04131 free(mp->file);
04132 mp->file = strdup(file);
04133 }
04134 return;
04135 }
04136
04137
04138
04139
04140 DEBUGMSGTL(("parse-mibs", " Module %d %s is in %s\n", max_module,
04141 name, file));
04142 mp = (struct module *) calloc(1, sizeof(struct module));
04143 if (mp == NULL)
04144 return;
04145 mp->name = strdup(name);
04146 mp->file = strdup(file);
04147 mp->imports = NULL;
04148 mp->no_imports = -1;
04149 mp->modid = max_module;
04150 ++max_module;
04151
04152 mp->next = module_head;
04153 module_head = mp;
04154 }
04155
04156
04157 static void
04158 scan_objlist(struct node *root, struct objgroup *list, const char *error)
04159 {
04160 int oLine = mibLine;
04161
04162 while (list) {
04163 struct objgroup *gp = list;
04164 struct node *np;
04165 list = list->next;
04166 np = root;
04167 while (np)
04168 if (label_compare(np->label, gp->name))
04169 np = np->next;
04170 else
04171 break;
04172 if (!np) {
04173 mibLine = gp->line;
04174 print_error(error, gp->name, QUOTESTRING);
04175 }
04176 free(gp->name);
04177 free(gp);
04178 }
04179 mibLine = oLine;
04180 }
04181
04182
04183
04184
04185
04186 static struct node *
04187 parse(FILE * fp, struct node *root)
04188 {
04189 char token[MAXTOKEN];
04190 char name[MAXTOKEN];
04191 int type = LABEL;
04192 int lasttype = LABEL;
04193
04194 #define BETWEEN_MIBS 1
04195 #define IN_MIB 2
04196 int state = BETWEEN_MIBS;
04197 struct node *np, *nnp;
04198 struct objgroup *oldgroups = NULL, *oldobjects = NULL, *oldnotifs =
04199 NULL;
04200
04201 DEBUGMSGTL(("parse-file", "Parsing file: %s...\n", File));
04202
04203 if (last_err_module)
04204 free(last_err_module);
04205 last_err_module = 0;
04206
04207 np = root;
04208 if (np != NULL) {
04209
04210
04211
04212 while (np->next)
04213 np = np->next;
04214 }
04215
04216 while (type != ENDOFFILE) {
04217 if (lasttype == CONTINUE)
04218 lasttype = type;
04219 else
04220 type = lasttype = get_token(fp, token, MAXTOKEN);
04221
04222 switch (type) {
04223 case END:
04224 if (state != IN_MIB) {
04225 print_error("Error, END before start of MIB", NULL, type);
04226 return NULL;
04227 } else {
04228 struct module *mp;
04229 #ifdef TEST
04230 printf("\nNodes for Module %s:\n", name);
04231 print_nodes(stdout, root);
04232 #endif
04233 scan_objlist(root, objgroups, "Undefined OBJECT-GROUP");
04234 scan_objlist(root, objects, "Undefined OBJECT");
04235 scan_objlist(root, notifs, "Undefined NOTIFICATION");
04236 objgroups = oldgroups;
04237 objects = oldobjects;
04238 notifs = oldnotifs;
04239 for (mp = module_head; mp; mp = mp->next)
04240 if (mp->modid == current_module)
04241 break;
04242 do_linkup(mp, root);
04243 np = root = NULL;
04244 }
04245 state = BETWEEN_MIBS;
04246 #ifdef TEST
04247 if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
04248 NETSNMP_DS_LIB_MIB_WARNINGS)) {
04249 xmalloc_stats(stderr);
04250 }
04251 #endif
04252 continue;
04253 case IMPORTS:
04254 parse_imports(fp);
04255 continue;
04256 case EXPORTS:
04257 while (type != SEMI && type != ENDOFFILE)
04258 type = get_token(fp, token, MAXTOKEN);
04259 continue;
04260 case LABEL:
04261 case INTEGER:
04262 case INTEGER32:
04263 case UINTEGER32:
04264 case UNSIGNED32:
04265 case COUNTER:
04266 case COUNTER64:
04267 case GAUGE:
04268 case IPADDR:
04269 case NETADDR:
04270 case NSAPADDRESS:
04271 case OBJSYNTAX:
04272 case APPSYNTAX:
04273 case SIMPLESYNTAX:
04274 case OBJNAME:
04275 case NOTIFNAME:
04276 case KW_OPAQUE:
04277 case TIMETICKS:
04278 break;
04279 case ENDOFFILE:
04280 continue;
04281 default:
04282 strcpy(name, token);
04283 type = get_token(fp, token, MAXTOKEN);
04284 nnp = NULL;
04285 if (type == MACRO) {
04286 nnp = parse_macro(fp, name);
04287 if (nnp == NULL) {
04288 print_error("Bad parse of MACRO", NULL, type);
04289
04290
04291
04292 }
04293 free_node(nnp);
04294 nnp = NULL;
04295 } else
04296 print_error(name, "is a reserved word", lasttype);
04297 continue;
04298 }
04299 strcpy(name, token);
04300 type = get_token(fp, token, MAXTOKEN);
04301 nnp = NULL;
04302
04303
04304
04305
04306
04307 if (lasttype == LABEL && type == LEFTBRACKET) {
04308 while (type != RIGHTBRACKET && type != ENDOFFILE)
04309 type = get_token(fp, token, MAXTOKEN);
04310 if (type == ENDOFFILE) {
04311 print_error("Expected \"}\"", token, type);
04312 return NULL;
04313 }
04314 type = get_token(fp, token, MAXTOKEN);
04315 }
04316
04317 switch (type) {
04318 case DEFINITIONS:
04319 if (state != BETWEEN_MIBS) {
04320 print_error("Error, nested MIBS", NULL, type);
04321 return NULL;
04322 }
04323 state = IN_MIB;
04324 current_module = which_module(name);
04325 oldgroups = objgroups;
04326 objgroups = NULL;
04327 oldobjects = objects;
04328 objects = NULL;
04329 oldnotifs = notifs;
04330 notifs = NULL;
04331 if (current_module == -1) {
04332 new_module(name, File);
04333 current_module = which_module(name);
04334 }
04335 DEBUGMSGTL(("parse-mibs", "Parsing MIB: %d %s\n",
04336 current_module, name));
04337 while ((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE)
04338 if (type == BEGIN)
04339 break;
04340 break;
04341 case OBJTYPE:
04342 nnp = parse_objecttype(fp, name);
04343 if (nnp == NULL) {
04344 print_error("Bad parse of OBJECT-TYPE", NULL, type);
04345 return NULL;
04346 }
04347 break;
04348 case OBJGROUP:
04349 nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
04350 if (nnp == NULL) {
04351 print_error("Bad parse of OBJECT-GROUP", NULL, type);
04352 return NULL;
04353 }
04354 break;
04355 case NOTIFGROUP:
04356 nnp = parse_objectgroup(fp, name, NOTIFICATIONS, ¬ifs);
04357 if (nnp == NULL) {
04358 print_error("Bad parse of NOTIFICATION-GROUP", NULL, type);
04359 return NULL;
04360 }
04361 break;
04362 case TRAPTYPE:
04363 nnp = parse_trapDefinition(fp, name);
04364 if (nnp == NULL) {
04365 print_error("Bad parse of TRAP-TYPE", NULL, type);
04366 return NULL;
04367 }
04368 break;
04369 case NOTIFTYPE:
04370 nnp = parse_notificationDefinition(fp, name);
04371 if (nnp == NULL) {
04372 print_error("Bad parse of NOTIFICATION-TYPE", NULL, type);
04373 return NULL;
04374 }
04375 break;
04376 case COMPLIANCE:
04377 nnp = parse_compliance(fp, name);
04378 if (nnp == NULL) {
04379 print_error("Bad parse of MODULE-COMPLIANCE", NULL, type);
04380 return NULL;
04381 }
04382 break;
04383 case AGENTCAP:
04384 nnp = parse_capabilities(fp, name);
04385 if (nnp == NULL) {
04386 print_error("Bad parse of AGENT-CAPABILITIES", NULL, type);
04387 return NULL;
04388 }
04389 break;
04390 case MACRO:
04391 nnp = parse_macro(fp, name);
04392 if (nnp == NULL) {
04393 print_error("Bad parse of MACRO", NULL, type);
04394
04395
04396
04397 }
04398 free_node(nnp);
04399 nnp = NULL;
04400 break;
04401 case MODULEIDENTITY:
04402 nnp = parse_moduleIdentity(fp, name);
04403 if (nnp == NULL) {
04404 print_error("Bad parse of MODULE-IDENTITY", NULL, type);
04405 return NULL;
04406 }
04407 break;
04408 case OBJIDENTITY:
04409 nnp = parse_objectgroup(fp, name, OBJECTS, &objects);
04410 if (nnp == NULL) {
04411 print_error("Bad parse of OBJECT-IDENTITY", NULL, type);
04412 return NULL;
04413 }
04414 break;
04415 case OBJECT:
04416 type = get_token(fp, token, MAXTOKEN);
04417 if (type != IDENTIFIER) {
04418 print_error("Expected IDENTIFIER", token, type);
04419 return NULL;
04420 }
04421 type = get_token(fp, token, MAXTOKEN);
04422 if (type != EQUALS) {
04423 print_error("Expected \"::=\"", token, type);
04424 return NULL;
04425 }
04426 nnp = parse_objectid(fp, name);
04427 if (nnp == NULL) {
04428 print_error("Bad parse of OBJECT IDENTIFIER", NULL, type);
04429 return NULL;
04430 }
04431 break;
04432 case EQUALS:
04433 nnp = parse_asntype(fp, name, &type, token);
04434 lasttype = CONTINUE;
04435 break;
04436 case ENDOFFILE:
04437 break;
04438 default:
04439 print_error("Bad operator", token, type);
04440 return NULL;
04441 }
04442 if (nnp) {
04443 if (np)
04444 np->next = nnp;
04445 else
04446 np = root = nnp;
04447 while (np->next)
04448 np = np->next;
04449 if (np->type == TYPE_OTHER)
04450 np->type = type;
04451 }
04452 }
04453 DEBUGMSGTL(("parse-file", "End of file (%s)\n", File));
04454 return root;
04455 }
04456
04457
04458
04459
04460 static int
04461 is_labelchar(int ich)
04462 {
04463 if ((isalnum(ich)) || (ich == '-'))
04464 return 1;
04465 if (ich == '_' && netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
04466 NETSNMP_DS_LIB_MIB_PARSE_LABEL)) {
04467 return 1;
04468 }
04469
04470 return 0;
04471 }
04472
04473
04474
04475
04476
04477
04478 static int
04479 get_token(FILE * fp, char *token, int maxtlen)
04480 {
04481 register int ch, ch_next;
04482 register char *cp = token;
04483 register int hash = 0;
04484 register struct tok *tp;
04485 int too_long = 0;
04486
04487
04488
04489
04490 do {
04491 ch = getc(fp);
04492 if (ch == '\n')
04493 mibLine++;
04494 }
04495 while (isspace(ch) && ch != EOF);
04496 *cp++ = ch;
04497 *cp = '\0';
04498 switch (ch) {
04499 case EOF:
04500 return ENDOFFILE;
04501 case '"':
04502 return parseQuoteString(fp, token, maxtlen);
04503 case '\'':
04504 while ((ch = getc(fp)) != EOF && ch != '\''
04505 && cp - token < maxtlen - 2)
04506 *cp++ = ch;
04507 if (ch == '\'') {
04508 unsigned long val = 0;
04509 *cp++ = '\'';
04510 *cp++ = ch = getc(fp);
04511 *cp = 0;
04512 cp = token + 1;
04513 switch (ch) {
04514 case EOF:
04515 return ENDOFFILE;
04516 case 'b':
04517 case 'B':
04518 while ((ch = *cp++) != '\'')
04519 if (ch != '0' && ch != '1')
04520 return LABEL;
04521 else
04522 val = val * 2 + ch - '0';
04523 break;
04524 case 'h':
04525 case 'H':
04526 while ((ch = *cp++) != '\'')
04527 if ('0' <= ch && ch <= '9')
04528 val = val * 16 + ch - '0';
04529 else if ('a' <= ch && ch <= 'f')
04530 val = val * 16 + ch - 'a' + 10;
04531 else if ('A' <= ch && ch <= 'F')
04532 val = val * 16 + ch - 'A' + 10;
04533 else
04534 return LABEL;
04535 break;
04536 default:
04537 return LABEL;
04538 }
04539 sprintf(token, "%ld", val);
04540 return NUMBER;
04541 } else
04542 return LABEL;
04543 case '(':
04544 return LEFTPAREN;
04545 case ')':
04546 return RIGHTPAREN;
04547 case '{':
04548 return LEFTBRACKET;
04549 case '}':
04550 return RIGHTBRACKET;
04551 case '[':
04552 return LEFTSQBRACK;
04553 case ']':
04554 return RIGHTSQBRACK;
04555 case ';':
04556 return SEMI;
04557 case ',':
04558 return COMMA;
04559 case '|':
04560 return BAR;
04561 case '.':
04562 ch_next = getc(fp);
04563 if (ch_next == '.')
04564 return RANGE;
04565 ungetc(ch_next, fp);
04566 return LABEL;
04567 case ':':
04568 ch_next = getc(fp);
04569 if (ch_next != ':') {
04570 ungetc(ch_next, fp);
04571 return LABEL;
04572 }
04573 ch_next = getc(fp);
04574 if (ch_next != '=') {
04575 ungetc(ch_next, fp);
04576 return LABEL;
04577 }
04578 return EQUALS;
04579 case '-':
04580 ch_next = getc(fp);
04581 if (ch_next == '-') {
04582 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
04583 NETSNMP_DS_LIB_MIB_COMMENT_TERM)) {
04584
04585
04586
04587 while ((ch_next != EOF) && (ch_next != '\n'))
04588 ch_next = getc(fp);
04589 } else {
04590
04591
04592
04593
04594
04595
04596 ch = ' ';
04597 ch_next = getc(fp);
04598 while (ch_next != EOF && ch_next != '\n' &&
04599 (ch != '-' || ch_next != '-')) {
04600 ch = ch_next;
04601 ch_next = getc(fp);
04602 }
04603 }
04604 if (ch_next == EOF)
04605 return ENDOFFILE;
04606 if (ch_next == '\n')
04607 mibLine++;
04608 return get_token(fp, token, maxtlen);
04609 }
04610 ungetc(ch_next, fp);
04611 default:
04612
04613
04614
04615
04616
04617 if (!is_labelchar(ch))
04618 return LABEL;
04619 hash += tolower(ch);
04620 more:
04621 while (is_labelchar(ch_next = getc(fp))) {
04622 hash += tolower(ch_next);
04623 if (cp - token < maxtlen - 1)
04624 *cp++ = ch_next;
04625 else
04626 too_long = 1;
04627 }
04628 ungetc(ch_next, fp);
04629 *cp = '\0';
04630
04631 if (too_long)
04632 print_error("Warning: token too long", token, CONTINUE);
04633 for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
04634 if ((tp->hash == hash) && (!label_compare(tp->name, token)))
04635 break;
04636 }
04637 if (tp) {
04638 if (tp->token != CONTINUE)
04639 return (tp->token);
04640 while (isspace((ch_next = getc(fp))))
04641 if (ch_next == '\n')
04642 mibLine++;
04643 if (ch_next == EOF)
04644 return ENDOFFILE;
04645 if (isalnum(ch_next)) {
04646 *cp++ = ch_next;
04647 hash += tolower(ch_next);
04648 goto more;
04649 }
04650 }
04651 if (token[0] == '-' || isdigit(token[0])) {
04652 for (cp = token + 1; *cp; cp++)
04653 if (!isdigit(*cp))
04654 return LABEL;
04655 return NUMBER;
04656 }
04657 return LABEL;
04658 }
04659 }
04660
04661 int
04662 snmp_get_token(FILE * fp, char *token, int maxtlen)
04663 {
04664 return get_token(fp, token, maxtlen);
04665 }
04666
04667 int
04668 add_mibfile(const char* tmpstr, const char* d_name, FILE *ip )
04669 {
04670 FILE *fp;
04671 char token[MAXTOKEN], token2[MAXTOKEN];
04672
04673
04674
04675
04676 if ((fp = fopen(tmpstr, "r")) == NULL) {
04677 snmp_log_perror(tmpstr);
04678 return 1;
04679 }
04680 DEBUGMSGTL(("parse-mibs", "Checking file: %s...\n",
04681 tmpstr));
04682 mibLine = 1;
04683 File = tmpstr;
04684 get_token(fp, token, MAXTOKEN);
04685
04686
04687
04688 if (get_token(fp, token2, MAXTOKEN) == DEFINITIONS) {
04689 new_module(token, tmpstr);
04690 if (ip)
04691 fprintf(ip, "%s %s\n", token, d_name);
04692 fclose(fp);
04693 return 0;
04694 } else {
04695 fclose(fp);
04696 return 1;
04697 }
04698 }
04699
04700
04701
04702
04703
04704
04705
04706 int
04707 add_mibdir(const char *dirname)
04708 {
04709 FILE *ip;
04710 DIR *dir, *dir2;
04711 const char *oldFile = File;
04712 struct dirent *file;
04713 char tmpstr[300];
04714 int count = 0;
04715 int fname_len = 0;
04716 #if !(defined(WIN32) || defined(cygwin))
04717 char token[MAXTOKEN];
04718 char space;
04719 char newline;
04720 struct stat dir_stat, idx_stat;
04721 char tmpstr1[300];
04722 int empty = 1;
04723 #endif
04724
04725 DEBUGMSGTL(("parse-mibs", "Scanning directory %s\n", dirname));
04726 #if !(defined(WIN32) || defined(cygwin))
04727 snprintf(token, sizeof(token), "%s/%s", dirname, ".index");
04728 token[ sizeof(token)-1 ] = 0;
04729 if (stat(token, &idx_stat) == 0 && stat(dirname, &dir_stat) == 0) {
04730 if (dir_stat.st_mtime < idx_stat.st_mtime) {
04731 DEBUGMSGTL(("parse-mibs", "The index is good\n"));
04732 if ((ip = fopen(token, "r")) != NULL) {
04733 while (fscanf(ip, "%127s%c%299s%c", token, &space, tmpstr,
04734 &newline) == 4) {
04735
04736 empty = 0;
04737
04738
04739
04740
04741
04742 if (space != ' ' || newline != '\n') {
04743 snmp_log(LOG_ERR,
04744 "add_mibdir: strings scanned in from %s/%s " \
04745 "are too large. count = %d\n ", dirname,
04746 ".index", count);
04747 break;
04748 }
04749
04750 snprintf(tmpstr1, sizeof(tmpstr1), "%s/%s", dirname, tmpstr);
04751 tmpstr1[ sizeof(tmpstr1)-1 ] = 0;
04752 new_module(token, tmpstr1);
04753 count++;
04754 }
04755 fclose(ip);
04756 if ( !empty ) {
04757 return count;
04758 }
04759 DEBUGMSGTL(("parse-mibs", "Empty MIB index\n"));
04760 } else
04761 DEBUGMSGTL(("parse-mibs", "Can't read index\n"));
04762 } else
04763 DEBUGMSGTL(("parse-mibs", "Index outdated\n"));
04764 } else
04765 DEBUGMSGTL(("parse-mibs", "No index\n"));
04766 #endif
04767
04768 if ((dir = opendir(dirname))) {
04769 snprintf(tmpstr, sizeof(tmpstr), "%s/.index", dirname);
04770 tmpstr[ sizeof(tmpstr)-1 ] = 0;
04771 ip = fopen(tmpstr, "w");
04772 while ((file = readdir(dir))) {
04773
04774
04775
04776
04777
04778 if (file->d_name != NULL) {
04779 fname_len = strlen( file->d_name );
04780 if (fname_len > 0 && file->d_name[0] != '.'
04781 && file->d_name[0] != '#'
04782 && file->d_name[fname_len-1] != '#'
04783 && file->d_name[fname_len-1] != '~') {
04784 snprintf(tmpstr, sizeof(tmpstr), "%s/%s", dirname, file->d_name);
04785 tmpstr[ sizeof(tmpstr)-1 ] = 0;
04786 if ((dir2 = opendir(tmpstr))) {
04787
04788
04789
04790 closedir(dir2);
04791 } else {
04792 if ( add_mibfile( tmpstr, file->d_name, ip ))
04793 count++;
04794 }
04795 }
04796 }
04797 }
04798 File = oldFile;
04799 closedir(dir);
04800 if (ip)
04801 fclose(ip);
04802 return (count);
04803 }
04804 else
04805 DEBUGMSGTL(("parse-mibs","cannot open MIB directory %s\n", dirname));
04806
04807 return (-1);
04808 }
04809
04810
04811
04812
04813
04814
04815 struct tree *
04816 read_mib(const char *filename)
04817 {
04818 FILE *fp;
04819 char token[MAXTOKEN];
04820
04821 fp = fopen(filename, "r");
04822 if (fp == NULL) {
04823 snmp_log_perror(filename);
04824 return NULL;
04825 }
04826 mibLine = 1;
04827 File = filename;
04828 DEBUGMSGTL(("parse-mibs", "Parsing file: %s...\n", filename));
04829 get_token(fp, token, MAXTOKEN);
04830 fclose(fp);
04831 new_module(token, filename);
04832 (void) netsnmp_read_module(token);
04833
04834 return tree_head;
04835 }
04836
04837
04838 struct tree *
04839 read_all_mibs()
04840 {
04841 struct module *mp;
04842
04843 for (mp = module_head; mp; mp = mp->next)
04844 if (mp->no_imports == -1)
04845 netsnmp_read_module(mp->name);
04846 adopt_orphans();
04847
04848 return tree_head;
04849 }
04850
04851
04852 #ifdef TEST
04853 main(int argc, char *argv[])
04854 {
04855 int i;
04856 struct tree *tp;
04857 netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_MIB_WARNINGS, 2);
04858
04859 netsnmp_init_mib();
04860
04861 if (argc == 1)
04862 (void) read_all_mibs();
04863 else
04864 for (i = 1; i < argc; i++)
04865 read_mib(argv[i]);
04866
04867 for (tp = tree_head; tp; tp = tp->next_peer)
04868 print_subtree(stdout, tp, 0);
04869 free_tree(tree_head);
04870
04871 return 0;
04872 }
04873 #endif
04874
04875 static int
04876 parseQuoteString(FILE * fp, char *token, int maxtlen)
04877 {
04878 register int ch;
04879 int count = 0;
04880 int too_long = 0;
04881 char *token_start = token;
04882
04883 for (ch = getc(fp); ch != EOF; ch = getc(fp)) {
04884 if (ch == '\r')
04885 continue;
04886 if (ch == '\n') {
04887 mibLine++;
04888 } else if (ch == '"') {
04889 *token = '\0';
04890 if (too_long && netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
04891 NETSNMP_DS_LIB_MIB_WARNINGS) > 1) {
04892
04893
04894
04895 char ch_save = *(token_start + 50);
04896 *(token_start + 50) = '\0';
04897 print_error("Warning: string too long",
04898 token_start, QUOTESTRING);
04899 *(token_start + 50) = ch_save;
04900 }
04901 return QUOTESTRING;
04902 }
04903
04904
04905
04906
04907 if (++count < maxtlen)
04908 *token++ = ch;
04909 else
04910 too_long = 1;
04911 }
04912
04913 return 0;
04914 }
04915
04916
04917
04918
04919
04920
04921
04922
04923 static struct index_list *
04924 getIndexes(FILE * fp, struct index_list **retp)
04925 {
04926 int type;
04927 char token[MAXTOKEN];
04928 char nextIsImplied = 0;
04929
04930 struct index_list *mylist = NULL;
04931 struct index_list **mypp = &mylist;
04932
04933 free_indexes(retp);
04934
04935 type = get_token(fp, token, MAXTOKEN);
04936
04937 if (type != LEFTBRACKET) {
04938 return NULL;
04939 }
04940
04941 type = get_token(fp, token, MAXTOKEN);
04942 while (type != RIGHTBRACKET && type != ENDOFFILE) {
04943 if ((type == LABEL) || (type & SYNTAX_MASK)) {
04944 *mypp =
04945 (struct index_list *) calloc(1, sizeof(struct index_list));
04946 if (*mypp) {
04947 (*mypp)->ilabel = strdup(token);
04948 (*mypp)->isimplied = nextIsImplied;
04949 mypp = &(*mypp)->next;
04950 nextIsImplied = 0;
04951 }
04952 } else if (type == IMPLIED) {
04953 nextIsImplied = 1;
04954 }
04955 type = get_token(fp, token, MAXTOKEN);
04956 }
04957
04958 *retp = mylist;
04959 return mylist;
04960 }
04961
04962 static struct varbind_list *
04963 getVarbinds(FILE * fp, struct varbind_list **retp)
04964 {
04965 int type;
04966 char token[MAXTOKEN];
04967
04968 struct varbind_list *mylist = NULL;
04969 struct varbind_list **mypp = &mylist;
04970
04971 free_varbinds(retp);
04972
04973 type = get_token(fp, token, MAXTOKEN);
04974
04975 if (type != LEFTBRACKET) {
04976 return NULL;
04977 }
04978
04979 type = get_token(fp, token, MAXTOKEN);
04980 while (type != RIGHTBRACKET && type != ENDOFFILE) {
04981 if ((type == LABEL) || (type & SYNTAX_MASK)) {
04982 *mypp =
04983 (struct varbind_list *) calloc(1,
04984 sizeof(struct
04985 varbind_list));
04986 if (*mypp) {
04987 (*mypp)->vblabel = strdup(token);
04988 mypp = &(*mypp)->next;
04989 }
04990 }
04991 type = get_token(fp, token, MAXTOKEN);
04992 }
04993
04994 *retp = mylist;
04995 return mylist;
04996 }
04997
04998 static void
04999 free_indexes(struct index_list **spp)
05000 {
05001 if (spp && *spp) {
05002 struct index_list *pp, *npp;
05003
05004 pp = *spp;
05005 *spp = NULL;
05006
05007 while (pp) {
05008 npp = pp->next;
05009 if (pp->ilabel)
05010 free(pp->ilabel);
05011 free(pp);
05012 pp = npp;
05013 }
05014 }
05015 }
05016
05017 static void
05018 free_varbinds(struct varbind_list **spp)
05019 {
05020 if (spp && *spp) {
05021 struct varbind_list *pp, *npp;
05022
05023 pp = *spp;
05024 *spp = NULL;
05025
05026 while (pp) {
05027 npp = pp->next;
05028 if (pp->vblabel)
05029 free(pp->vblabel);
05030 free(pp);
05031 pp = npp;
05032 }
05033 }
05034 }
05035
05036 static void
05037 free_ranges(struct range_list **spp)
05038 {
05039 if (spp && *spp) {
05040 struct range_list *pp, *npp;
05041
05042 pp = *spp;
05043 *spp = NULL;
05044
05045 while (pp) {
05046 npp = pp->next;
05047 free(pp);
05048 pp = npp;
05049 }
05050 }
05051 }
05052
05053 static void
05054 free_enums(struct enum_list **spp)
05055 {
05056 if (spp && *spp) {
05057 struct enum_list *pp, *npp;
05058
05059 pp = *spp;
05060 *spp = NULL;
05061
05062 while (pp) {
05063 npp = pp->next;
05064 if (pp->label)
05065 free(pp->label);
05066 free(pp);
05067 pp = npp;
05068 }
05069 }
05070 }
05071
05072 static struct enum_list *
05073 copy_enums(struct enum_list *sp)
05074 {
05075 struct enum_list *xp = NULL, **spp = &xp;
05076
05077 while (sp) {
05078 *spp = (struct enum_list *) calloc(1, sizeof(struct enum_list));
05079 if (!*spp)
05080 break;
05081 (*spp)->label = strdup(sp->label);
05082 (*spp)->value = sp->value;
05083 spp = &(*spp)->next;
05084 sp = sp->next;
05085 }
05086 return (xp);
05087 }
05088
05089 static struct range_list *
05090 copy_ranges(struct range_list *sp)
05091 {
05092 struct range_list *xp = NULL, **spp = &xp;
05093
05094 while (sp) {
05095 *spp = (struct range_list *) calloc(1, sizeof(struct range_list));
05096 if (!*spp)
05097 break;
05098 (*spp)->low = sp->low;
05099 (*spp)->high = sp->high;
05100 spp = &(*spp)->next;
05101 sp = sp->next;
05102 }
05103 return (xp);
05104 }
05105
05106
05107
05108
05109
05110 static int
05111 tossObjectIdentifier(FILE * fp)
05112 {
05113 int type;
05114 char token[MAXTOKEN];
05115 int bracketcount = 1;
05116
05117 type = get_token(fp, token, MAXTOKEN);
05118
05119 if (type != LEFTBRACKET)
05120 return 0;
05121 while ((type != RIGHTBRACKET || bracketcount > 0) && type != ENDOFFILE) {
05122 type = get_token(fp, token, MAXTOKEN);
05123 if (type == LEFTBRACKET)
05124 bracketcount++;
05125 else if (type == RIGHTBRACKET)
05126 bracketcount--;
05127 }
05128
05129 if (type == RIGHTBRACKET)
05130 return OBJID;
05131 else
05132 return 0;
05133 }
05134
05135
05136
05137 struct tree *
05138 find_node(const char *name, struct tree *subtree)
05139 {
05140 return (find_tree_node(name, -1));
05141 }
05142
05143
05144
05145 struct tree *
05146 find_node2(const char *name, const char *module)
05147 {
05148 int modid = -1;
05149 if (module) {
05150 modid = which_module(module);
05151 }
05152 if (modid == -1)
05153 {
05154 return (NULL);
05155 }
05156 return (find_tree_node(name, modid));
05157 }
05158
05159 struct module *
05160 find_module(int mid)
05161 {
05162 struct module *mp;
05163
05164 for (mp = module_head; mp != NULL; mp = mp->next) {
05165 if (mp->modid == mid)
05166 break;
05167 }
05168 if (mp != 0)
05169 return mp;
05170 return NULL;
05171 }
05172
05173
05174 static char leave_indent[256];
05175 static int leave_was_simple;
05176
05177 static void
05178 print_mib_leaves(FILE * f, struct tree *tp, int width)
05179 {
05180 struct tree *ntp;
05181 char *ip = leave_indent + strlen(leave_indent) - 1;
05182 char last_ipch = *ip;
05183
05184 *ip = '+';
05185 if (tp->type == TYPE_OTHER || tp->type > TYPE_SIMPLE_LAST) {
05186 fprintf(f, "%s--%s(%ld)\n", leave_indent, tp->label, tp->subid);
05187 if (tp->indexes) {
05188 struct index_list *xp = tp->indexes;
05189 int first = 1, cpos = 0, len, cmax =
05190 width - strlen(leave_indent) - 12;
05191 *ip = last_ipch;
05192 fprintf(f, "%s | Index: ", leave_indent);
05193 while (xp) {
05194 if (first)
05195 first = 0;
05196 else
05197 fprintf(f, ", ");
05198 cpos += (len = strlen(xp->ilabel) + 2);
05199 if (cpos > cmax) {
05200 fprintf(f, "\n");
05201 fprintf(f, "%s | ", leave_indent);
05202 cpos = len;
05203 }
05204 fprintf(f, "%s", xp->ilabel);
05205 xp = xp->next;
05206 }
05207 fprintf(f, "\n");
05208 *ip = '+';
05209 }
05210 } else {
05211 const char *acc, *typ;
05212 int size = 0;
05213 switch (tp->access) {
05214 case MIB_ACCESS_NOACCESS:
05215 acc = "----";
05216 break;
05217 case MIB_ACCESS_READONLY:
05218 acc = "-R--";
05219 break;
05220 case MIB_ACCESS_WRITEONLY:
05221 acc = "--W-";
05222 break;
05223 case MIB_ACCESS_READWRITE:
05224 acc = "-RW-";
05225 break;
05226 case MIB_ACCESS_NOTIFY:
05227 acc = "---N";
05228 break;
05229 case MIB_ACCESS_CREATE:
05230 acc = "CR--";
05231 break;
05232 default:
05233 acc = " ";
05234 break;
05235 }
05236 switch (tp->type) {
05237 case TYPE_OBJID:
05238 typ = "ObjID ";
05239 break;
05240 case TYPE_OCTETSTR:
05241 typ = "String ";
05242 size = 1;
05243 break;
05244 case TYPE_INTEGER:
05245 if (tp->enums)
05246 typ = "EnumVal ";
05247 else
05248 typ = "INTEGER ";
05249 break;
05250 case TYPE_NETADDR:
05251 typ = "NetAddr ";
05252 break;
05253 case TYPE_IPADDR:
05254 typ = "IpAddr ";
05255 break;
05256 case TYPE_COUNTER:
05257 typ = "Counter ";
05258 break;
05259 case TYPE_GAUGE:
05260 typ = "Gauge ";
05261 break;
05262 case TYPE_TIMETICKS:
05263 typ = "TimeTicks";
05264 break;
05265 case TYPE_OPAQUE:
05266 typ = "Opaque ";
05267 size = 1;
05268 break;
05269 case TYPE_NULL:
05270 typ = "Null ";
05271 break;
05272 case TYPE_COUNTER64:
05273 typ = "Counter64";
05274 break;
05275 case TYPE_BITSTRING:
05276 typ = "BitString";
05277 break;
05278 case TYPE_NSAPADDRESS:
05279 typ = "NsapAddr ";
05280 break;
05281 case TYPE_UNSIGNED32:
05282 typ = "Unsigned ";
05283 break;
05284 case TYPE_UINTEGER:
05285 typ = "UInteger ";
05286 break;
05287 case TYPE_INTEGER32:
05288 typ = "Integer32";
05289 break;
05290 default:
05291 typ = " ";
05292 break;
05293 }
05294 fprintf(f, "%s-- %s %s %s(%ld)\n", leave_indent, acc, typ,
05295 tp->label, tp->subid);
05296 *ip = last_ipch;
05297 if (tp->tc_index >= 0)
05298 fprintf(f, "%s Textual Convention: %s\n", leave_indent,
05299 tclist[tp->tc_index].descriptor);
05300 if (tp->enums) {
05301 struct enum_list *ep = tp->enums;
05302 int cpos = 0, cmax =
05303 width - strlen(leave_indent) - 16;
05304 fprintf(f, "%s Values: ", leave_indent);
05305 while (ep) {
05306 char buf[80];
05307 int bufw;
05308 if (ep != tp->enums)
05309 fprintf(f, ", ");
05310 snprintf(buf, sizeof(buf), "%s(%d)", ep->label, ep->value);
05311 buf[ sizeof(buf)-1 ] = 0;
05312 cpos += (bufw = strlen(buf) + 2);
05313 if (cpos >= cmax) {
05314 fprintf(f, "\n%s ", leave_indent);
05315 cpos = bufw;
05316 }
05317 fprintf(f, "%s", buf);
05318 ep = ep->next;
05319 }
05320 fprintf(f, "\n");
05321 }
05322 if (tp->ranges) {
05323 struct range_list *rp = tp->ranges;
05324 if (size)
05325 fprintf(f, "%s Size: ", leave_indent);
05326 else
05327 fprintf(f, "%s Range: ", leave_indent);
05328 while (rp) {
05329 if (rp != tp->ranges)
05330 fprintf(f, " | ");
05331 if (rp->low == rp->high)
05332 fprintf(f, "%d", rp->low);
05333 else
05334 fprintf(f, "%d..%d", rp->low, rp->high);
05335 rp = rp->next;
05336 }
05337 fprintf(f, "\n");
05338 }
05339 }
05340 *ip = last_ipch;
05341 strcat(leave_indent, " |");
05342 leave_was_simple = tp->type != TYPE_OTHER;
05343
05344 {
05345 int i, j, count = 0;
05346 struct leave {
05347 oid id;
05348 struct tree *tp;
05349 } *leaves, *lp;
05350
05351 for (ntp = tp->child_list; ntp; ntp = ntp->next_peer)
05352 count++;
05353 if (count) {
05354 leaves = (struct leave *) calloc(count, sizeof(struct leave));
05355 if (!leaves)
05356 return;
05357 for (ntp = tp->child_list, count = 0; ntp;
05358 ntp = ntp->next_peer) {
05359 for (i = 0, lp = leaves; i < count; i++, lp++)
05360 if (lp->id >= ntp->subid)
05361 break;
05362 for (j = count; j > i; j--)
05363 leaves[j] = leaves[j - 1];
05364 lp->id = ntp->subid;
05365 lp->tp = ntp;
05366 count++;
05367 }
05368 for (i = 1, lp = leaves; i <= count; i++, lp++) {
05369 if (!leave_was_simple || lp->tp->type == 0)
05370 fprintf(f, "%s\n", leave_indent);
05371 if (i == count)
05372 ip[3] = ' ';
05373 print_mib_leaves(f, lp->tp, width);
05374 }
05375 free(leaves);
05376 leave_was_simple = 0;
05377 }
05378 }
05379 ip[1] = 0;
05380 }
05381
05382 void
05383 print_mib_tree(FILE * f, struct tree *tp, int width)
05384 {
05385 leave_indent[0] = ' ';
05386 leave_indent[1] = 0;
05387 leave_was_simple = 1;
05388 print_mib_leaves(f, tp, width);
05389 }
05390
05391
05392
05393
05394
05395
05396 static struct node *
05397 merge_parse_objectid(struct node *np, FILE * fp, char *name)
05398 {
05399 struct node *nnp;
05400
05401
05402
05403 nnp = parse_objectid(fp, name);
05404 if (nnp) {
05405
05406
05407
05408
05409
05410
05411
05412 struct node *headp, *nextp;
05413 int ncount = 0;
05414 nextp = headp = nnp;
05415 while (nnp->next) {
05416 nextp = nnp;
05417 ncount++;
05418 nnp = nnp->next;
05419 }
05420
05421 np->label = nnp->label;
05422 np->subid = nnp->subid;
05423 np->modid = nnp->modid;
05424 np->parent = nnp->parent;
05425 if (nnp->filename != NULL) {
05426 free(nnp->filename);
05427 }
05428 free(nnp);
05429
05430 if (ncount) {
05431 nextp->next = np;
05432 np = headp;
05433 }
05434 } else {
05435 free_node(np);
05436 np = NULL;
05437 }
05438
05439 return np;
05440 }
05441
05442
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453 static void
05454 tree_from_node(struct tree *tp, struct node *np)
05455 {
05456 free_partial_tree(tp, FALSE);
05457
05458 tp->label = np->label;
05459 np->label = NULL;
05460 tp->enums = np->enums;
05461 np->enums = NULL;
05462 tp->ranges = np->ranges;
05463 np->ranges = NULL;
05464 tp->indexes = np->indexes;
05465 np->indexes = NULL;
05466 tp->augments = np->augments;
05467 np->augments = NULL;
05468 tp->varbinds = np->varbinds;
05469 np->varbinds = NULL;
05470 tp->hint = np->hint;
05471 np->hint = NULL;
05472 tp->units = np->units;
05473 np->units = NULL;
05474 tp->description = np->description;
05475 np->description = NULL;
05476 tp->reference = np->reference;
05477 np->reference = NULL;
05478 tp->defaultValue = np->defaultValue;
05479 np->defaultValue = NULL;
05480 tp->subid = np->subid;
05481 tp->tc_index = np->tc_index;
05482 tp->type = translation_table[np->type];
05483 tp->access = np->access;
05484 tp->status = np->status;
05485
05486 set_function(tp);
05487 }
05488
05489 #endif