This is from someone in my company using libsmi, but not on the mailing
list. This problem may have been fixed already, as this is with Lib SMI
0.4.1.
Pete
========
I have attached two simple MIB files FOO-TEST-MIB and FOO-CORP-MIB1
(sic) the “1” is appended so that it is not automatically imported when
loading FOO-TEST-MIB.
The Problem: FOO-TEST-MIB top node (fooTest) is defined in terms of
fooProductOID which is imported from FOO-CORP-MIB. If the corp mib is
not in SMI path nor previously imported, there is an error correctly
reported regarding 1) the inability to find the module but also 2) the
lack of parent node for fooTest. This is fine but, subsequently
attempting to load FOO-CORP-MIB1 causes a problem during setObjectName
mergeNodeTrees call that ultimately results in a crash due to objectPtr
remaining on lists after being freed.
I have also included a revised version of 'setObjectName' which seems to
work for me. I have not studied the data structures and relationships
between objects in great detail, so, I suspect this is not the best
solution nor a complete solution. However, it performed perfectly in all
of my test cases. If you have time to analyze it and recommend a better
fix, I would greatly appreciate it. You are free to use this code for
libsmi if it is, in fact, a valid solution.
Sincerely,
Ted Latonik
Melbourne, FL USA
Object *setObjectName( Object *objectPtr, char *name )
{
Node *nodePtr, *nextPtr;
Module *modulePtr;
Object *newObjectPtr;
Module *newModulePtr; // ADDED TO SUPPORT BUGFIX
if ( objectPtr->export.name )
{
smiFree( objectPtr->export.name );
}
objectPtr->export.name = name;
/*
* If this name is found on the pending list (at depth==1 in
* pendingRootNode), we have to move the corresponding subtree to
* the main tree.
*/
for ( nodePtr = smiHandle->pendingNodePtr->firstChildPtr; nodePtr;
nodePtr = nextPtr )
{
/*
* probably we change the contents of `pending', so remember
* the next pointer.
*/
nextPtr = nodePtr->nextPtr;
if ( !strcmp( nodePtr->firstObjectPtr->export.name, name ) )
{
/*
* remove nodePtr from the pendingRootNode tree.
*/
if ( nodePtr->prevPtr )
{
nodePtr->prevPtr->nextPtr = nodePtr->nextPtr;
}
else
{
smiHandle->pendingNodePtr->firstChildPtr =
nodePtr->nextPtr;
}
if ( nodePtr->nextPtr )
{
nodePtr->nextPtr->prevPtr = nodePtr->prevPtr;
}
else
{
smiHandle->pendingNodePtr->lastChildPtr =
nodePtr->prevPtr;
}
#if 0
objectPtr->nodePtr->firstObjectPtr = NULL;
objectPtr->nodePtr->lastObjectPtr = NULL;
#else
if ( objectPtr->nodePtr->lastObjectPtr != NULL )
{
if ( objectPtr->nodePtr->lastObjectPtr->export.oid ==
NULL )
{
objectPtr->nodePtr->lastObjectPtr =
objectPtr->nodePtr->lastObjectPtr->prevSameNodePtr;
if ( objectPtr->nodePtr->lastObjectPtr == NULL )
{
objectPtr->nodePtr->firstObjectPtr = NULL;
}
}
}
#endif
// ADDED TO SUPPORT BUGFIX-----------------------
newModulePtr = objectPtr->modulePtr;
//-----------------------------------------------
newObjectPtr = nodePtr->firstObjectPtr;
if ( newObjectPtr )
{
modulePtr = newObjectPtr->modulePtr;
if ( modulePtr->objectPtr == objectPtr )
{
modulePtr->objectPtr = newObjectPtr;
}
if ( modulePtr->firstObjectPtr == objectPtr )
{
modulePtr->firstObjectPtr = objectPtr->nextPtr;
modulePtr->firstObjectPtr->prevPtr = NULL;
}
if ( modulePtr->lastObjectPtr == objectPtr )
{
modulePtr->lastObjectPtr = objectPtr->prevPtr;
modulePtr->lastObjectPtr->nextPtr = NULL;
}
// FIX BEGINS HERE
//---------------------------------------------------------
// If If the forward reference is in the same module
just
// merge and free
//---------------------------------------------------------
if ( modulePtr == newModulePtr )
{
mergeNodeTrees( objectPtr->nodePtr, nodePtr );
smiFree( objectPtr->export.name );
smiFree( objectPtr );
}
//---------------------------------------------------------
// This happens when a previously undefined prefix is
being
// defined
//---------------------------------------------------------
else if ( !strcmp( name, objectPtr->export.name ) )
{
//-----------------------------------------------------
// Remove the object from the old module
//-----------------------------------------------------
modulePtr->firstObjectPtr =
modulePtr->firstObjectPtr->nextPtr;
modulePtr->firstObjectPtr->prevPtr = NULL;
//-----------------------------------------------------
// Merge the nodes
//-----------------------------------------------------
mergeNodeTrees( objectPtr->nodePtr, nodePtr );
//-----------------------------------------------------
// Replace the object in the new module
// It always seems to be the lastObjectPtr but the
// following is added in case
//-----------------------------------------------------
if ( newModulePtr->firstObjectPtr == objectPtr )
{
if ( newObjectPtr->nextPtr = objectPtr->nextPtr
)
newObjectPtr->nextPtr->prevPtr =
newObjectPtr;
newModulePtr->firstObjectPtr = newObjectPtr;
newObjectPtr->prevPtr = NULL;
}
if ( newModulePtr->lastObjectPtr == objectPtr )
{
if ( newObjectPtr->prevPtr = objectPtr->prevPtr
)
newObjectPtr->prevPtr->nextPtr =
newObjectPtr;
newModulePtr->lastObjectPtr = newObjectPtr;
newObjectPtr->nextPtr = NULL;
}
//-----------------------------------------------------
// Fix the prefix node and the module ptr
//-----------------------------------------------------
modulePtr->prefixNodePtr =
modulePtr->firstObjectPtr->nodePtr;
objectPtr->nodePtr->firstObjectPtr->modulePtr =
objectPtr->modulePtr;
newModulePtr->prefixNodePtr =
newModulePtr->firstObjectPtr->nodePtr;
//-----------------------------------------------------
// Reset the OID so the parser will fill it in
//-----------------------------------------------------
newObjectPtr->export.oidlen = 0;
if ( newObjectPtr->export.oid )
{
free( newObjectPtr->export.oid );
newObjectPtr->export.oid = NULL;
}
smiFree( objectPtr->export.name );
smiFree( objectPtr );
}
else
{
printf( "Is this case possible?" );
}
return newObjectPtr;
}
}
}
return objectPtr;
}
--***********************************************************************
-- MIB fooTest from project `foosample'
--
-- Auto-generated by SNMP IQ Application Builder on 11/10/2003
-- Version:
-- Authored on: 05/20/2002
--
-- Foo Corporation Test Definition
--
--
--***********************************************************************
--
FOOTEST-MIB DEFINITIONS ::= BEGIN
IMPORTS
--==============================================================
--
-- Imports from: FOO-CORP-MIB
--
--==============================================================
fooProjectOID FROM FOO-CORP-MIB
--==============================================================
--
-- Imports from: SNMPv2-CONF
--
--==============================================================
OBJECT-GROUP FROM SNMPv2-CONF
--==============================================================
--
-- Imports from: SNMPv2-SMI
--
--==============================================================
Counter32,
Counter64,
Gauge32,
Integer32,
IpAddress,
MODULE-IDENTITY,
NOTIFICATION-TYPE,
OBJECT-TYPE,
Opaque,
TimeTicks,
Unsigned32 FROM SNMPv2-SMI
--==============================================================
--
-- Imports from: SNMPv2-TC
--
--==============================================================
DisplayString,
RowStatus,
TruthValue FROM SNMPv2-TC;
--==============================================================
fooTest MODULE-IDENTITY
LAST-UPDATED "200205200000Z"
ORGANIZATION "Foo Corporation"
CONTACT-INFO
" Icon Laboratories, Inc."
DESCRIPTION
"Foo Corporation Test Definition"
::= { fooProjectOID 1 }
-- ************************************************************************
-- TYPE ASSIGNMENTS
-- ************************************************************************
Real32 ::= DisplayString
-- Top-level structure of the MIB
fooTestEvent OBJECT IDENTIFIER ::= { fooTest 0 }
powerAlarm NOTIFICATION-TYPE
OBJECTS {
mySet,
myByteList
}
STATUS current
DESCRIPTION
"powerAlarm"
::= { fooTestEvent 1 }
bombshellEvent NOTIFICATION-TYPE
OBJECTS {
myByteList,
myUint,
myInt,
myStr,
myCntr64,
myBool,
myVarStr,
mySet,
myIpAddr,
myGauge,
myCntr32,
myTime,
myRowStat,
myObjectID,
tbl1RowStat,
entry4
}
STATUS current
DESCRIPTION
"Must have a description"
::= { fooTestEvent 500 }
myByteList OBJECT-TYPE
SYNTAX Opaque (SIZE(0..20))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Test the opaque datatype"
::= { fooTest 1 }
myUint OBJECT-TYPE
SYNTAX Unsigned32 (3..5|8|10..12)
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Test the uint datatype with ranges"
DEFVAL { 12 }
::= { fooTest 2 }
myInt OBJECT-TYPE
SYNTAX Integer32 (-12|-8..10)
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Test the int datatype with ranges"
DEFVAL { -6 }
::= { fooTest 3 }
myStr OBJECT-TYPE
SYNTAX DisplayString (SIZE(5))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Fixed-length string with default"
DEFVAL { "12345" }
::= { fooTest 4 }
myCntr64 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Counter64 variable, read-only."
::= { fooTest 5 }
myBool OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Boolean with default of false"
DEFVAL { false }
::= { fooTest 6 }
myVarStr OBJECT-TYPE
SYNTAX DisplayString (SIZE(3..8))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Var-length string"
DEFVAL { "larry" }
::= { fooTest 7 }
mySet OBJECT-TYPE
SYNTAX INTEGER {
on(1),
off(2),
maybe(3)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Enumerated set with default value"
DEFVAL { off }
::= { fooTest 8 }
myIpAddr OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Inet address with default."
DEFVAL { '7f000001'H }
::= { fooTest 9 }
myGauge OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Gauge datatype."
::= { fooTest 10 }
myCntr32 OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"32-bit counter - readonly."
::= { fooTest 11 }
myTime OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Time type."
::= { fooTest 12 }
myRowStat OBJECT-TYPE
SYNTAX RowStatus
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Rowstat enumeration."
DEFVAL { active }
::= { fooTest 13 }
myObjectID OBJECT-TYPE
SYNTAX OBJECT IDENTIFIER
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"An object."
::= { fooTest 14 }
myReal32 OBJECT-TYPE
SYNTAX Real32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"A floating type."
DEFVAL { "0.000000" }
::= { fooTest 15 }
myBitStr OBJECT-TYPE
SYNTAX BITS {
zero(0),
one(1),
two(2),
three(3),
four(4),
five(5),
six(6),
seven(7),
eight(8)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"myBitStr"
::= { fooTest 16 }
myOctetStr OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..32))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"myOctetStr"
::= { fooTest 17 }
-- Begin Table table1Table =====================================================
table1Table OBJECT-TYPE
SYNTAX SEQUENCE OF Table1Entry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"This is my dorky description."
::= { fooTest 100 }
table1Entry OBJECT-TYPE
SYNTAX Table1Entry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Row of table table1Table"
INDEX {
mainIndex,
index2
}
::= { table1Table 1 }
Table1Entry ::= SEQUENCE {
mainIndex Unsigned32,
index2 Unsigned32,
tbl1Bits BITS,
tbl1OctetStr OCTET STRING,
tbl1ByteList Opaque,
tbl1Uint Unsigned32,
tbl1Int Integer32,
tbl1Str DisplayString,
tbl1Cntr64 Counter64,
tbl1Bool TruthValue,
tbl1VarStr DisplayString,
tbl1Set INTEGER,
tbl1IpAddr IpAddress,
tbl1Gauge Gauge32,
tbl1Cntr32 Counter32,
tbl1Time TimeTicks,
tbl1RowStat RowStatus,
tbl1ObjectID OBJECT IDENTIFIER,
tbl1Real32 Real32
}
mainIndex OBJECT-TYPE
SYNTAX Unsigned32 (1..12)
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Must have a description"
::= { table1Entry 151 }
index2 OBJECT-TYPE
SYNTAX Unsigned32 (1..12)
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Must have a description"
::= { table1Entry 152 }
tbl1Bits OBJECT-TYPE
SYNTAX BITS {
zero(0),
one(1),
two(2),
three(3),
four(4),
five(5),
six(6),
seven(7),
eight(8)
}
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"tbl1Bits"
::= { table1Entry 1 }
tbl1OctetStr OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..24))
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"tbl1OctetStr"
::= { table1Entry 2 }
tbl1ByteList OBJECT-TYPE
SYNTAX Opaque (SIZE(0..20))
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Test the opaque datatype"
::= { table1Entry 101 }
tbl1Uint OBJECT-TYPE
SYNTAX Unsigned32 (3..5|8|10..12)
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Test the uint datatype with ranges"
DEFVAL { 3 }
::= { table1Entry 102 }
tbl1Int OBJECT-TYPE
SYNTAX Integer32 (-12|-8..10)
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Test the int datatype with ranges"
::= { table1Entry 103 }
tbl1Str OBJECT-TYPE
SYNTAX DisplayString (SIZE(5))
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Fixed-length string with default"
DEFVAL { "Smith" }
::= { table1Entry 104 }
tbl1Cntr64 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Counter64 variable, read-only."
::= { table1Entry 105 }
tbl1Bool OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Boolean with default of false"
DEFVAL { false }
::= { table1Entry 106 }
tbl1VarStr OBJECT-TYPE
SYNTAX DisplayString (SIZE(3..8))
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Var-length string"
DEFVAL { "larry" }
::= { table1Entry 107 }
tbl1Set OBJECT-TYPE
SYNTAX INTEGER {
on(1),
off(2),
maybe(3)
}
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Enumerated set with no default value"
DEFVAL { off }
::= { table1Entry 108 }
tbl1IpAddr OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Inet address with no default."
::= { table1Entry 109 }
tbl1Gauge OBJECT-TYPE
SYNTAX Gauge32
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Gauge datatype."
::= { table1Entry 110 }
tbl1Cntr32 OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"32-bit counter - readonly."
::= { table1Entry 111 }
tbl1Time OBJECT-TYPE
SYNTAX TimeTicks
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Time type."
::= { table1Entry 112 }
tbl1RowStat OBJECT-TYPE
SYNTAX RowStatus
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"Rowstat enumeration."
DEFVAL { notReady }
::= { table1Entry 113 }
tbl1ObjectID OBJECT-TYPE
SYNTAX OBJECT IDENTIFIER
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"An object."
::= { table1Entry 114 }
tbl1Real32 OBJECT-TYPE
SYNTAX Real32
MAX-ACCESS read-create
STATUS current
DESCRIPTION
"A floating type."
DEFVAL { "0.000000" }
::= { table1Entry 115 }
-- End Table table1Table =======================================================
-- Begin Table table2Table =====================================================
table2Table OBJECT-TYPE
SYNTAX SEQUENCE OF Table2Entry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"A description for table2."
::= { fooTest 200 }
table2Entry OBJECT-TYPE
SYNTAX Table2Entry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Row of table table2Table"
INDEX {
mainIndex,
index3
}
::= { table2Table 1 }
Table2Entry ::= SEQUENCE {
index3 DisplayString,
entry3 TruthValue,
entry4 Opaque,
entry5 OBJECT IDENTIFIER
}
index3 OBJECT-TYPE
SYNTAX DisplayString (SIZE(1..5))
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"Must have a description"
::= { table2Entry 201 }
entry3 OBJECT-TYPE
SYNTAX TruthValue
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"This is the index description."
DEFVAL { false }
::= { table2Entry 202 }
entry4 OBJECT-TYPE
SYNTAX Opaque (SIZE(0..10))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"This is the entry description."
::= { table2Entry 203 }
entry5 OBJECT-TYPE
SYNTAX OBJECT IDENTIFIER
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"This is the entry description."
::= { table2Entry 204 }
-- End Table table2Table =======================================================
statScalarGroup OBJECT-GROUP
OBJECTS {
myByteList,
myUint,
myStr,
myCntr64,
myBool,
myVarStr,
mySet,
myIpAddr,
myGauge,
myCntr32,
myTime,
myRowStat,
myObjectID,
myReal32,
myInt,
myByteList,
myUint,
myInt,
myStr,
myCntr64,
myBool,
myVarStr,
mySet,
myIpAddr,
myGauge,
myCntr32,
myTime,
myRowStat,
myObjectID,
myReal32,
myBitStr,
myOctetStr
}
STATUS current
DESCRIPTION
"Must have a description"
::= { fooTest 300 }
statTableGroup OBJECT-GROUP
OBJECTS {
tbl1ByteList,
tbl1Uint,
tbl1Int,
tbl1Str,
tbl1Cntr64,
tbl1Bool,
tbl1VarStr,
tbl1Set,
tbl1IpAddr,
tbl1Gauge,
tbl1Cntr32,
tbl1Time,
tbl1RowStat,
tbl1ObjectID,
tbl1Real32,
entry3,
entry4,
entry5
}
STATUS current
DESCRIPTION
"Must have a description"
::= { fooTest 301 }
myNode OBJECT IDENTIFIER ::= { fooTest 400 }
END
--***********************************************************************
-- MIB fooCorp from project `TEST'
--
-- Auto-generated by SNMP IQ Application Builder on 11/10/2003
-- Version:
-- Authored on: 05/23/2001
--
-- The root of the foo Corporation enterprise MIB.
-- foo Corp is a fictional organization with an
-- enterprise number that SNMP trainers can use.
--
--
--***********************************************************************
--
FOO-CORP-MIB DEFINITIONS ::= BEGIN
IMPORTS
--==============================================================
--
-- Imports from: SNMPv2-SMI
--
--==============================================================
MODULE-IDENTITY,
enterprises FROM SNMPv2-SMI;
--==============================================================
fooCorp MODULE-IDENTITY
LAST-UPDATED "200105230000Z"
ORGANIZATION "foo Corporation"
CONTACT-INFO
" Icon Laboratories, Inc.
3636 Westown Parkway, Suite 101
West Des Moines, IA 50266 USA"
DESCRIPTION
"The root of the foo Corporation enterprise MIB.
foo Corp is a fictional organization with an
enterprise number that SNMP trainers can use."
::= { enterprises 9547 }
-- ************************************************************************
-- TYPE ASSIGNMENTS
-- ************************************************************************
-- Top-level structure of the MIB
fooCorpAdmin OBJECT IDENTIFIER ::= { fooCorp 1 }
fooProjectOID OBJECT IDENTIFIER ::= { fooCorpAdmin 1 }
fooProductOID OBJECT IDENTIFIER ::= { fooCorpAdmin 2 }
fooClientOID OBJECT IDENTIFIER ::= { fooCorpAdmin 3 }
fooEmployeeID OBJECT IDENTIFIER ::= { fooCorpAdmin 4 }
fooPhoneNo OBJECT IDENTIFIER ::= { fooCorpAdmin 5 }
fooMibModules OBJECT IDENTIFIER ::= { fooCorpAdmin 6 }
fooProjects OBJECT IDENTIFIER ::= { fooCorp 2 }
fooProducts OBJECT IDENTIFIER ::= { fooCorp 3 }
fooExperimental OBJECT IDENTIFIER ::= { fooCorp 4 }
END