parse.c
资源名称:snmp.src.rar [点击查看]
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:103k
源码类别:
SNMP编程
开发平台:
C/C++
- /*
- * parse.c
- *
- * Update: 1998-09-22 <mslifcak@iss.net>
- * Clear nbuckets in init_node_hash.
- * New method xcalloc returns zeroed data structures.
- * New method alloc_node encapsulates common node creation.
- * New method to configure terminate comment at end of line.
- * New method to configure accept underscore in labels.
- *
- * Update: 1998-10-10 <daves@csc.liv.ac.uk>
- * fully qualified OID parsing patch
- *
- * Update: 1998-10-20 <daves@csc.liv.ac.uk>
- * merge_anon_children patch
- *
- * Update: 1998-10-21 <mslifcak@iss.net>
- * Merge_parse_objectid associates information with last node in chain.
- */
- /******************************************************************
- Copyright 1989, 1991, 1992 by Carnegie Mellon University
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of CMU not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ******************************************************************/
- #include <config.h>
- #include <snmp_logging.h>
- #include <stdio.h>
- #if HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- /* Wow. This is ugly. -- Wes */
- #if HAVE_DIRENT_H
- # include <dirent.h>
- # define NAMLEN(dirent) strlen((dirent)->d_name)
- #else
- # define dirent direct
- # define NAMLEN(dirent) (dirent)->d_namlen
- #endif
- #if HAVE_WINSOCK_H
- #include <ip/socket.h>
- #endif
- #if HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
- #include <regex.h>
- #endif
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- #include "system.h"
- #include "parse.h"
- #include "asn1.h"
- #include "mib.h"
- #include "snmp_api.h"
- #include "snmp_debug.h"
- #include "snmp_logging.h"
- #include "default_store.h"
- #include "tools.h"
- /*
- * This is one element of an object identifier with either an integer
- * subidentifier, or a textual string label, or both.
- * The subid is -1 if not present, and label is NULL if not present.
- */
- struct subid_s {
- int subid;
- int modid;
- char *label;
- };
- #define MAXTC 1024
- struct tc { /* textual conventions */
- int type;
- int modid;
- char *descriptor;
- char *hint;
- struct enum_list *enums;
- struct range_list *ranges;
- } tclist[MAXTC];
- int Line = 0;
- const char *File = "(none)";
- static int anonymous = 0;
- #define SYNTAX_MASK 0x80
- /* types of tokens
- Tokens wiht the SYNTAX_MASK bit set are syntax tokens */
- #define CONTINUE -1
- #define ENDOFFILE 0
- #define LABEL 1
- #define SUBTREE 2
- #define SYNTAX 3
- #define OBJID (4 | SYNTAX_MASK)
- #define OCTETSTR (5 | SYNTAX_MASK)
- #define INTEGER (6 | SYNTAX_MASK)
- #define INTEGER32 INTEGER
- #define NETADDR (7 | SYNTAX_MASK)
- #define IPADDR (8 | SYNTAX_MASK)
- #define COUNTER (9 | SYNTAX_MASK)
- #define GAUGE (10 | SYNTAX_MASK)
- #define TIMETICKS (11 | SYNTAX_MASK)
- #define KW_OPAQUE (12 | SYNTAX_MASK)
- #define NUL (13 | SYNTAX_MASK)
- #define SEQUENCE 14
- #define OF 15 /* SEQUENCE OF */
- #define OBJTYPE 16
- #define ACCESS 17
- #define READONLY 18
- #define READWRITE 19
- #define WRITEONLY 20
- #define NOACCESS 21
- #undef STATUS
- #define STATUS 22
- #define MANDATORY 23
- #define KW_OPTIONAL 24
- #define OBSOLETE 25
- /* #define RECOMMENDED 26 */
- #define PUNCT 27
- #define EQUALS 28
- #define NUMBER 29
- #define LEFTBRACKET 30
- #define RIGHTBRACKET 31
- #define LEFTPAREN 32
- #define RIGHTPAREN 33
- #define COMMA 34
- #define DESCRIPTION 35
- #define QUOTESTRING 36
- #define INDEX 37
- #define DEFVAL 38
- #define DEPRECATED 39
- #define SIZE 40
- #define BITSTRING (41 | SYNTAX_MASK)
- #define NSAPADDRESS (42 | SYNTAX_MASK)
- #define COUNTER64 (43 | SYNTAX_MASK)
- #define OBJGROUP 44
- #define NOTIFTYPE 45
- #define AUGMENTS 46
- #define COMPLIANCE 47
- #define READCREATE 48
- #define UNITS 49
- #define REFERENCE 50
- #define NUM_ENTRIES 51
- #define MODULEIDENTITY 52
- #define LASTUPDATED 53
- #define ORGANIZATION 54
- #define CONTACTINFO 55
- #define UINTEGER32 (56 | SYNTAX_MASK)
- #define CURRENT 57
- #define DEFINITIONS 58
- #define END 59
- #define SEMI 60
- #define TRAPTYPE 61
- #define ENTERPRISE 62
- /* #define DISPLAYSTR (63 | SYNTAX_MASK) */
- #define BEGIN 64
- #define IMPORTS 65
- #define EXPORTS 66
- #define ACCNOTIFY 67
- #define BAR 68
- #define RANGE 69
- #define CONVENTION 70
- #define DISPLAYHINT 71
- #define FROM 72
- #define CAPABILITIES 73
- #define MACRO 74
- #define IMPLIED 75
- struct tree *
- read_module(const char *name);
- struct tok {
- const char *name; /* token name */
- int len; /* length not counting nul */
- int token; /* value */
- int hash; /* hash of name */
- struct tok *next; /* pointer to next in hash table */
- };
- /*
- static struct tok tokens[] = {
- { "obsolete", sizeof ("obsolete")-1, OBSOLETE },
- { "Opaque", sizeof ("Opaque")-1, KW_OPAQUE },
- { "optional", sizeof ("optional")-1, KW_OPTIONAL },
- { "LAST-UPDATED", sizeof ("LAST-UPDATED")-1, LASTUPDATED },
- { "ORGANIZATION", sizeof ("ORGANIZATION")-1, ORGANIZATION },
- { "CONTACT-INFO", sizeof ("CONTACT-INFO")-1, CONTACTINFO },
- { "MODULE-IDENTITY", sizeof ("MODULE-IDENTITY")-1, MODULEIDENTITY },
- { "MODULE-COMPLIANCE", sizeof ("MODULE-COMPLIANCE")-1, COMPLIANCE },
- { "DEFINITIONS", sizeof("DEFINITIONS")-1, DEFINITIONS},
- { "END", sizeof("END")-1, END},
- { "AUGMENTS", sizeof ("AUGMENTS")-1, AUGMENTS },
- { "not-accessible", sizeof ("not-accessible")-1, NOACCESS },
- { "write-only", sizeof ("write-only")-1, WRITEONLY },
- { "NsapAddress", sizeof("NsapAddress")-1, NSAPADDRESS},
- { "UNITS", sizeof("Units")-1, UNITS},
- { "REFERENCE", sizeof("REFERENCE")-1, REFERENCE},
- { "NUM-ENTRIES", sizeof("NUM-ENTRIES")-1, NUM_ENTRIES},
- { "BITSTRING", sizeof("BITSTRING")-1, BITSTRING},
- { "BIT", sizeof("BIT")-1, CONTINUE},
- { "BITS", sizeof("BITS")-1, BITSTRING},
- { "Counter64", sizeof("Counter64")-1, COUNTER64},
- { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS },
- { "NOTIFICATION-TYPE", sizeof ("NOTIFICATION-TYPE")-1, NOTIFTYPE },
- { "OBJECT-GROUP", sizeof ("OBJECT-GROUP")-1, OBJGROUP },
- { "OBJECT-IDENTITY", sizeof ("OBJECT-IDENTITY")-1, OBJGROUP },
- { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID },
- { "OBJECT", sizeof ("OBJECT")-1, CONTINUE },
- { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR },
- { "Gauge", sizeof ("Gauge")-1, GAUGE },
- { "Gauge32", sizeof ("Gauge32")-1, GAUGE },
- { "Unsigned32", sizeof ("Unsigned32")-1, GAUGE },
- { "read-write", sizeof ("read-write")-1, READWRITE },
- { "read-create", sizeof ("read-create")-1, READCREATE },
- { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR },
- { "OCTET", sizeof ("OCTET")-1, CONTINUE },
- { "OF", sizeof ("OF")-1, OF },
- { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE },
- { "NULL", sizeof ("NULL")-1, NUL },
- { "IpAddress", sizeof ("IpAddress")-1, IPADDR },
- { "UInteger32", sizeof ("UInteger32")-1, UINTEGER32 },
- { "INTEGER", sizeof ("INTEGER")-1, INTEGER },
- { "Integer32", sizeof ("Integer32")-1, INTEGER32 },
- { "Counter", sizeof ("Counter")-1, COUNTER },
- { "Counter32", sizeof ("Counter32")-1, COUNTER },
- { "read-only", sizeof ("read-only")-1, READONLY },
- { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION },
- { "INDEX", sizeof ("INDEX")-1, INDEX },
- { "DEFVAL", sizeof ("DEFVAL")-1, DEFVAL },
- { "deprecated", sizeof ("deprecated")-1, DEPRECATED },
- { "SIZE", sizeof ("SIZE")-1, SIZE },
- { "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS },
- { "ACCESS", sizeof ("ACCESS")-1, ACCESS },
- { "mandatory", sizeof ("mandatory")-1, MANDATORY },
- { "current", sizeof ("current")-1, CURRENT },
- { "STATUS", sizeof ("STATUS")-1, STATUS },
- { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX },
- { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE },
- { "TRAP-TYPE", sizeof ("TRAP-TYPE")-1, TRAPTYPE },
- { "ENTERPRISE", sizeof ("ENTERPRISE")-1, ENTERPRISE },
- { "BEGIN", sizeof ("BEGIN")-1, BEGIN },
- { "IMPORTS", sizeof ("IMPORTS")-1, IMPORTS },
- { "EXPORTS", sizeof ("EXPORTS")-1, EXPORTS },
- { "accessible-for-notify", sizeof ("accessible-for-notify")-1, ACCNOTIFY },
- { "TEXTUAL-CONVENTION", sizeof ("TEXTUAL-CONVENTION")-1, CONVENTION },
- { "NOTIFICATION-GROUP", sizeof ("NOTIFICATION-GROUP")-1, NOTIFTYPE },
- { "DISPLAY-HINT", sizeof ("DISPLAY-HINT")-1, DISPLAYHINT },
- { "FROM", sizeof ("FROM")-1, FROM },
- { "AGENT-CAPABILITIES", sizeof ("AGENT-CAPABILITIES")-1, CAPABILITIES },
- { "MACRO", sizeof ("MACRO")-1, MACRO },
- { "IMPLIED", sizeof ("IMPLIED")-1, IMPLIED },
- { NULL }
- }; */
- static struct module_compatability *module_map_head;
- /* static struct module_compatability module_map[] = {
- { "RFC1065-SMI", "RFC1155-SMI", NULL, 0},
- { "RFC1066-MIB", "RFC1156-MIB", NULL, 0},
- /* 'mib' -> 'mib-2'
- { "RFC1156-MIB", "RFC1158-MIB", NULL, 0},
- /* 'snmpEnableAuthTraps' -> 'snmpEnableAuthenTraps'
- { "RFC1158-MIB", "RFC1213-MIB", NULL, 0},
- /* 'nullOID' -> 'zeroDotZero'
- { "RFC1155-SMI", "SNMPv2-SMI", NULL, 0},
- { "RFC1213-MIB", "SNMPv2-SMI", "mib-2", 0},
- { "RFC1213-MIB", "SNMPv2-MIB", "sys", 3},
- { "RFC1213-MIB", "IF-MIB", "if", 2},
- { "RFC1213-MIB", "IP-MIB", "ip", 2},
- { "RFC1213-MIB", "IP-MIB", "icmp", 4},
- { "RFC1213-MIB", "TCP-MIB", "tcp", 3},
- { "RFC1213-MIB", "UDP-MIB", "udp", 3},
- { "RFC1213-MIB", "SNMPv2-SMI", "transmission", 0},
- { "RFC1213-MIB", "SNMPv2-MIB", "snmp", 4},
- { "RFC1271-MIB", "RMON-MIB", NULL, 0},
- { "RFC1286-MIB", "SOURCE-ROUTING-MIB", "dot1dSr", 7},
- { "RFC1286-MIB", "BRIDGE-MIB", NULL, 0},
- { "RFC1315-MIB", "FRAME-RELAY-DTE-MIB", NULL, 0},
- { "RFC1316-MIB", "CHARACTER-MIB", NULL, 0},
- }; */
- #define MODULE_NOT_FOUND 0
- #define MODULE_LOADED_OK 1
- #define MODULE_ALREADY_LOADED 2
- /* #define MODULE_LOAD_FAILED 3 */
- #define MODULE_LOAD_FAILED MODULE_NOT_FOUND
- #define HASHSIZE 32
- #define BUCKET(x) (x & (HASHSIZE-1))
- #define NHASHSIZE 128
- #define NBUCKET(x) (x & (NHASHSIZE-1))
- static struct tok *buckets[HASHSIZE];
- char * module_name (int modid, char *cp);
- static struct node *nbuckets[NHASHSIZE];
- static struct tree *tbuckets[NHASHSIZE];
- static struct module *module_head = NULL;
- struct node *orphan_nodes = NULL;
- struct tree *tree_head = NULL;
- extern struct tree tree[];
- #define NUMBER_OF_ROOT_NODES 3
- static struct module_import root_imports[NUMBER_OF_ROOT_NODES];
- static int current_module = 0;
- static int max_module = 0;
- static char *last_err_module = 0; /* no repeats on "Cannot find module..." */
- #ifdef UCD_SNMP
- static void tree_from_node(struct tree *tp, struct node *np);
- static struct index_list * copy_indexes(struct index_list *);
- static void build_translation_table (void);
- static void init_tree_roots (void);
- static void unlink_tree(struct tree *);
- static void read_import_replacements (const char *, struct module_import *);
- #endif
- static void do_subtree (struct tree *, struct node **);
- static void do_linkup (struct module *, struct node *);
- static void dump_module_list (void);
- static int get_token (FILE *, char *, int);
- static int parseQuoteString (FILE *, char *, int);
- static int tossObjectIdentifier (FILE *);
- static int name_hash (const char *);
- static void init_node_hash (struct node *);
- static void print_error (const char *, const char *, int);
- static void free_tree (struct tree *);
- static void free_partial_tree (struct tree *, int);
- static void free_node (struct node *);
- static void merge_anon_children (struct tree *, struct tree *);
- static void unlink_tbucket(struct tree *);
- static int getoid (FILE *, struct subid_s *, int);
- static struct node *parse_objectid (FILE *, char *);
- static int get_tc (const char *, int, int *, struct enum_list **, struct range_list **, char **);
- static int get_tc_index (const char *, int);
- static struct enum_list *parse_enumlist (FILE *, struct enum_list **);
- static struct range_list *parse_ranges(FILE *fp, struct range_list **);
- static struct node *parse_asntype (FILE *, char *, int *, char *);
- static struct node *parse_objecttype (FILE *, char *);
- static struct node *parse_objectgroup (FILE *, char *);
- static struct node *parse_notificationDefinition (FILE *, char *);
- static struct node *parse_trapDefinition (FILE *, char *);
- static struct node *parse_compliance (FILE *, char *);
- static struct node *parse_capabilities(FILE *, char *);
- static struct node *parse_moduleIdentity (FILE *, char *);
- static struct node *parse_macro(FILE *, char *);
- static void parse_imports (FILE *);
- static struct node *parse (FILE *, struct node *);
- static int read_module_internal (const char *);
- static void read_module_replacements (const char *);
- static void new_module (const char *, const char *);
- static struct node *merge_parse_objectid (struct node *, FILE *, char *);
- static struct index_list *getIndexes(FILE *fp, struct index_list **);
- static void free_indexes(struct index_list **);
- static void free_ranges(struct range_list **);
- static void free_enums(struct enum_list **);
- static struct range_list * copy_ranges(struct range_list *);
- static struct enum_list * copy_enums(struct enum_list *);
- /* backwards compatibility wrappers */
- void snmp_set_mib_errors(int err)
- {
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_ERRORS, err);
- }
- void snmp_set_mib_warnings(int warn)
- {
- ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, warn);
- }
- void snmp_set_save_descriptions(int save)
- {
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS, save);
- }
- void snmp_set_mib_comment_term(int save)
- {
- /* 0=strict, 1=EOL terminated */
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM, save);
- }
- void snmp_set_mib_parse_label(int save)
- {
- /* 0=strict, 1=underscore OK in label */
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL, save);
- }
- /* end wrappers */
- void snmp_mib_toggle_options_usage(const char *lead, FILE *outf) {
- fprintf(outf, "%sMIBOPTS values:n", lead);
- fprintf(outf, "%s u: %sallow the usage of underlines in mib symbols.n",
- lead, ((ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL))?"dis":""));
- fprintf(outf, "%s c: %sallow the usage of "--" to terminate comments.n",
- lead, ((ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM))?"":"dis"));
- fprintf(outf, "%s d: %ssave the descriptions of the mib objects.n",
- lead, ((ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS))?"don't ":""));
- fprintf(outf, "%s e: Disable mib errors of MIB symbols conflictsn",
- lead);
- fprintf(outf, "%s w: Enable mib warnings of MIB symbols conflictsn",
- lead);
- fprintf(outf, "%s W: Enable detailed warnings of MIB symbols conflictsn",
- lead);
- fprintf(outf, "%s R: Replace MIB symbols from latest modulen",
- lead);
- }
- char *snmp_mib_toggle_options(char *options) {
- if (options) {
- while(*options) {
- switch(*options) {
- case 'u':
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL, !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL));
- break;
- case 'c':
- ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM);
- break;
- case 'e':
- ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_MIB_ERRORS);
- break;
- case 'w':
- ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, 1);
- break;
- case 'W':
- ds_set_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS, 2);
- break;
- case 'd':
- ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS);
- break;
- case 'R':
- ds_toggle_boolean(DS_LIBRARY_ID, DS_LIB_MIB_REPLACE);
- break;
- default:
- /* return at the unknown option */
- return options;
- }
- options++;
- }
- }
- return NULL;
- }
- static int
- name_hash(const char* name)
- {
- int hash = 0;
- const char *cp;
- if (name) {
- for(cp = name; *cp; cp++) {
- hash += tolower(*cp);
- }
- }
- return(hash);
- }
- static void
- init_node_hash(struct node *nodes)
- {
- register struct node *np, *nextp;
- register int hash;
- memset(nbuckets, 0, sizeof(nbuckets));
- for(np = nodes; np;){
- nextp = np->next;
- hash = NBUCKET(name_hash(np->parent));
- np->next = nbuckets[hash];
- nbuckets[hash] = np;
- np = nextp;
- }
- }
- static int erroneousMibs = 0;
- int get_mib_parse_error_count(void)
- {
- return erroneousMibs;
- }
- static void
- print_error(const char *string,
- const char *token,
- int type)
- {
- erroneousMibs++;
- DEBUGMSGTL(("parse-mibs", "n"));
- if (type == ENDOFFILE)
- snmp_log(LOG_ERR, "%s (EOF): At line %d in %sn", string, Line,
- File);
- else if (token && *token)
- snmp_log(LOG_ERR, "%s (%s): At line %d in %sn", string, token,
- Line, File);
- else
- snmp_log(LOG_ERR, "%s: At line %d in %sn", string, Line, File);
- }
- extern char *strdup (const char*);
- static void
- print_module_not_found(const char *cp)
- {
- if (!last_err_module || strcmp(cp, last_err_module))
- print_error("Cannot find module", cp, CONTINUE);
- if (last_err_module) free(last_err_module);
- last_err_module = strdup(cp);
- }
- static struct node *
- alloc_node(int modid)
- {
- struct node *np;
- np = (struct node *) calloc(1, sizeof(struct node));
- if (np) {
- np->tc_index = -1;
- np->modid = modid;
- }
- return np;
- }
- static void unlink_tbucket(struct tree *tp)
- {
- int hash = NBUCKET(name_hash(tp->label));
- struct tree *otp = NULL, *ntp = tbuckets[hash];
- while (ntp && ntp != tp) {
- otp = ntp; ntp = ntp->next;
- }
- if (!ntp) snmp_log(LOG_EMERG, "Can't find %s in tbucketsn", tp->label);
- else if (otp) otp->next = ntp->next;
- else tbuckets[hash] = tp->next;
- }
- #ifdef UCD_SNMP
- static void unlink_tree(struct tree *tp)
- {
- struct tree *otp = NULL, *ntp = tp->parent->child_list;
- while (ntp && ntp != tp) {
- otp = ntp; ntp = ntp->next_peer;
- }
- if (!ntp) snmp_log(LOG_EMERG, "Can't find %s in %s's childrenn",
- tp->label, tp->parent->label);
- else if (otp) otp->next_peer = ntp->next_peer;
- else tp->parent->child_list = tp->next_peer;
- }
- #endif
- static void
- free_partial_tree(struct tree *tp, int keep_label)
- {
- if ( !tp)
- return;
- /* remove the data from this tree node */
- free_enums(&tp->enums);
- if (!keep_label)
- SNMP_FREE(tp->label);
- SNMP_FREE(tp->hint);
- SNMP_FREE(tp->units);
- SNMP_FREE(tp->description);
- }
- /*
- * free a tree node. Note: the node must already have been unlinked
- * from the tree when calling this routine
- */
- static void
- free_tree(struct tree *Tree)
- {
- if (!Tree)
- return;
- unlink_tbucket(Tree);
- free_partial_tree (Tree, FALSE);
- #ifdef UCD_SNMP
- if (Tree->number_modules > 1 )
- free(Tree->module_list);
- #endif
- free (Tree);
- }
- static void
- free_node(struct node *np)
- {
- if ( !np) return;
- free_enums(&np->enums);
- free_ranges(&np->ranges);
- free_indexes(&np->indexes);
- if (np->label) free(np->label);
- if (np->hint) free(np->hint);
- if (np->units) free(np->units);
- if (np->description) free(np->description);
- if (np->parent) free(np->parent);
- free(np);
- }
- #ifdef TEST
- static void
- print_nodes(FILE *fp,
- struct node *root)
- {
- extern void xmalloc_stats (FILE *);
- struct enum_list *ep;
- struct index_list *ip;
- struct range_list *rp;
- struct node *np;
- for(np = root; np; np = np->next){
- fprintf(fp, "%s ::= { %s %ld } (%d)n", np->label, np->parent,
- np->subid, np->type);
- if (np->tc_index >= 0)
- fprintf(fp, " TC = %sn", tclist[np->tc_index].descriptor);
- if (np->enums){
- fprintf(fp, " Enums: n");
- for(ep = np->enums; ep; ep = ep->next){
- fprintf(fp, " %s(%d)n", ep->label, ep->value);
- }
- }
- if (np->ranges){
- fprintf(fp, " Ranges: n");
- for(rp = np->ranges; rp; rp = rp->next){
- fprintf(fp, " %d..%dn", rp->low, rp->high);
- }
- }
- if (np->indexes){
- fprintf(fp, " Indexes: n");
- for(ip = np->indexes; ip; ip = ip->next){
- fprintf(fp, " %sn", ip->ilabel);
- }
- }
- if (np->hint)
- fprintf(fp, " Hint: %sn", np->hint);
- if (np->units)
- fprintf(fp, " Units: %sn", np->units);
- }
- }
- #endif
- void
- print_subtree(FILE *f,
- struct tree *tree,
- int count)
- {
- #ifdef UCD_SNMP
- struct tree *tp;
- int i;
- char modbuf[256];
- for(i = 0; i < count; i++)
- fprintf(f, " ");
- fprintf(f, "Children of %s(%ld):n", tree->label, tree->subid);
- count++;
- for(tp = tree->child_list; tp; tp = tp->next_peer){
- for(i = 0; i < count; i++)
- fprintf(f, " ");
- fprintf(f, "%s:%s(%ld) type=%d",
- module_name(tp->module_list[0], modbuf),
- tp->label, tp->subid, tp->type);
- if (tp->tc_index != -1) fprintf(f, " tc=%d", tp->tc_index);
- if (tp->hint) fprintf(f, " hint=%s", tp->hint);
- if (tp->units) fprintf(f, " units=%s", tp->units);
- if (tp->number_modules > 1) {
- fprintf(f, " modules:");
- for (i = 1; i < tp->number_modules; i++)
- fprintf(f, " %s", module_name(tp->module_list[i], modbuf));
- }
- fprintf(f, "n");
- }
- for(tp = tree->child_list; tp; tp = tp->next_peer){
- if (tp->child_list)
- print_subtree(f, tp, count);
- }
- #endif
- }
- void
- print_ascii_dump_tree(FILE *f,
- struct tree *tree,
- int count)
- {
- struct tree *tp;
- count++;
- for(tp = tree->child_list; tp; tp = tp->next_peer){
- fprintf(f, "%s OBJECT IDENTIFIER ::= { %s %ld }n", tp->label, tree->label, tp->subid);
- }
- for(tp = tree->child_list; tp; tp = tp->next_peer){
- if (tp->child_list)
- print_ascii_dump_tree(f, tp, count);
- }
- }
- #ifdef UCD_SNMP
- static int translation_table[256];
- static void
- build_translation_table()
- {
- int count;
- for(count = 0; count < 256; count++){
- switch(count){
- case OBJID:
- translation_table[count] = TYPE_OBJID;
- break;
- case OCTETSTR:
- translation_table[count] = TYPE_OCTETSTR;
- break;
- case INTEGER:
- translation_table[count] = TYPE_INTEGER;
- break;
- case NETADDR:
- translation_table[count] = TYPE_IPADDR;
- break;
- case IPADDR:
- translation_table[count] = TYPE_IPADDR;
- break;
- case COUNTER:
- translation_table[count] = TYPE_COUNTER;
- break;
- case GAUGE:
- translation_table[count] = TYPE_GAUGE;
- break;
- case TIMETICKS:
- translation_table[count] = TYPE_TIMETICKS;
- break;
- case KW_OPAQUE:
- translation_table[count] = TYPE_OPAQUE;
- break;
- case NUL:
- translation_table[count] = TYPE_NULL;
- break;
- case COUNTER64:
- translation_table[count] = TYPE_COUNTER64;
- break;
- case BITSTRING:
- translation_table[count] = TYPE_BITSTRING;
- break;
- case NSAPADDRESS:
- translation_table[count] = TYPE_NSAPADDRESS;
- break;
- case UINTEGER32:
- translation_table[count] = TYPE_UINTEGER;
- break;
- default:
- translation_table[count] = TYPE_OTHER;
- break;
- }
- }
- }
- #endif
- /*static void
- init_tree_roots()
- {
- struct tree *tp, *lasttp;
- int base_modid;
- int hash;
- base_modid = which_module("SNMPv2-SMI");
- if (base_modid == -1 )
- base_modid = which_module("RFC1155-SMI");
- if (base_modid == -1 )
- base_modid = which_module("RFC1213-MIB");
- // build root node
- tp = (struct tree *) calloc(1, sizeof(struct tree));
- if (tp == NULL) return;
- tp->label = strdup("joint-iso-ccitt");
- #ifdef UCD_SNMP
- tp->modid = base_modid;
- tp->number_modules = 1;
- tp->module_list = &(tp->modid);
- tp->tc_index = -1;
- #endif
- tp->subid = 2;
- set_function(tp); // from mib.c
- hash = NBUCKET(name_hash(tp->label));
- tp->next = tbuckets[hash];
- tbuckets[hash] = tp;
- lasttp = tp;
- root_imports[0].label = strdup( tp->label );
- root_imports[0].modid = base_modid;
- // build root node
- tp = (struct tree *) calloc(1, sizeof(struct tree));
- if (tp == NULL) return;
- tp->next_peer = lasttp;
- tp->label = strdup("ccitt");
- #ifdef UCD_SNMP
- tp->modid = base_modid;
- tp->number_modules = 1;
- tp->module_list = &(tp->modid);
- tp->tc_index = -1;
- #endif
- tp->subid = 0;
- set_function(tp); // from mib.c
- hash = NBUCKET(name_hash(tp->label));
- tp->next = tbuckets[hash];
- tbuckets[hash] = tp;
- lasttp = tp;
- root_imports[1].label = strdup( tp->label );
- root_imports[1].modid = base_modid;
- // build root node
- tp = (struct tree *) calloc(1, sizeof(struct tree));
- if (tp == NULL) return;
- tp->next_peer = lasttp;
- tp->label = strdup("iso");
- #ifdef UCD_SNMP
- tp->modid = base_modid;
- tp->number_modules = 1;
- tp->module_list = &(tp->modid);
- tp->tc_index = -1;
- #endif
- tp->subid = 1;
- set_function(tp); // from mib.c
- hash = NBUCKET(name_hash(tp->label));
- tp->next = tbuckets[hash];
- tbuckets[hash] = tp;
- lasttp = tp;
- root_imports[2].label = strdup( tp->label );
- root_imports[2].modid = base_modid;
- tree_head = tp;
- }
- */
- #ifdef STRICT_MIB_PARSEING
- #define label_compare strcasecmp
- #else
- #define label_compare strcmp
- #endif
- struct tree *
- find_tree_node(const char *name,
- int modid)
- {
- struct tree *tp, *headtp;
- #ifdef UCD_SNMP
- int count, *int_p, i;
- #endif
- if (!name || !*name)
- return(NULL);
- headtp = tbuckets[NBUCKET(name_hash(name))];
- for ( tp = headtp ; tp ; tp = tp->next ) {
- if ( !label_compare(tp->label, name) ) {
- if ( modid == -1 ) /* Any module */
- return(tp);
- #ifdef UCD_SNMP
- for (int_p = tp->module_list, count=0 ;
- count < tp->number_modules ;
- ++count, ++int_p )
- if ( *int_p == modid )
- #endif
- return(tp);
- }
- }
- return(NULL);
- }
- /* computes a value which represents how close name1 is to name2.
- * high scores mean a worse match.
- * (yes, the algorithm sucks!)
- */
- #define MAX_BAD 0xffffff
- u_int
- compute_match(const char *search_base, const char *key) {
- #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
- int rc;
- regex_t parsetree;
- regmatch_t pmatch;
- rc=regcomp(&parsetree, key, REG_ICASE | REG_EXTENDED);
- if (rc == 0)
- rc=regexec(&parsetree, search_base, 1, &pmatch, 0);
- regfree(&parsetree);
- if (rc == 0) {
- /* found */
- return pmatch.rm_so;
- }
- #else /* use our own wildcard matcher */
- /* first find the longest matching substring (ick) */
- char *first = NULL, *result = NULL, *entry;
- const char *position;
- char *newkey = strdup(key);
- entry = strtok( newkey, "*" );
- position = search_base;
- while ( entry ) {
- result = strcasestr(position, entry);
- if (result == NULL) {
- free(newkey);
- return MAX_BAD;
- }
- if (first == NULL)
- first = result;
- position = result + strlen(entry);
- entry = strtok( NULL, "*" );
- }
- free(newkey);
- if (result)
- return(first-search_base);
- #endif
- /* not found */
- return MAX_BAD;
- }
- /*
- * Find the tree node that best matches the pattern string.
- * Use the "reported" flag such that only one match
- * is attempted for every node.
- *
- * Warning! This function may recurse.
- *
- * Caller _must_ invoke clear_tree_flags before first call
- * to this function. This function may be called multiple times
- * to ensure that the entire tree is traversed.
- */
- struct tree *
- find_best_tree_node(const char *pattrn, struct tree *tree_top, u_int *match)
- {
- struct tree *tp, *best_so_far = NULL, *retptr;
- u_int old_match=MAX_BAD, new_match=MAX_BAD;
- if (!pattrn || !*pattrn)
- return(NULL);
- if (!tree_top)
- tree_top = get_tree_head();
- for ( tp = tree_top ; tp ; tp=tp->next_peer ) {
- if (!tp->reported)
- new_match = compute_match(tp->label, pattrn);
- tp->reported = 1;
- if (new_match < old_match) {
- best_so_far = tp;
- old_match = new_match;
- }
- if (new_match == 0)
- break; /* this is the best result we can get */
- if (tp->child_list) {
- retptr = find_best_tree_node(pattrn, tp->child_list, &new_match);
- if (new_match < old_match) {
- best_so_far = retptr;
- old_match = new_match;
- }
- if (new_match == 0)
- break; /* this is the best result we can get */
- }
- }
- if (match)
- *match = old_match;
- return(best_so_far);
- }
- static void
- merge_anon_children(struct tree *tp1,
- struct tree *tp2)
- /* NB: tp1 is the 'anonymous' node */
- {
- struct tree *child1, *child2, *previous;
- for ( child1 = tp1->child_list ; child1 ; ) {
- for ( child2 = tp2->child_list, previous = NULL ;
- child2 ; previous = child2, child2 = child2->next_peer ) {
- if ( child1->subid == child2->subid ) {
- /*
- * Found 'matching' children,
- * so merge them
- */
- if ( !strncmp( child1->label, ANON, ANON_LEN)) {
- merge_anon_children( child1, child2 );
- child1->child_list = NULL;
- previous = child1; /* Finished with 'child1' */
- child1 = child1->next_peer;
- free_tree( previous );
- goto next;
- }
- else if ( !strncmp( child2->label, ANON, ANON_LEN)) {
- merge_anon_children( child2, child1 );
- if ( previous )
- previous->next_peer = child2->next_peer;
- else
- tp2->child_list = child2->next_peer;
- free_tree(child2);
- previous = child1; /* Move 'child1' to 'tp2' */
- child1 = child1->next_peer;
- previous->next_peer = tp2->child_list;
- tp2->child_list = previous;
- for ( previous = tp2->child_list ;
- previous ;
- previous = previous->next_peer )
- previous->parent = tp2;
- goto next;
- }
- else if ( !label_compare( child1->label, child2->label) ) {
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING, "Warning: %s.%ld is both %s and %s (%s)n",
- tp2->label, child1->subid,
- child1->label, child2->label, File);
- continue;
- }
- else {
- /*
- * Two copies of the same node.
- * 'child2' adopts the children of 'child1'
- */
- if ( child2->child_list ) {
- for ( previous = child2->child_list ;
- previous->next_peer ;
- previous = previous->next_peer )
- ; /* Find the end of the list */
- previous->next_peer = child1->child_list;
- }
- else
- child2->child_list = child1->child_list;
- for ( previous = child1->child_list ;
- previous ;
- previous = previous->next_peer )
- previous->parent = child2;
- child1->child_list = NULL;
- previous = child1; /* Finished with 'child1' */
- child1 = child1->next_peer;
- free_tree( previous );
- goto next;
- }
- }
- }
- /*
- * If no match, move 'child1' to 'tp2' child_list
- */
- if ( child1 ) {
- previous = child1;
- child1 = child1->next_peer;
- previous->parent = tp2;
- previous->next_peer = tp2->child_list;
- tp2->child_list = previous;
- }
- next:;
- }
- }
- /*
- * Find all the children of root in the list of nodes. Link them into the
- * tree and out of the nodes list.
- */
- static void
- do_subtree(struct tree *root,
- struct node **nodes)
- {
- #ifdef UCD_SNMP
- register struct tree *tp, *anon_tp=NULL;
- register struct node *np, **headp;
- struct node *oldnp = NULL, *child_list = NULL, *childp = NULL;
- int hash;
- int *int_p;
- tp = root;
- headp = &nbuckets[NBUCKET(name_hash(tp->label))];
- /*
- * Search each of the nodes for one whose parent is root, and
- * move each into a separate list.
- */
- for(np = *headp; np; np = np->next){
- if ( !label_compare(tp->label, np->parent)){
- /* take this node out of the node list */
- if (oldnp == NULL){
- *headp = np->next; /* fix root of node list */
- } else {
- oldnp->next = np->next; /* link around this node */
- }
- if (child_list) childp->next = np;
- else child_list = np;
- childp = np;
- }
- else {
- oldnp = np;
- }
- }
- if (childp) childp->next = NULL;
- /*
- * Take each element in the child list and place it into the tree.
- */
- for(np = child_list; np; np = np->next){
- anon_tp = NULL;
- tp = root->child_list;
- while (tp)
- if (tp->subid == np->subid) break;
- else tp = tp->next_peer;
- if (tp) {
- if (!label_compare (tp->label, np->label)) {
- /* Update list of modules */
- int_p = (int *) malloc((tp->number_modules+1) * sizeof(int));
- if (int_p == NULL) return;
- memcpy(int_p, tp->module_list, tp->number_modules*sizeof(int));
- int_p[tp->number_modules] = np->modid;
- if (tp->number_modules > 1 )
- free(tp->module_list);
- ++tp->number_modules;
- tp->module_list = int_p;
- if ( ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_REPLACE) ) {
- /* Replace from node */
- tree_from_node(tp,np);
- }
- /* Handle children */
- do_subtree(tp, nodes);
- continue;
- }
- if (!strncmp( np->label, ANON, ANON_LEN) ||
- !strncmp( tp->label, ANON, ANON_LEN)) {
- anon_tp = tp; /* Need to merge these two trees later */
- }
- else if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING, "Warning: %s.%ld is both %s and %s (%s)n",
- root->label, np->subid, tp->label, np->label, File);
- }
- tp = (struct tree *) calloc(1, sizeof(struct tree));
- if (tp == NULL) return;
- tp->parent = root;
- tp->modid = np->modid;
- tp->number_modules = 1;
- tp->module_list = &(tp->modid);
- tree_from_node(tp, np);
- tp->next_peer = root->child_list;
- root->child_list = tp;
- hash = NBUCKET(name_hash(tp->label));
- tp->next = tbuckets[hash];
- tbuckets[hash] = tp;
- /* if (tp->type == TYPE_OTHER) */
- do_subtree(tp, nodes); /* recurse on this child if it isn't
- an end node */
- if ( anon_tp ) {
- if (!strncmp( tp->label, ANON, ANON_LEN)) {
- /*
- * The new node is anonymous,
- * so merge it with the existing one.
- */
- merge_anon_children( tp, anon_tp );
- /* unlink and destroy tp */
- unlink_tree(tp);
- free_tree(tp);
- }
- else if (!strncmp( anon_tp->label, ANON, ANON_LEN)) {
- struct tree *ntp;
- /*
- * The old node was anonymous,
- * so merge it with the existing one,
- * and fill in the full information.
- */
- merge_anon_children( anon_tp, tp );
- /* unlink anon_tp from the hash */
- unlink_tbucket(anon_tp);
- /* get rid of old contents of anon_tp */
- free_partial_tree(anon_tp, FALSE);
- /* put in the current information */
- anon_tp->label = tp->label;
- anon_tp->child_list = tp->child_list;
- anon_tp->modid = tp->modid;
- anon_tp->tc_index = tp->tc_index;
- anon_tp->type = tp->type;
- anon_tp->enums = tp->enums;
- anon_tp->indexes = tp->indexes;
- anon_tp->ranges = tp->ranges;
- anon_tp->hint = tp->hint;
- anon_tp->units = tp->units;
- anon_tp->description = tp->description;
- anon_tp->parent = tp->parent;
- set_function(anon_tp);
- /* update parent pointer in moved children */
- ntp = anon_tp->child_list;
- while (ntp) {
- ntp->parent = anon_tp;
- ntp = ntp->next_peer;
- }
- /* hash in anon_tp in its new place */
- hash = NBUCKET(name_hash(anon_tp->label));
- anon_tp->next = tbuckets[hash];
- tbuckets[hash] = anon_tp;
- /* unlink and destroy tp */
- unlink_tbucket(tp);
- unlink_tree(tp);
- free(tp);
- }
- else {
- /* Uh? One of these two should have been anonymous! */
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING,
- "Warning: expected anonymous node (either %s or %s) in %sn",
- tp->label, anon_tp->label, File);
- }
- anon_tp = NULL;
- }
- }
- /* free all nodes that were copied into tree */
- oldnp = NULL;
- for(np = child_list; np; np = np->next){
- if (oldnp)
- free_node(oldnp);
- oldnp = np;
- }
- if (oldnp)
- free_node(oldnp);
- #endif
- }
- static void do_linkup(struct module *mp,
- struct node *np)
- {
- struct module_import *mip;
- struct node *onp;
- struct tree *tp;
- int i;
- /*
- * All modules implicitly import
- * the roots of the tree
- */
- if (snmp_get_do_debugging() > 1) dump_module_list();
- DEBUGMSGTL(("parse-mibs", "Processing IMPORTS for module %d %sn", mp->modid, mp->name));
- if ( mp->no_imports == 0 ) {
- mp->no_imports = NUMBER_OF_ROOT_NODES;
- mp->imports = root_imports;
- }
- /*
- * Build the tree
- */
- init_node_hash( np );
- for ( i=0, mip=mp->imports ; i < mp->no_imports ; ++i, ++mip ) {
- char modbuf[256];
- DEBUGMSGTL(("parse-mibs", " Processing import: %sn", mip->label));
- if (get_tc_index( mip->label, mip->modid ) != -1)
- continue;
- tp = find_tree_node( mip->label, mip->modid );
- if (!tp) {
- if (mip->modid != -1)
- snmp_log(LOG_WARNING, "Did not find '%s' in module %s (%s)n",
- mip->label, module_name(mip->modid, modbuf), File);
- continue;
- }
- do_subtree( tp, &np );
- }
- /*
- * If any nodes left over,
- * check that they're not the result of a "fully qualified"
- * name, and then add them to the list of orphans
- */
- if (!np) return;
- for ( tp = tree_head ; tp ; tp=tp->next_peer )
- do_subtree( tp, &np );
- if (!np) return;
- for ( np = orphan_nodes ; np && np->next ; np = np->next )
- ; /* find the end of the orphan list */
- for (i = 0; i < NHASHSIZE; i++)
- if ( nbuckets[i] ) {
- if ( orphan_nodes )
- onp = np->next = nbuckets[i];
- else
- onp = orphan_nodes = nbuckets[i];
- nbuckets[i] = NULL;
- while (onp) {
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING,
- "Unlinked OID in %s: %s ::= { %s %ld }n",
- (mp->name ? mp->name : "<no module>"),
- (onp->label ? onp->label : "<no label>"),
- (onp->parent ? onp->parent : "<no parent>"),
- onp->subid);
- np = onp;
- onp = onp->next;
- }
- }
- return;
- }
- /*
- * Takes a list of the form:
- * { iso org(3) dod(6) 1 }
- * and creates several nodes, one for each parent-child pair.
- * Returns 0 on error.
- */
- static int
- getoid(FILE *fp,
- struct subid_s *id, /* an array of subids */
- int length) /* the length of the array */
- {
- register int count;
- int type;
- char token[MAXTOKEN];
- if ((type = get_token(fp, token, MAXTOKEN)) != LEFTBRACKET){
- print_error("Expected "{"", token, type);
- return 0;
- }
- type = get_token(fp, token, MAXTOKEN);
- for(count = 0; count < length; count++, id++){
- id->label = NULL;
- id->modid = current_module;
- id->subid = -1;
- if (type == RIGHTBRACKET){
- return count;
- } else if (type != LABEL && type != NUMBER){
- print_error("Not valid for object identifier", token, type);
- return 0;
- }
- if (type == LABEL){
- /* this entry has a label */
- id->label = strdup(token);
- type = get_token(fp, token, MAXTOKEN);
- if (type == LEFTPAREN){
- type = get_token(fp, token, MAXTOKEN);
- if (type == NUMBER){
- id->subid = atoi(token);
- if ((type = get_token(fp, token, MAXTOKEN)) != RIGHTPAREN){
- print_error("Expected a closing parenthesis",
- token, type);
- return 0;
- }
- } else {
- print_error("Expected a number", token, type);
- return 0;
- }
- } else {
- continue;
- }
- } else if (type == NUMBER) {
- /* this entry has just an integer sub-identifier */
- id->subid = atoi(token);
- }
- else {
- print_error("Expected label or number", token, type);
- return 0;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- print_error ("Too long OID", token, type);
- return 0;
- }
- /*
- * Parse a sequence of object subidentifiers for the given name.
- * The "label OBJECT IDENTIFIER ::=" portion has already been parsed.
- *
- * The majority of cases take this form :
- * label OBJECT IDENTIFIER ::= { parent 2 }
- * where a parent label and a child subidentifier number are specified.
- *
- * Variations on the theme include cases where a number appears with
- * the parent, or intermediate subidentifiers are specified by label,
- * by number, or both.
- *
- * Here are some representative samples :
- * internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }
- * mgmt OBJECT IDENTIFIER ::= { internet 2 }
- * rptrInfoHealth OBJECT IDENTIFIER ::= { snmpDot3RptrMgt 0 4 }
- *
- * Here is a very rare form :
- * iso OBJECT IDENTIFIER ::= { 1 }
- *
- * Returns NULL on error. When this happens, memory may be leaked.
- */
- static struct node *
- parse_objectid(FILE *fp,
- char *name)
- {
- register int count;
- register struct subid_s *op, *nop;
- int length;
- struct subid_s loid[32];
- struct node *np, *root = NULL, *oldnp = NULL;
- struct tree *tp;
- if ((length = getoid(fp, loid, 32)) == 0){
- print_error("Bad object identifier", NULL, CONTINUE);
- return NULL;
- }
- /*
- * Handle numeric-only object identifiers,
- * by labelling the first sub-identifier
- */
- op = loid;
- if ( !op->label )
- for ( tp = tree_head ; tp ; tp=tp->next_peer )
- if ( (int)tp->subid == op->subid ) {
- op->label = strdup(tp->label);
- break;
- }
- /*
- * Handle "label OBJECT-IDENTIFIER ::= { subid }"
- */
- if (length == 1) {
- op = loid;
- np = alloc_node(op->modid);
- if (np == NULL) return(NULL);
- np->subid = op->subid;
- np->label = strdup(name);
- if (op->label) free(op->label);
- return np;
- }
- /*
- * For each parent-child subid pair in the subid array,
- * create a node and link it into the node list.
- */
- for(count = 0, op = loid, nop=loid+1; count < (length - 1);
- count++, op++, nop++){
- /* every node must have parent's name and child's name or number */
- /* XX the next statement is always true -- does it matter ?? */
- if (op->label && (nop->label || (nop->subid != -1))){
- np = alloc_node(nop->modid);
- if (np == NULL) return(NULL);
- if (root == NULL) root = np;
- np->parent = strdup (op->label);
- if (count == (length - 2)) {
- /* The name for this node is the label for this entry */
- np->label = strdup (name);
- }
- else {
- if (!nop->label) {
- nop->label = (char *) malloc(20 + ANON_LEN);
- if (nop->label == NULL) return(NULL);
- sprintf(nop->label, "%s%d", ANON, anonymous++);
- }
- np->label = strdup (nop->label);
- }
- if (nop->subid != -1)
- np->subid = nop->subid;
- else
- print_error("Warning: This entry is pretty silly",
- np->label, CONTINUE);
- /* set up next entry */
- if (oldnp) oldnp->next = np;
- oldnp = np;
- } /* end if(op->label... */
- }
- /* free the loid array */
- for(count = 0, op = loid; count < length; count++, op++){
- if (op->label)
- free(op->label);
- }
- return root;
- }
- static int
- get_tc(const char *descriptor,
- int modid,
- int *tc_index,
- struct enum_list **ep,
- struct range_list **rp,
- char **hint)
- {
- int i;
- struct tc *tcp;
- i = get_tc_index(descriptor, modid);
- if (tc_index) *tc_index = i;
- if (i != -1)
- {
- tcp = &tclist[i];
- if (ep) {
- free_enums(ep);
- *ep = copy_enums(tcp->enums);
- }
- if (rp) {
- free_ranges(rp);
- *rp = copy_ranges(tcp->ranges);
- }
- if (hint) {
- if (*hint) free(*hint);
- *hint = (tcp->hint ? strdup(tcp->hint) : NULL);
- }
- return tcp->type;
- }
- return LABEL;
- }
- /* return index into tclist of given TC descriptor
- return -1 if not found
- */
- static int
- get_tc_index(const char *descriptor,
- int modid)
- {
- int i;
- struct tc *tcp;
- struct module *mp;
- struct module_import *mip;
- /*
- * Check that the descriptor isn't imported
- * by searching the import list
- */
- for ( mp = module_head ; mp ; mp = mp->next )
- if ( mp->modid == modid )
- break;
- if ( mp )
- for ( i=0, mip=mp->imports ; i < mp->no_imports ; ++i, ++mip ) {
- if ( !label_compare( mip->label, descriptor )) {
- /* Found it - so amend the module ID */
- modid = mip->modid;
- break;
- }
- }
- for(i=0, tcp=tclist; i < MAXTC; i++, tcp++){
- if (tcp->type == 0)
- break;
- if (!label_compare(descriptor, tcp->descriptor) &&
- ((modid == tcp->modid) || (modid == -1))){
- return i;
- }
- }
- return -1;
- }
- /* translate integer tc_index to string identifier from tclist
- *
- * Returns pointer to string in table (should not be modified) or NULL
- */
- const char *
- get_tc_descriptor(int tc_index)
- {
- if (tc_index < 0 || tc_index >= MAXTC) return NULL;
- return (tclist[tc_index].descriptor);
- }
- /*
- * Parses an enumeration list of the form:
- * { label(value) label(value) ... }
- * The initial { has already been parsed.
- * Returns NULL on error.
- */
- static struct enum_list *
- parse_enumlist(FILE *fp, struct enum_list **retp)
- {
- register int type;
- char token [MAXTOKEN];
- struct enum_list *ep = NULL, **epp = &ep;
- free_enums(retp);
- while((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE){
- if (type == RIGHTBRACKET)
- break;
- if (type == LABEL){
- /* this is an enumerated label */
- *epp = (struct enum_list *) calloc(1, sizeof(struct enum_list));
- if (*epp == NULL) return(NULL);
- /* a reasonable approximation for the length */
- (*epp)->label = strdup(token);
- type = get_token(fp, token, MAXTOKEN);
- if (type != LEFTPAREN) {
- print_error("Expected "("", token, type);
- return NULL;
- }
- type = get_token(fp, token, MAXTOKEN);
- if (type != NUMBER) {
- print_error("Expected integer", token, type);
- return NULL;
- }
- (*epp)->value = atoi(token);
- type = get_token(fp, token, MAXTOKEN);
- if (type != RIGHTPAREN) {
- print_error("Expected ")"", token, type);
- return NULL;
- }
- epp = &(*epp)->next;
- }
- }
- if (type == ENDOFFILE){
- print_error("Expected "}"", token, type);
- return NULL;
- }
- *retp = ep;
- return ep;
- }
- static struct range_list *parse_ranges(FILE *fp, struct range_list **retp)
- { int low, high;
- char nexttoken[MAXTOKEN];
- int nexttype;
- struct range_list *rp = NULL, **rpp = &rp;
- int size = 0, taken = 1;
- free_ranges(retp);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- if (nexttype == SIZE) {
- size = 1;
- taken = 0;
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- if (nexttype != LEFTPAREN)
- print_error("Expected "(" after SIZE", nexttoken, nexttype);
- }
- do {
- if (!taken) nexttype = get_token(fp, nexttoken, MAXTOKEN);
- else taken = 0;
- high = low = atol(nexttoken);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- if (nexttype == RANGE) {
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- high = atol(nexttoken);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- }
- *rpp = (struct range_list *)calloc (1, sizeof(struct range_list));
- if (*rpp == NULL) break;
- (*rpp)->low = low;
- (*rpp)->high = high;
- rpp = &(*rpp)->next;
- } while (nexttype == BAR);
- if (size) {
- if (nexttype != RIGHTPAREN)
- print_error ("Expected ")" after SIZE", nexttoken, nexttype);
- nexttype = get_token(fp, nexttoken, nexttype);
- }
- if (nexttype != RIGHTPAREN)
- print_error ("Expected ")"", nexttoken, nexttype);
- *retp = rp;
- return rp;
- }
- /*
- * Parses an asn type. Structures are ignored by this parser.
- * Returns NULL on error.
- */
- static struct node *
- parse_asntype(FILE *fp,
- char *name,
- int *ntype,
- char *ntoken)
- {
- int type, i;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- char *hint = NULL;
- struct tc *tcp;
- int level;
- type = get_token(fp, token, MAXTOKEN);
- if (type == SEQUENCE){
- level = 0;
- while((type = get_token(fp, token, MAXTOKEN)) != ENDOFFILE){
- if (type == LEFTBRACKET){
- level++;
- }
- else if (type == RIGHTBRACKET && --level == 0){
- *ntype = get_token(fp, ntoken, MAXTOKEN);
- return NULL;
- }
- }
- print_error("Expected "}"", token, type);
- return NULL;
- } else if (type == LEFTBRACKET) {
- struct node *np;
- int ch_next = '{';
- ungetc(ch_next, fp);
- np = parse_objectid (fp, name);
- if (np != NULL) {
- *ntype = get_token(fp, ntoken, MAXTOKEN);
- return np;
- }
- return NULL;
- } else {
- if (type == CONVENTION) {
- while (type != SYNTAX && type != ENDOFFILE) {
- if (type == DISPLAYHINT) {
- type = get_token(fp, token, MAXTOKEN);
- if (type != QUOTESTRING) print_error("DISPLAY-HINT must be string", token, type);
- else hint = strdup (token);
- }
- else
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- if (type == LABEL)
- {
- type = get_tc(token, current_module, NULL, NULL, NULL, NULL);
- }
- /* textual convention */
- for(i = 0; i < MAXTC; i++){
- if (tclist[i].type == 0)
- break;
- }
- if (i == MAXTC){
- print_error("Too many textual conventions", token, type);
- SNMP_FREE(hint);
- return NULL;
- }
- if (!(type & SYNTAX_MASK)){
- print_error("Textual convention doesn't map to real type", token,
- type);
- SNMP_FREE(hint);
- return NULL;
- }
- tcp = &tclist[i];
- tcp->modid = current_module;
- tcp->descriptor = strdup(name);
- tcp->hint = hint;
- tcp->type = type;
- *ntype = get_token(fp, ntoken, MAXTOKEN);
- if (*ntype == LEFTPAREN){
- tcp->ranges = parse_ranges(fp, &tcp->ranges);
- *ntype = get_token(fp, ntoken, MAXTOKEN);
- } else if (*ntype == LEFTBRACKET) {
- /* if there is an enumeration list, parse it */
- tcp->enums = parse_enumlist(fp, &tcp->enums);
- *ntype = get_token(fp, ntoken, MAXTOKEN);
- }
- return NULL;
- }
- }
- /*
- * Parses an OBJECT TYPE macro.
- * Returns 0 on error.
- */
- static struct node *
- parse_objecttype(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char nexttoken[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- int nexttype, tctype;
- register struct node *np;
- type = get_token(fp, token, MAXTOKEN);
- if (type != SYNTAX){
- print_error("Bad format for OBJECT-TYPE", token, type);
- return NULL;
- }
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- if (type == LABEL){
- int tmp_index;
- tctype = get_tc(token, current_module, &tmp_index,
- &np->enums, &np->ranges, &np->hint);
- if (tctype == LABEL &&
- ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS) > 1){
- print_error("Warning: No known translation for type", token, type);
- }
- type = tctype;
- np->tc_index = tmp_index; /* store TC for later reference */
- }
- np->type = type;
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- switch(type){
- case SEQUENCE:
- if (nexttype == OF){
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- }
- break;
- case INTEGER:
- case UINTEGER32:
- case COUNTER:
- case GAUGE:
- case BITSTRING:
- case LABEL:
- if (nexttype == LEFTBRACKET) {
- /* if there is an enumeration list, parse it */
- np->enums = parse_enumlist(fp, &np->enums);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- } else if (nexttype == LEFTPAREN){
- /* if there is a range list, parse it */
- np->ranges = parse_ranges(fp, &np->ranges);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- }
- break;
- case OCTETSTR:
- case KW_OPAQUE:
- /* parse any SIZE specification */
- if (nexttype == LEFTPAREN) {
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- if (nexttype == SIZE) {
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- if (nexttype == LEFTPAREN) {
- np->ranges = parse_ranges(fp, &np->ranges);
- nexttype = get_token(fp, nexttoken, MAXTOKEN); /* ) */
- if (nexttype == RIGHTPAREN)
- {
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- break;
- }
- }
- }
- print_error("Bad SIZE syntax", token, type);
- free_node(np);
- return NULL;
- }
- break;
- case OBJID:
- case NETADDR:
- case IPADDR:
- case TIMETICKS:
- case NUL:
- case NSAPADDRESS:
- case COUNTER64:
- break;
- default:
- print_error("Bad syntax", token, type);
- free_node(np);
- return NULL;
- }
- if (nexttype == UNITS){
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad UNITS", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- np->units = strdup (quoted_string_buffer);
- nexttype = get_token(fp, nexttoken, MAXTOKEN);
- }
- if (nexttype != ACCESS){
- print_error("Should be ACCESS", nexttoken, nexttype);
- free_node(np);
- return NULL;
- }
- type = get_token(fp, token, MAXTOKEN);
- if (type != READONLY && type != READWRITE && type != WRITEONLY
- && type != NOACCESS && type != READCREATE && type != ACCNOTIFY){
- print_error("Bad ACCESS type", token, type);
- free_node(np);
- return NULL;
- }
- np->access = type;
- type = get_token(fp, token, MAXTOKEN);
- if (type != STATUS){
- print_error("Should be STATUS", token, type);
- free_node(np);
- return NULL;
- }
- type = get_token(fp, token, MAXTOKEN);
- if (type != MANDATORY && type != CURRENT && type != KW_OPTIONAL &&
- type != OBSOLETE && type != DEPRECATED){
- print_error("Bad STATUS", token, type);
- free_node(np);
- return NULL;
- }
- np->status = type;
- /*
- * Optional parts of the OBJECT-TYPE macro
- */
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- switch (type) {
- case DESCRIPTION:
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad DESCRIPTION", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) {
- np->description = strdup (quoted_string_buffer);
- }
- break;
- case REFERENCE:
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad REFERENCE", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- break;
- case INDEX:
- np->indexes = getIndexes(fp, &np->indexes);
- if (np->indexes == NULL) {
- print_error("Bad Index List",token,type);
- free_node(np);
- return NULL;
- }
- break;
- case DEFVAL:
- case AUGMENTS:
- case NUM_ENTRIES:
- if (tossObjectIdentifier(fp) != OBJID) {
- print_error("Bad Object Identifier", token, type);
- free_node(np);
- return NULL;
- }
- break;
- default:
- print_error("Bad format of optional clauses", token, type);
- free_node(np);
- return NULL;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- if (type != EQUALS){
- print_error("Bad format", token, type);
- free_node(np);
- return NULL;
- }
- return merge_parse_objectid(np, fp, name);
- }
- /*
- * Parses an OBJECT GROUP macro.
- * Returns 0 on error.
- *
- * Also parses object-identity, since they are similar (ignore STATUS).
- * - WJH 10/96
- */
- static struct node *
- parse_objectgroup(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- register struct node *np;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- switch (type) {
- case DESCRIPTION:
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad DESCRIPTION", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) {
- np->description = strdup (quoted_string_buffer);
- }
- break;
- case REFERENCE:
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad REFERENCE", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- break;
- default:
- /* NOTHING */
- break;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- return merge_parse_objectid(np, fp, name);
- }
- /*
- * Parses a NOTIFICATION-TYPE macro.
- * Returns 0 on error.
- */
- static struct node *
- parse_notificationDefinition(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- register struct node *np;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- switch (type) {
- case DESCRIPTION:
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad DESCRIPTION", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) {
- np->description = strdup (quoted_string_buffer);
- }
- break;
- default:
- /* NOTHING */
- break;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- return merge_parse_objectid(np, fp, name);
- }
- /*
- * Parses a TRAP-TYPE macro.
- * Returns 0 on error.
- */
- static struct node *
- parse_trapDefinition(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- register struct node *np;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- switch (type) {
- case DESCRIPTION:
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- if (type != QUOTESTRING) {
- print_error("Bad DESCRIPTION", quoted_string_buffer, type);
- free_node(np);
- return NULL;
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_SAVE_MIB_DESCRS)) {
- np->description = strdup (quoted_string_buffer);
- }
- break;
- case ENTERPRISE:
- type = get_token(fp, token, MAXTOKEN);
- if (type == LEFTBRACKET) {
- type = get_token(fp, token, MAXTOKEN);
- if (type != LABEL) {
- print_error("Bad Trap Format", token, type);
- free_node(np);
- return NULL;
- }
- np->parent = strdup(token);
- /* Get right bracket */
- type = get_token(fp, token, MAXTOKEN);
- }
- else if (type == LABEL)
- np->parent = strdup(token);
- break;
- default:
- /* NOTHING */
- break;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- type = get_token(fp, token, MAXTOKEN);
- np->label = strdup(name);
- if (type != NUMBER) {
- print_error("Expected a Number", token, type);
- free_node(np);
- return NULL;
- }
- np->subid = atoi(token);
- np->next = alloc_node(current_module);
- if (np->next == NULL) {
- free_node(np);
- return(NULL);
- }
- np->next->parent = np->parent;
- np->parent = (char *)malloc(strlen(np->parent)+2);
- if (np->parent == NULL) {
- free_node(np->next); free_node(np);
- return(NULL);
- }
- strcpy(np->parent, np->next->parent);
- strcat(np->parent, "#");
- np->next->label = strdup(np->parent);
- return np;
- }
- /*
- * Parses a compliance macro
- * Returns 0 on error.
- */
- static struct node *
- parse_compliance(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- register struct node *np;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- }
- return merge_parse_objectid(np, fp, name);
- }
- /*
- * Parses a capabilities macro
- * Returns 0 on error.
- */
- static struct node *
- parse_capabilities(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- register struct node *np;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- }
- return merge_parse_objectid(np, fp, name);
- }
- /*
- * Parses a module identity macro
- * Returns 0 on error.
- */
- static struct node *
- parse_moduleIdentity(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- char quoted_string_buffer[MAXQUOTESTR];
- register struct node *np;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, MAXTOKEN);
- while (type != EQUALS && type != ENDOFFILE) {
- type = get_token(fp, quoted_string_buffer, MAXQUOTESTR);
- }
- return merge_parse_objectid(np, fp, name);
- }
- /*
- * Parses a MACRO definition
- * Expect BEGIN, discard everything to end.
- * Returns 0 on error.
- */
- static struct node *
- parse_macro(FILE *fp,
- char *name)
- {
- register int type;
- char token[MAXTOKEN];
- struct node *np;
- int iLine = Line;
- np = alloc_node(current_module);
- if (np == NULL) return(NULL);
- type = get_token(fp, token, sizeof(token));
- while (type != EQUALS && type != ENDOFFILE) {
- type = get_token(fp, token, sizeof(token));
- }
- if (type != EQUALS) return NULL;
- while (type != BEGIN && type != ENDOFFILE) {
- type = get_token(fp, token, sizeof(token));
- }
- if (type != BEGIN) return NULL;
- while (type != END && type != ENDOFFILE) {
- type = get_token(fp, token, sizeof(token));
- }
- if (type != END) return NULL;
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING,
- "%s MACRO (lines %d..%d parsed and ignored).n", name, iLine, Line);
- return np;
- }
- /*
- * Parses a module import clause
- * loading any modules referenced
- */
- static void
- parse_imports(FILE *fp)
- {
- #ifdef UCD_SNMP
- register int type;
- char token[MAXTOKEN];
- char modbuf[256];
- #define MAX_IMPORTS 256
- struct module_import import_list[MAX_IMPORTS];
- int this_module, old_current_module;
- const char *old_File;
- int old_line;
- struct module *mp;
- int import_count=0; /* Total number of imported descriptors */
- int i=0, old_i; /* index of first import from each module */
- type = get_token(fp, token, MAXTOKEN);
- /*
- * Parse the IMPORTS clause
- */
- while (type != SEMI && type != ENDOFFILE) {
- if (type == LABEL ) {
- if (import_count == MAX_IMPORTS ) {
- print_error("Too many imported symbols", token, type);
- do {
- type = get_token(fp, token, MAXTOKEN);
- } while (type != SEMI && type != ENDOFFILE);
- return;
- }
- import_list[import_count++].label = strdup(token);
- }
- else if ( type == FROM ) {
- type = get_token(fp, token, MAXTOKEN);
- if ( import_count == i ) { /* All imports are handled internally */
- type = get_token(fp, token, MAXTOKEN);
- continue;
- }
- this_module = which_module(token);
- for ( old_i=i ; i<import_count ; ++i)
- import_list[i].modid = this_module;
- old_current_module = current_module; /* Save state */
- old_File = File;
- old_line = Line;
- current_module = this_module;
- /*
- * Recursively read any pre-requisite modules
- */
- if (read_module_internal(token) == MODULE_NOT_FOUND ) {
- for ( ; old_i<import_count ; ++old_i ) {
- read_import_replacements( token, &import_list[old_i]);
- }
- }
- current_module = old_current_module; /* Restore state */
- File = old_File;
- Line = old_line;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- /*
- * Save the import information
- * in the global module table
- */
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( mp->modid == current_module) {
- if ( import_count == 0)
- return;
- if (mp->imports && (mp->imports != root_imports))
- {
- /* this can happen if all modules are in one source file. */
- for ( i=0 ; i<mp->no_imports; ++i ) {
- DEBUGMSGTL(("parse-mibs", "#### freeing Module %d '%s' %dn",
- mp->modid, mp->imports[i].label, mp->imports[i].modid));
- free(mp->imports[i].label);
- }
- free(mp->imports);
- }
- mp->imports = (struct module_import *)
- calloc(import_count, sizeof(struct module_import));
- if (mp->imports == NULL) return;
- for ( i=0 ; i<import_count ; ++i ) {
- mp->imports[i].label = import_list[i].label;
- mp->imports[i].modid = import_list[i].modid;
- DEBUGMSGTL(("parse-mibs", "#### adding Module %d '%s' %dn",
- mp->modid, mp->imports[i].label, mp->imports[i].modid));
- }
- mp->no_imports = import_count;
- return;
- }
- /*
- * Shouldn't get this far
- */
- print_module_not_found(module_name(current_module,modbuf));
- return;
- #endif
- }
- /*
- * MIB module handling routines
- */
- static void dump_module_list (void)
- {
- struct module *mp = module_head;
- DEBUGMSGTL(("parse-mibs", "Module list:n"));
- while (mp) {
- DEBUGMSGTL(("parse-mibs", " %s %d %s %dn", mp->name, mp->modid, mp->file, mp->no_imports));
- mp = mp->next;
- }
- }
- int
- which_module(const char *name)
- {
- struct module *mp;
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( !label_compare(mp->name, name))
- return(mp->modid);
- DEBUGMSGTL(("parse-mibs", "Module %s not foundn", name));
- return(-1);
- }
- /*
- * module_name - copy module name to user buffer, return ptr to same.
- */
- char *
- module_name (int modid,
- char *cp)
- {
- struct module *mp;
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( mp->modid == modid )
- {
- strcpy(cp, mp->name);
- return(cp);
- }
- DEBUGMSGTL(("parse-mibs", "Module %d not foundn", modid));
- sprintf(cp, "#%d", modid);
- return(cp);
- }
- /*
- * Backwards compatability
- * Read newer modules that replace the one specified:-
- * either all of them (read_module_replacements),
- * or those relating to a specified identifier (read_import_replacements)
- * plus an interface to add new replacement requirements
- */
- void
- add_module_replacement(const char *old_module,
- const char *new_module_name,
- const char *tag,
- int len)
- {
- struct module_compatability *mcp;
- mcp = (struct module_compatability *)
- calloc(1, sizeof( struct module_compatability));
- if (mcp == NULL) return;
- mcp->old_module = strdup( old_module );
- mcp->new_module = strdup( new_module_name );
- if (tag)
- mcp->tag = strdup( tag );
- mcp->tag_len = len;
- mcp->next = module_map_head;
- module_map_head = mcp;
- }
- static void
- read_module_replacements(const char *name)
- {
- struct module_compatability *mcp;
- for ( mcp=module_map_head ; mcp; mcp=mcp->next ) {
- if ( !label_compare( mcp->old_module, name )) {
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING,
- "Loading replacement module %s for %s (%s)n",
- mcp->new_module, name, File);
- (void)read_module( mcp->new_module );
- return;
- }
- }
- if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_ERRORS))
- print_module_not_found(name);
- }
- #ifdef UCD_SNMP
- static void
- read_import_replacements(const char *old_module_name,
- struct module_import *identifier)
- {
- struct module_compatability *mcp;
- /*
- * Look for matches first
- */
- for ( mcp=module_map_head ; mcp; mcp=mcp->next ) {
- if ( !label_compare( mcp->old_module, old_module_name )) {
- if ( /* exact match */
- ( mcp->tag_len==0 &&
- (mcp->tag == NULL ||
- !label_compare( mcp->tag, identifier->label ))) ||
- /* prefix match */
- ( mcp->tag_len!=0 &&
- !strncmp( mcp->tag, identifier->label, mcp->tag_len ))
- ) {
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING,
- "Importing %s from replacement module %s instead of %s (%s)n",
- identifier->label, mcp->new_module, old_module_name, File);
- (void)read_module( mcp->new_module );
- identifier->modid = which_module(mcp->new_module);
- return; /* finished! */
- }
- }
- }
- /*
- * If no exact match, load everything relevant
- */
- read_module_replacements( old_module_name );
- }
- #endif
- /*
- * Read in the named module
- * Returns the root of the whole tree
- * (by analogy with 'read_mib')
- */
- static int
- read_module_internal (const char *name)
- {
- struct module *mp;
- FILE *fp;
- struct node *np;
- if ( tree_head == NULL )
- init_mib_internals(); /* was init_mib */
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( !label_compare(mp->name, name)) {
- const char *oldFile = File;
- int oldLine = Line;
- if ( mp->no_imports != -1 ) {
- DEBUGMSGTL(("parse-mibs", "Module %s already loadedn", name));
- return MODULE_ALREADY_LOADED;
- }
- if ((fp = fopen(mp->file, "r")) == NULL) {
- snmp_log_perror(mp->file);
- return MODULE_LOAD_FAILED;
- }
- mp->no_imports=0; /* Note that we've read the file */
- File = mp->file;
- Line = 1;
- /*
- * Parse the file
- */
- np = parse( fp, NULL );
- fclose(fp);
- File = oldFile;
- Line = oldLine;
- return MODULE_LOADED_OK;
- }
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS) > 1)
- snmp_log(LOG_WARNING, "Module %s not foundn", name);
- return MODULE_NOT_FOUND;
- }
- void
- adopt_orphans (void)
- {
- struct node *np, *onp;
- struct tree *tp = NULL;
- int i, adopted;
- if ( !orphan_nodes )
- return;
- init_node_hash(orphan_nodes);
- orphan_nodes = NULL;
- while (1) {
- adopted = 0;
- for ( i = 0; i < NHASHSIZE; i++)
- if ( nbuckets[i] ) {
- for ( np = nbuckets[i] ; np!= NULL ; np=np->next )
- tp = find_tree_node( np->parent, -1 );
- if ( tp ) {
- do_subtree( tp, &np );
- adopted = 1;
- }
- }
- if ( adopted == 0 )
- break;
- }
- /*
- * Report on outstanding orphans
- * and link them back into the orphan list
- */
- for (i = 0; i < NHASHSIZE; i++)
- if ( nbuckets[i] ) {
- if ( orphan_nodes )
- onp = np->next = nbuckets[i];
- else
- onp = orphan_nodes = nbuckets[i];
- nbuckets[i] = NULL;
- while (onp) {
- char modbuf[256];
- snmp_log (LOG_WARNING,
- "Unlinked OID in %s: %s ::= { %s %ld }n",
- module_name(onp->modid, modbuf),
- (onp->label ? onp->label : "<no label>"),
- (onp->parent ? onp->parent : "<no parent>"),
- onp->subid);
- np = onp;
- onp = onp->next;
- }
- }
- }
- struct tree *
- read_module(const char *name)
- {
- if ( read_module_internal(name) == MODULE_NOT_FOUND )
- read_module_replacements( name );
- return tree_head;
- }
- void
- unload_module_by_ID( int modID, struct tree *tree_top )
- {
- #ifdef UCD_SNMP
- struct tree *tp, *prev, *next;
- int i;
- prev = NULL;
- for ( tp=tree_top ; tp ; tp=next ) {
- next = tp->next_peer;
- /*
- * This next section looks rather complex.
- * Essentially, this is equivalent to the code fragment:
- * if (tp->modID = modID)
- * tp->number_modules--;
- * but handles one tree node being part of several modules.
- */
- for ( i=0 ; i<tp->number_modules ; i++ ) {
- if ( tp->module_list[i] == modID ) {
- tp->number_modules--;
- switch ( tp->number_modules ) {
- case 0: /* That was the only module */
- tp->modid = -1; /* Mark as unused */
- break;
- case 1: /* We did have a list of two, but this is no
- longer needed. Transfer the other entry
- ( i.e. module_list[1-i] - think about it! )
- to the 'single' slot tp->modid, and discard
- the list.
- */
- tp->modid = tp->module_list[1-i];
- free(tp->module_list);
- tp->module_list = NULL; /* let's be tidy */
- break;
- default: /* We still need the list, so shuffle down
- all following entries to close up the gap */
- while ( i < tp->number_modules ) {
- tp->module_list[i] = tp->module_list[i+1];
- i++;
- }
- break;
- }
- break; /* Don't need to look through the rest of the list */
- }
- }
- /*
- * OK - that's dealt with *this* node.
- * Now let's look at the children.
- * (Isn't recursion wonderful!)
- */
- if ( tp->child_list )
- unload_module_by_ID( modID, tp->child_list );
- if ( tp->number_modules == 0 ) {
- /* This node isn't needed any more (except perhaps
- for the sake of the children) */
- if ( tp->child_list == NULL ) {
- if ( prev )
- prev->next_peer = tp->next_peer;
- else
- tp->parent->child_list = tp->next_peer;
- free_tree( tp );
- }
- else
- free_partial_tree( tp, TRUE );
- }
- else
- prev = tp;
- }
- #endif
- }
- int
- unload_module(const char *name)
- {
- struct module *mp;
- int modID = -1;
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( !label_compare(mp->name, name)) {
- modID = mp->modid;
- break;
- }
- if ( modID == -1 ) {
- DEBUGMSGTL(("unload-mib", "Module %s not found to unloadn", name));
- return MODULE_NOT_FOUND;
- }
- unload_module_by_ID( modID, tree_head );
- mp->no_imports = -1; /* mark as unloaded */
- return MODULE_LOADED_OK; /* Well, you know what I mean! */
- }
- static void
- new_module (const char *name,
- const char *file)
- {
- struct module *mp;
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( !label_compare(mp->name, name)) {
- DEBUGMSGTL(("parse-mibs", "Module %s already notedn", name));
- /* Not the same file */
- if (label_compare(mp->file, file)) {
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- snmp_log(LOG_WARNING,
- "Warning: Module %s was in %s now is %sn",
- name, mp->file, file);
- /* Use the new one in preference */
- free(mp->file);
- mp->file = strdup(file);
- }
- return;
- }
- /* Add this module to the list */
- DEBUGMSGTL(("parse-mibs", " Module %d %s is in %sn", max_module, name, file));
- mp = (struct module *) calloc(1, sizeof(struct module));
- if (mp == NULL) return;
- mp->name = strdup(name);
- mp->file = strdup(file);
- mp->imports = NULL;
- mp->no_imports = -1; /* Not yet loaded */
- mp->modid = max_module;
- ++max_module;
- mp->next = module_head; /* Or add to the *end* of the list? */
- module_head = mp;
- }
- /*
- * Parses a mib file and returns a linked list of nodes found in the file.
- * Returns NULL on error.
- */
- static struct node *
- parse(FILE *fp,
- struct node *root)
- {
- char token[MAXTOKEN];
- char name[MAXTOKEN];
- int type = LABEL;
- int lasttype = LABEL;
- #define BETWEEN_MIBS 1
- #define IN_MIB 2
- int state = BETWEEN_MIBS;
- struct node *np, *nnp;
- DEBUGMSGTL(("parse-file", "Parsing file: %s...n", File));
- if (last_err_module) free(last_err_module); last_err_module = 0;
- np = root;
- if (np != NULL) {
- /* now find end of chain */
- while(np->next)
- np = np->next;
- }
- while (type != ENDOFFILE){
- if (lasttype == CONTINUE) lasttype = type;
- else type = lasttype = get_token(fp, token, MAXTOKEN);
- switch (type) {
- case END:
- if (state != IN_MIB){
- print_error("Error, END before start of MIB", NULL, type);
- return NULL;
- }
- else {
- struct module *mp;
- #ifdef TEST
- printf("nNodes for Module %s:n", name);
- print_nodes( stdout, np );
- #endif
- for (mp = module_head; mp; mp = mp->next)
- if (mp->modid == current_module) break;
- do_linkup(mp, root);
- np = root = NULL;
- }
- state = BETWEEN_MIBS;
- #ifdef TEST
- if (ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS))
- xmalloc_stats (stderr);
- #endif
- continue;
- case IMPORTS:
- parse_imports( fp );
- continue;
- case EXPORTS:
- while (type != SEMI && type != ENDOFFILE)
- type = get_token(fp, token, MAXTOKEN);
- continue;
- case LABEL:
- break;
- case ENDOFFILE:
- continue;
- default:
- strcpy(name, token);
- type = get_token(fp, token, MAXTOKEN);
- nnp = NULL;
- if (type == MACRO) {
- nnp = parse_macro(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of MACRO", NULL, type);
- /*return NULL;*/
- }
- free_node(nnp); /* IGNORE */
- nnp = NULL;
- }
- else
- print_error(name, "is a reserved word", lasttype);
- continue; /* see if we can parse the rest of the file */
- }
- strcpy(name, token);
- type = get_token(fp, token, MAXTOKEN);
- nnp = NULL;
- /* Handle obsolete method to assign an object identifier to a
- module*/
- if (lasttype == LABEL && type == LEFTBRACKET) {
- while (type != RIGHTBRACKET && type != ENDOFFILE)
- type = get_token(fp, token, MAXTOKEN);
- if (type == ENDOFFILE){
- print_error("Expected "}"", token, type);
- return NULL;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- switch (type) {
- case DEFINITIONS:
- if (state != BETWEEN_MIBS){
- print_error("Error, nested MIBS", NULL, type);
- return NULL;
- }
- state = IN_MIB;
- current_module = which_module( name );
- if ( current_module == -1 ) {
- new_module(name, File);
- current_module = which_module(name);
- }
- DEBUGMSGTL(("parse-mibs", "Parsing MIB: %d %sn", current_module, name));
- while ((type = get_token (fp, token, MAXTOKEN)) != ENDOFFILE)
- if (type == BEGIN) break;
- break;
- case OBJTYPE:
- nnp = parse_objecttype(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of OBJECT-TYPE", NULL, type);
- return NULL;
- }
- break;
- case OBJGROUP:
- nnp = parse_objectgroup(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of OBJECT-GROUP", NULL, type);
- return NULL;
- }
- break;
- case TRAPTYPE:
- nnp = parse_trapDefinition(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of TRAP-TYPE", NULL, type);
- return NULL;
- }
- break;
- case NOTIFTYPE:
- nnp = parse_notificationDefinition(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of NOTIFICATION-TYPE", NULL, type);
- return NULL;
- }
- break;
- case COMPLIANCE:
- nnp = parse_compliance(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of MODULE-COMPLIANCE", NULL, type);
- return NULL;
- }
- break;
- case CAPABILITIES:
- nnp = parse_capabilities(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of AGENT-CAPABILITIES", NULL, type);
- return NULL;
- }
- break;
- case MACRO:
- nnp = parse_macro(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of MACRO", NULL, type);
- /*return NULL;*/
- }
- free_node(nnp); /* IGNORE */
- nnp = NULL;
- break;
- case MODULEIDENTITY:
- nnp = parse_moduleIdentity(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of MODULE-IDENTITY", NULL, type);
- return NULL;
- }
- break;
- case OBJID:
- type = get_token(fp, token, MAXTOKEN);
- if (type != EQUALS){
- print_error("Expected "::="", token, type);
- return NULL;
- }
- nnp = parse_objectid(fp, name);
- if (nnp == NULL){
- print_error("Bad parse of OBJECT IDENTIFIER", NULL, type);
- return NULL;
- }
- break;
- case EQUALS:
- nnp = parse_asntype(fp, name, &type, token);
- lasttype = CONTINUE;
- break;
- case ENDOFFILE:
- break;
- default:
- print_error("Bad operator", token, type);
- return NULL;
- }
- if (nnp) {
- if (np) np->next = nnp;
- else np = root = nnp;
- while (np->next) np = np->next;
- }
- }
- DEBUGMSGTL(("parse-file", "End of file (%s)n", File));
- return root;
- }
- /* return zero if character is not a label character. */
- static int
- is_labelchar (int ich)
- {
- if ((isalnum(ich)) || (ich == '-'))
- return 1;
- if (ich == '_' && ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_PARSE_LABEL))
- return 1;
- return 0;
- }
- /*
- * Parses a token from the file. The type of the token parsed is returned,
- * and the text is placed in the string pointed to by token.
- * Warning: this method may recurse.
- */
- static int
- get_token(FILE *fp,
- char *token,
- int maxtlen)
- {
- register int ch, ch_next;
- register char *cp = token;
- register int hash = 0;
- register struct tok *tp;
- int too_long = 0;
- /* skip all white space */
- do {
- ch = getc(fp);
- if (ch == 'n')
- Line++;
- }
- while(isspace(ch) && ch != EOF);
- *cp++ = (char)ch; *cp = ' ';
- switch (ch) {
- case EOF:
- return ENDOFFILE;
- case '"':
- return parseQuoteString(fp, token, maxtlen);
- case ''': /* binary or hex constant */
- while ((ch = getc(fp)) != EOF && ch != ''' && cp-token < maxtlen-2)
- *cp++ = (char)ch;
- if (ch == ''') {
- unsigned long val = 0;
- *cp++ = ''';
- ch = getc(fp);
- *cp++ = (char)ch;
- *cp = 0;
- cp = token+1;
- switch (ch) {
- case EOF:
- return ENDOFFILE;
- case 'b':
- case 'B':
- while ((ch = *cp++) != ''')
- if (ch != '0' && ch != '1') return LABEL;
- else val = val * 2 + ch - '0';
- break;
- case 'h':
- case 'H':
- while ((ch = *cp++) != ''')
- if ('0' <= ch && ch <= '9') val = val*16+ch-'0';
- else if ('a' <= ch && ch <= 'f') val = val*16+ch-'a'+10;
- else if ('A' <= ch && ch <= 'F') val = val*16+ch-'A'+10;
- else return LABEL;
- break;
- default:
- return LABEL;
- }
- sprintf(token, "%ld", val);
- return NUMBER;
- }
- else return LABEL;
- case '(':
- return LEFTPAREN;
- case ')':
- return RIGHTPAREN;
- case '{':
- return LEFTBRACKET;
- case '}':
- return RIGHTBRACKET;
- case ';':
- return SEMI;
- case ',':
- return COMMA;
- case '|':
- return BAR;
- case '.':
- ch_next = getc(fp);
- if (ch_next == '.') return RANGE;
- ungetc(ch_next, fp);
- return LABEL;
- case ':':
- ch_next = getc(fp);
- if (ch_next != ':') {
- ungetc(ch_next, fp);
- return LABEL;
- }
- ch_next = getc(fp);
- if (ch_next != '=') {
- ungetc(ch_next, fp);
- return LABEL;
- }
- return EQUALS;
- case '-':
- ch_next = getc(fp);
- if (ch_next == '-') {
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_MIB_COMMENT_TERM)) {
- /* Treat the rest of this line as a comment. */
- while ((ch_next != EOF) && (ch_next != 'n'))
- ch_next = getc(fp);
- } else {
- /* Treat the rest of the line or until another '--' as a comment */
- /* (this is the "technically" correct way to parse comments) */
- ch = ' ';
- ch_next = getc(fp);
- while (ch_next != EOF && ch_next != 'n' &&
- (ch != '-' || ch_next != '-')) {
- ch = ch_next; ch_next = getc(fp);
- }
- }
- if (ch_next == EOF) return ENDOFFILE;
- if (ch_next == 'n') Line++;
- return get_token (fp, token, maxtlen);
- }
- ungetc(ch_next, fp);
- default:
- /*
- * Accumulate characters until end of token is found. Then attempt to
- * match this token as a reserved word. If a match is found, return the
- * type. Else it is a label.
- */
- if (!is_labelchar(ch)) return LABEL;
- hash += tolower(ch);
- more:
- while (is_labelchar(ch_next = getc(fp))) {
- hash += tolower(ch_next);
- if (cp - token < maxtlen - 1) *cp++ = (char)ch_next;
- else too_long = 1;
- }
- ungetc(ch_next, fp);
- *cp = ' ';
- if (too_long)
- print_error("Warning: token too long", token, CONTINUE);
- for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
- if ((tp->hash == hash) && (!label_compare(tp->name, token)))
- break;
- }
- if (tp) {
- if (tp->token != CONTINUE) return (tp->token);
- while (isspace((ch_next = getc(fp))))
- if (ch_next == 'n') Line++;
- if (ch_next == EOF) return ENDOFFILE;
- if (isalnum(ch_next)) {
- *cp++ = (char)ch_next;
- hash += tolower(ch_next);
- goto more;
- }
- }
- if (token[0] == '-' || isdigit(token[0])) {
- for(cp = token+1; *cp; cp++)
- if (!isdigit(*cp))
- return LABEL;
- return NUMBER;
- }
- return LABEL;
- }
- }
- int
- snmp_get_token(FILE *fp,
- char *token,
- int maxtlen)
- {
- return get_token(fp, token, maxtlen);
- }
- /*
- * Returns the root of the whole tree
- * (for backwards compatability)
- */
- struct tree *
- read_mib(const char *filename)
- {
- FILE *fp;
- char token[MAXTOKEN];
- fp = fopen(filename, "r");
- if (fp == NULL) {
- snmp_log_perror(filename);
- return NULL;
- }
- Line = 1;
- File = filename;
- DEBUGMSGTL(("parse-mibs", "Parsing file: %s...n", filename));
- get_token( fp, token, MAXTOKEN);
- fclose(fp);
- new_module(token, filename);
- (void) read_module(token);
- return tree_head;
- }
- struct tree *
- read_all_mibs(void)
- {
- struct module *mp;
- for ( mp=module_head ; mp ; mp=mp->next )
- if ( mp->no_imports == -1 )
- read_module( mp->name );
- adopt_orphans();
- return tree_head;
- }
- static int
- parseQuoteString(FILE *fp,
- char *token,
- int maxtlen)
- {
- register int ch;
- int count = 0;
- int too_long = 0;
- char *token_start = token;
- for (ch = getc(fp); ch != EOF; ch = getc(fp)) {
- if (ch == 'r') continue;
- if (ch == 'n') {
- Line++;
- }
- else if (ch == '"') {
- *token = ' ';
- if (too_long &&
- ds_get_int(DS_LIBRARY_ID, DS_LIB_MIB_WARNINGS) > 1)
- {
- /* show short form for brevity sake */
- char ch_save = *(token_start + 50);
- *(token_start + 50) = ' ';
- print_error ("Warning: string too long",
- token_start, QUOTESTRING);
- *(token_start + 50) = ch_save;
- }
- return QUOTESTRING;
- }
- /* maximum description length check. If greater, keep parsing
- but truncate the string */
- if (++count < maxtlen)
- *token++ = (char)ch;
- else too_long = 1;
- }
- return 0;
- }
- /*
- * struct index_list *
- * getIndexes(FILE *fp):
- * This routine parses a string like { blah blah blah } and returns a
- * list of the strings enclosed within it.
- *
- */
- static struct index_list *
- getIndexes(FILE *fp, struct index_list **retp) {
- int type;
- char token[MAXTOKEN];
- char nextIsImplied = 0;
- struct index_list *mylist = NULL;
- struct index_list **mypp = &mylist;
- free_indexes(retp);
- type = get_token(fp, token, MAXTOKEN);
- if (type != LEFTBRACKET) {
- return NULL;
- }
- type = get_token(fp, token, MAXTOKEN);
- while (type != RIGHTBRACKET && type != ENDOFFILE) {
- if ((type == LABEL) || (type & SYNTAX_MASK)) {
- *mypp = (struct index_list *) calloc(1, sizeof(struct index_list));
- if (*mypp) {
- (*mypp)->ilabel = strdup(token);
- (*mypp)->isimplied = nextIsImplied;
- mypp = &(*mypp)->next;
- nextIsImplied = 0;
- }
- } else if (type == IMPLIED) {
- nextIsImplied = 1;
- }
- type = get_token(fp, token, MAXTOKEN);
- }
- *retp = mylist;
- return mylist;
- }
- static void
- free_indexes(struct index_list **spp) {
- if (spp && *spp) {
- struct index_list *pp, *npp;
- pp = *spp; *spp = NULL;
- while(pp) {
- npp = pp->next;
- if (pp->ilabel) free(pp->ilabel);
- free(pp);
- pp = npp;
- }
- }
- }
- static void
- free_ranges(struct range_list **spp) {
- if (spp && *spp) {
- struct range_list *pp, *npp;
- pp = *spp; *spp = NULL;
- while(pp) {
- npp = pp->next;
- free(pp);
- pp = npp;
- }
- }
- }
- static void
- free_enums(struct enum_list **spp)
- {
- if (spp && *spp) {
- struct enum_list *pp, *npp;
- pp = *spp; *spp = NULL;
- while(pp)
- {
- npp = pp->next;
- if (pp->label) free(pp->label);
- free(pp);
- pp = npp;
- }
- }
- }
- static struct enum_list *
- copy_enums (struct enum_list *sp)
- {
- struct enum_list *xp = NULL, **spp = &xp;
- while (sp) {
- *spp = (struct enum_list *) calloc(1, sizeof(struct enum_list));
- if (!*spp) break;
- (*spp)->label = strdup(sp->label);
- (*spp)->value = sp->value;
- spp = &(*spp)->next;
- sp = sp->next;
- }
- return (xp);
- }
- static struct range_list *
- copy_ranges (struct range_list *sp)
- {
- struct range_list *xp = NULL, **spp = &xp;
- while (sp) {
- *spp = (struct range_list *) calloc(1, sizeof(struct range_list));
- if (!*spp) break;
- (*spp)->low = sp->low;
- (*spp)->high = sp->high;
- spp = &(*spp)->next;
- sp = sp->next;
- }
- return (xp);
- }
- /*
- static struct index_list *
- copy_indexes (struct index_list *sp)
- {
- struct index_list *xp = NULL, **spp = &xp;
- while (sp) {
- *spp = (struct index_list *) calloc(1, sizeof(struct index_list));
- if (!*spp) break;
- (*spp)->ilabel = strdup(sp->ilabel);
- spp = &(*spp)->next;
- sp = sp->next;
- }
- return (xp);
- }
- */
- /*
- * This routine parses a string like { blah blah blah } and returns OBJID if
- * it is well formed, and NULL if not.
- */
- static int
- tossObjectIdentifier(FILE *fp)
- {
- int type;
- char token[MAXTOKEN];
- int bracketcount = 1;
- type = get_token(fp, token, MAXTOKEN);
- if (type != LEFTBRACKET)
- return 0;
- while ((type != RIGHTBRACKET || bracketcount > 0) && type != ENDOFFILE )
- {
- type = get_token(fp, token, MAXTOKEN);
- if (type == LEFTBRACKET)
- bracketcount++;
- else if (type == RIGHTBRACKET)
- bracketcount--;
- }
- if (type == RIGHTBRACKET)
- return OBJID;
- else
- return 0;
- }
- struct tree *
- find_node(const char *name,
- struct tree *subtree) /* Unused */
- {
- return( find_tree_node( name, -1 ));
- }
- struct module *
- find_module(int mid)
- {
- struct module *mp;
- for(mp=module_head; mp!=NULL; mp = mp->next) {
- if (mp->modid == mid)
- break;
- }
- if (mp != 0)
- return mp;
- return NULL;
- }
- static char leave_indent[256];
- static int leave_was_simple;
- static void print_mib_leaves(FILE *f, struct tree *tp, int width)
- {
- #ifdef UCD_SNMP
- struct tree *ntp;
- char *ip = leave_indent+strlen(leave_indent)-1;
- char last_ipch = *ip;
- *ip = '+';
- if (tp->type == 0)
- fprintf(f, "%s--%s(%ld)n", leave_indent, tp->label, tp->subid);
- else {
- const char *acc, *typ;
- int size = 0;
- switch (tp->access) {
- case MIB_ACCESS_NOACCESS: acc = "----"; break;
- case MIB_ACCESS_READONLY: acc = "-R--"; break;
- case MIB_ACCESS_WRITEONLY: acc = "--W-"; break;
- case MIB_ACCESS_READWRITE: acc = "-RW-"; break;
- case MIB_ACCESS_NOTIFY: acc = "---N"; break;
- case MIB_ACCESS_CREATE: acc = "CR--"; break;
- default: acc = " "; break;
- }
- switch (tp->type) {
- case TYPE_OBJID: typ = "ObjID "; break;
- case TYPE_OCTETSTR: typ = "String "; size = 1; break;
- case TYPE_INTEGER:
- if (tp->enums) typ = "EnumVal ";
- else typ = "Integer "; break;
- case TYPE_NETADDR: typ = "NetAddr "; break;
- case TYPE_IPADDR: typ = "IpAddr "; break;
- case TYPE_COUNTER: typ = "Counter "; break;
- case TYPE_GAUGE: typ = "Gauge "; break;
- case TYPE_TIMETICKS: typ = "TimeTicks"; break;
- case TYPE_OPAQUE: typ = "Opaque "; size = 1; break;
- case TYPE_NULL: typ = "Null "; break;
- case TYPE_COUNTER64: typ = "Counter64"; break;
- case TYPE_BITSTRING: typ = "BitString"; break;
- case TYPE_NSAPADDRESS: typ = "NsapAddr "; break;
- case TYPE_UINTEGER: typ = "UInteger "; break;
- default: typ = " "; break;
- }
- fprintf(f, "%s-- %s %s %s(%ld)n", leave_indent, acc, typ, tp->label, tp->subid);
- *ip = last_ipch;
- if (tp->tc_index >= 0)
- fprintf(f, "%s Textual Convention: %sn", leave_indent,
- tclist[tp->tc_index].descriptor);
- if (tp->enums) {
- struct enum_list *ep = tp->enums;
- int cpos = 0, cmax = width - strlen(leave_indent) - 16;
- fprintf(f, "%s Values: ", leave_indent);
- while (ep) {
- char buf[80];
- int bufw;
- if (ep != tp->enums) fprintf(f, ", ");
- sprintf(buf, "%s(%d)", ep->label, ep->value);
- cpos += (bufw = strlen(buf) + 2);
- if (cpos >= cmax) {
- fprintf(f, "n%s ", leave_indent);
- cpos = bufw;
- }
- fprintf(f, "%s", buf);
- ep = ep->next;
- }
- fprintf(f, "n");
- }
- if (tp->ranges) {
- struct range_list *rp = tp->ranges;
- if (size) fprintf(f, "%s Size: ", leave_indent);
- else fprintf(f, "%s Range: ", leave_indent);
- while (rp) {
- if (rp != tp->ranges) fprintf(f, " | ");
- if (rp->low == rp->high) fprintf(f, "%d", rp->low);
- else fprintf(f, "%d..%d", rp->low, rp->high);
- rp = rp->next;
- }
- fprintf(f, "n");
- }
- }
- *ip = last_ipch;
- strcat(leave_indent, " |");
- leave_was_simple = tp->type != 0;
- { int i, j, count = 0;
- struct leave {
- oid id;
- struct tree *tp;
- } *leaves, *lp;
- for (ntp = tp->child_list; ntp; ntp = ntp->next_peer) count++;
- if (count) {
- leaves = (struct leave *)calloc(count, sizeof(struct leave));
- if (!leaves) return;
- for (ntp = tp->child_list, count = 0; ntp; ntp = ntp->next_peer) {
- for (i = 0, lp = leaves; i < count; i++, lp++)
- if (lp->id >= ntp->subid) break;
- for (j = count; j > i; j--) leaves[j] = leaves[j-1];
- lp->id = ntp->subid;
- lp->tp = ntp;
- count++;
- }
- for (i = 1, lp = leaves; i <= count; i++, lp++) {
- if (!leave_was_simple || lp->tp->type == 0)
- fprintf(f, "%sn", leave_indent);
- if (i == count) ip[3] = ' ';
- print_mib_leaves(f, lp->tp, width);
- }
- free(leaves);
- leave_was_simple = 0;
- }
- }
- ip[1] = 0;
- #endif
- }
- void print_mib_tree(FILE *f, struct tree *tp, int width)
- {
- leave_indent[0] = ' ';
- leave_indent[1] = 0;
- leave_was_simple = 1;
- print_mib_leaves(f, tp, width);
- }
- /*
- * Merge the parsed object identifier with the existing node.
- * If there is a problem with the identifier, release the existing node.
- */
- static struct node *
- merge_parse_objectid(struct node *np,
- FILE *fp,
- char *name)
- {
- struct node *nnp;
- nnp = parse_objectid(fp, name);
- if (nnp) {
- /* apply last OID sub-identifier data to the information */
- /* already collected for this node. */
- struct node *headp, *nextp;
- int ncount = 0;
- nextp = headp = nnp;
- while (nnp->next) {
- nextp = nnp;
- ncount++;
- nnp = nnp->next;
- }
- np->label = nnp->label;
- np->subid = nnp->subid;
- np->modid = nnp->modid;
- np->parent = nnp->parent;
- free(nnp);
- if (ncount) {
- nextp->next = np;
- np = headp;
- }
- }
- else {
- free_node(np); np = NULL;
- }
- return np;
- }
- /*
- * transfer data to tree from node
- *
- * move pointers for alloc'd data from np to tp.
- * this prevents them from being freed when np is released.
- * parent member is not moved.
- *
- * CAUTION: nodes may be repeats of existing tree nodes.
- * This can happen especially when resolving IMPORT clauses.
- *
- */
- #ifdef UCD_SNMP
- static void
- tree_from_node(struct tree *tp, struct node *np)
- {
- free_partial_tree(tp, FALSE);
- tp->label = np->label; np->label = NULL;
- tp->enums = np->enums; np->enums = NULL;
- tp->ranges = np->ranges; np->ranges = NULL;
- tp->indexes = np->indexes; np->indexes = NULL;
- tp->tc_index = np->tc_index;
- tp->access = np->access;
- tp->status = np->status;
- tp->hint = np->hint; np->hint = NULL;
- tp->units = np->units; np->units = NULL;
- tp->description = np->description; np->description = NULL;
- tp->subid = np->subid;
- tp->type = translation_table[np->type];
- set_function(tp);
- }
- #endif