📄 parse.c
字号:
do_subtree(struct tree *root,
struct node **nodes)
{
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((char*)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 %s\n",
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);
}
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 %s\n", 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: %s\n", 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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -