User Defined MIB Example Application


This application demonstrates how to add user defined MIBs to the SNMP agent.
The user defined MIB in this application defines scalar objects used to control
the LEDs on development board, and a table of names.  Since not all development
boards have LEDs that can be controlled by software, the example application
"simulates" the state of the LEDS and does not call any of the LED related API
functions.

Since Treck's SNMP library does not support dynamically adding MIBS, all the
user defined MIBs must be statically linked into the SNMP code before runtime.
Therefore, the SNMP library has been split into 2 parts:

1) The base SNMP agent source code located in \netos\src\snmpcust, where the
   user can make changes to the source files and rebuild the libraries (libsnmpd.a,
   libsnmpd_no_ipsec.a, libsnmpdv3.a libsnmpdv3_no_ipsec.a).
2) The SNMP libraries provided with the release (libsnmp.a, libsnmp_no_ipsec.a,
   libsnmpv3.a, libsnmpv3_no_ipsec.a).


***************************
*                         *
* Step 1: Compile the MIB *
*                         *
***************************


From a Windows DOS box, set the environment variable SMIPATH to 
SMIPATH=c:\netosX\mibcomp\mibcomp_win321\smi\mibs\ietf, where c:\netosX is the
directory where NET+OS is installed.  SMIPATH points to the directory path for
the depository for all the MIB definition files used by the MIB compiler.  Then
change directory to c:\netosX\mibcomp\mibcomp_win321\smi\bin, where the MIB
compiler executables are located.

Copy the MIB definition file(s) for the NET+OS SNMP application to the 
c:\netosX\mibcomp\mibcomp_win321\smi\mibs\ietf directory.  For the naMib example
application, the MIBs are located in the .\mibs subdirectory.  The example.sm2
MIB file is the original MIB definition from NET+OS 6.3 and earlier verions.  The
example-mib2 MIB file is an updated version of example.sm2 for NET+OS 7.0.  When
the MIB compiler compiles example.sm2, the compiler generates error messages and
warns that the compiler generated .c and .h files may be flawed.  Therefore, the
original MIB file was fixed and renamed example-mib2.  The MIB compiler has
problems with MIB files with an extension in the file name, so it's best to remove
the extension from the file name.

From the command line type

smidump –f Treck Mibname

to compile the MIB file and generate the C and H files.  For the naMib application,
Mibname can be either example or example-mib2.  If you compile the old MIB file,
the compiler will report errors, so it's best to compile the new MIB file.  Once
the compiler has successfully compiled the MIB file, it generates five files

Mibname_local.c
Mibname_local.h,
Mibname_var.c
Mibname_var.h
Mibname.ins

in c:\netosX\mibcomp\mibcomp_win312\smi\bin.  The Mibname_local.*, Mibname_var.c
and Mibname.ins files need to be copied to the NET+OS SNMP application directory.
The Mibname_var.h file is used by the SNMP application and the customized version of
the Treck SNMP agent build from the c:\netosX\src\snmpcust directory.  Therefore,
the Mibname_var.h file needs to be copied to the c:\netosX\h directory so it's
accessible to the SNMP application and the customized version of the SNMP agent.

For the naMib application, these five files MIB compiler generated files are

example_local.c
example_local.h
example_var.c
example_var.h
example.ins

and these files are already included in the naMib application.  example_var.h needs
to be moved to the c:\netosX\h directory so it's accessible to the SNMP application
and the customized version of the SNMP agent.


*****************************************
*                                       *
* Step 2: Integrate MIB with SNMP Agent *
*                                       *
*****************************************


The file Mibname.ins contains instructions on the changes needed to integrate the
user defined MIB with the SNMP agent.  For the naMib application, the following
changes are required in the trvars.c and trvars.h files located in the
c:\netosX\src\snmpcust.

INSERT INTO trvars.h BEFORE LINE: const ttSnmpSubtreeTM_CONST_QLF tvSnmpSubtrees[] =

const struct tsSnmpVariable tvSnmpExampleoneVars[] = {
    {tfvar_group, TM_SNMP_RWRITE, 0, 2, GREENLEDON, TM_SNMP_INTEGER, 0, {1,1}},
    {tfvar_group, TM_SNMP_RWRITE, 0, 2, YELLOWLEDON, TM_SNMP_INTEGER, 0, {1,2}},
    {tfvar_group, TM_SNMP_RWRITE, 0, 2, BIGBOSS, TM_SNMP_STRING, 0, {1,3}},
    {tfvar_simpletable, TM_SNMP_RONLY, 0, 4, INDEX, TM_SNMP_INTEGER, 0, {2,1,1,1}},
    {tfvar_simpletable, TM_SNMP_RWRITE, 0, 4, NAME, TM_SNMP_STRING, 0, {2,1,1,2}}
};

INSERT INTO trvars.h into const tsSnmpSubtree TM_CONST_QLF tvSnmpSubtrees[]
in lexicographical order:

    {(struct tsSnmpVariable *)tvSnmpExampleoneVars,
     {1,3,6,1,4,1,901,999,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     sizeof(tvSnmpExampleoneVars)/sizeof(*tvSnmpExampleoneVars),
     sizeof(*tvSnmpExampleoneVars), 9, 0, {'\0'}},

INSERT INTO trvars.c BEFORE LINE: #include "trvars.h"

#include "example_var.h"

INSERT INTO tragent.c into const ttConceptualTable TM_CONST_QLF tlConceptualTables[]
Nothing, you do not have conceptual tables.

For the naMib application, the above changes have already been done to the trvars.c
trvars.h files, but were left commented out.  These commented out changes must be
uncommented to properly integrate the MIB with the agent through a rebuild of the
sources in c:\netosX\src\snmpcust.


************************************
*                                  *
* Step 3: Prepare SNMP Application *
*                                  *
************************************


If a MIB from NET+OS 6.3 (or earlier versions) is being ported to NET+OS 7 (or later
versions), the existing SNMP application must be cleaned up to compile and link with
the MIB compiler generated .c and .h files.  The first part of this process requires
modifying the GNU and GHS build files.  For the GNU makefile and the GHS image.gpj and
rom.gpj files, add include paths for -I.\..\..\..\treck\snmp and 
-I.\..\..\..\treck\include.  These two directories contain Treck header files needed
by the MIB compiler generated .c and .h files.

Next we add the Mibname_local.c and Mibname_var.c files to the GNU makefile and the
GHS project.gpj files and remove all the NET+OS 6.3 related SNMP related source files
and libraries.  For the naMib application, we add example_local.c and example_vars.c,
and remove EXAMPLE.c, MibMan.c, table.c, EXAMPLEAction.c, libmanMib.a and libmanapi.a.
The removed library files are no longer needed in NET+OS 7 (and later versions).

The second part of this clean up process involves removing code that references files,
functions, variables, etc. that are no longer supported.  For the naMib application,
comment out the include files example.h, man_api.h, mibman.h and the function
fillTable() in root.c.  In the applicationStart() function in root.c, comment out all
the old NET+OS 6.3 SNMP related code and replace with a call to naSnmpStart().

At this point, the user can compile and link the SNMP application and execute it.
Using a MIB browser software, the user can communicate with the SNMP agent running on
the target to see the names of the objects supported by the MIB.  Since the GET/SET
functionality of the MIB isn't implemented yet, the user cannot GET/SET any of the
MIB objects.  For the naMib application, the MIB is located in the following MIB
tree hierarchy:

\iso\org\dod\internet\private\enterprise\example or 1.3.6.1.4.1.901.

The hierarchy of the MIB's objects is:

example\nsil\exampleOne\group\greenLedOn
                             \yellowLedOn
                             \bigBoss
example\nsil\exampleOne\table\simpleTable\simpleEntry\index
                                                     \name


Note 1:  The user must copy the MIB definition file to the PC running the MIB browser
software, compile the MIB with the MIB browser's compiler and load the compiler
output file into the MIB browser.  This allows the MIB broswer software to properly
view and access the user defined MIB(s) on the target.

Note 2:  The MIB compiler can compile the MIB without errors, but can generate code
that will not compile or function properly.  If this happens, the user can contact
Digi technical support or Treck at support@treck.com.  The user needs to provide
the MIB definition and the compiler generated output files.  Most of the
errors in the compiler generated .c and .h files can be corrected manually.


************************************
*                                  *
* Step 4: Implement GET/SET in MIB *
*                                  *
************************************


The Mibname_local.c file contains all the functions stubs that the user must fill in
to implement the GET/SET functionality for the objects supported by the MIB.  For the
naMib application, refer to the code in example_local.c.

The example_group variable is an instance of the struct group structure and is used
to store the values of the objects in 

example\nsil\exampleOne\group

which are greenLedOn, yellowLedOn and bigBoss.  These scalar objects are initialized
to their default values through the example_group_init() function.

The tfgroup_get() function is called to GET the values of the objects in

example\nsil\exampleOne\group

where the three objects in this group are greenLedOn, yellowLedOn and bigBoss.
The "what" argument specifies the object name to read and the "length" argument
specifies the number of bytes to GET.  The return value of the function is the
address of the data structure that contains the data for the GET operation.

The tfwrite_group() function is called to SET the values of the objects in

example\nsil\exampleOne\group

where the three objects in this group are greenLedOn, yellowLedOn and bigBoss.
The "what" argument specifies the object name to write, the "buffer" argument
specifies the address of the write data, and the "buffer_length" argument specifies
the number of write data bytes.  Thus, the SET operation will overwrite the
corresponding structure members of the example_group variable.

The naMib application creates 73 entries (just like in NET+OS 6.3 and earlier
versions) in the following table:

example\nsil\exampleOne\table\simpleTable\simpleEntry

that the user can GET/SET.  Thus, the array of default string names in the fillTable()
function of the old (NET+OS 6.3 and earlier versions) naMib application was ported
over, where the example_table_init() function initializes the the tables entries to
their default values.  The tabular objects table is implemented with the two
dimensional character array example_table.

The tfsimpletable_entry_get() function is called to GET the values of the table
entries.  When tfsimpletable_entry_get() is called with a value of 0 for the exact
argument and a value of -1 for entry0->index, the SNMP agent does not know from which
index of the table to start reading from.  Therefore, the implementation sets the
value of entry0->index to 1, fills the data structure pointed by the entry0 pointer
with the relevant data for the first entry of the table and returns 1.  This tells the
SNMP agent that the data returned by the function is for the first entry of the table.
When "exact" is 0 and entry->index is greater than 0, the SNMP agent wants to read the
table entry after the table index referenced by the value of entry->index (GET-NEXT).
Therefore, the value of entry->index is incremented, the data structure pointed by
the entry0 pointer is filled with the relevant data for the table entry referenced by
entry0->index and a value of 1 is returned.

When tfsimpletable_entry_get() is called with a value of 1 for the exact argument,
the SNMP agent knows exactly which entry of the table to read.  Therefore, the
implementation simply fills the data structure pointed by the entry0 pointer with
the relevant data for the table entry referenced by entry0->index.  Regardless of the
value of the exact argument, the implementation checks that a GET or GET-NEXT request
does not exceed the bounds of the table.  If this happens, a value of 0 is returned to
indicate that an error occurred.

The tfwrite_simpletable_entry() function is called to SET the values of the table
entries.  The "index0" argument specifies the index of the table entry to write, the
"value" argument specifies the address of the write data and the "value_length"
argument specifies the number of write data bytes.  The "what" argument is not used
because no object names for the table entries were specified in the MIB definition.
Therefore, the implementation overwrites the corresponding entry in the two
dimensional character array example_table with the SET data.

At this point, the user can rebuild the SNMP application, execute the program and use
the MIB browser to GET/SET the objects supported by the MIB.



Three Multi build files are provided.  The build file project.gpj
is used to control how application specific files are built.  All
updates to the build should be made to this file.  Project.gpj is 
a subproject to the other build files image.gpj and rom.gpj.  
Image.gpj is used to generate a debuggable version of the 
application, and also creates the file image.bin that can be written
into ROM if the bootloader is used.  Rom.gpj is used to generate a 
ROM image of the application if the bootloader is not used.

One GNU make file is provided.  Build the target 'image' to
generate an image that can be debugged with gdb, and the file 
image.bin which can be written to flash if the bootloader is used.
Build the target 'rom.bin' to create the file rom.bin which 
can be written to ROM if the bootloader is not used.

The following files are provided in this template.

appconf.h         sets application configuration settings
.\32b\image.gpj   used to build the big endian Green Hills version of the
                  application.  The build script creates a version that
                  can be debugged with Multi, and the file image.bin 
                  which can be written into a ROM that uses the bootloader.
.\32b\makefile    Make file for the GNU toolset.
.\32b\rom.gpj     used to build the big endian ROM image of application
project.gpj       contains application specific build settings
readme            this file
root.c            contains the applicationStart() function that starts
                  the SNMP agent
example_local.h   header file generated by the MIB compiler
example_local.c   C file generated by the MIB compiler that contains stub
                  functions for the user to fill in
example_var.h     header file generated by the MIB compiler
example_var.c     C file generated by the MIB compiler that contains code
                  calls the stub functions in example_local.c


In addition, the following files in the BSP directory are built
as part of this application.

reset.s         contains the reset code
appconf_api.c   contains code used to read settings in appconf.h


The application build file links in the following libraries.  Most of these
libraries are not actually used by the application.  They are included because
this application is meant to be used as a template for other applications that
may use these libraries.  The linker only includes the code in libraries that 
is actually used.  For example, none of the code in the email client library 
will be linked into this application since it does not call any email APIs.

The library names are listed below.

libbsp.a           contains the BSP library
libtcpip.a         contains the TCP/IP stack library
tx.a               contains the ThreadX kernel library
libfilesys.a       contains the file system library
libposix.a         contains the POSIX layer library
libflash.a         contains the Flash driver library
libsnmpd.a         contains the SNMP daemon library
libsnmp.a          contains the SNMP library
libftpclnt.a       contains the FTP client library
libftpsvr.a        contains the FTP server library
libemailc.a        contains the Email client library
libtelnsvr.a       contains the Telnet server library
libdnsclnt.a       contains the DNS client library
libfastip.a        contains the Fast IP library


The application uses the following files located in the
netos\src\linkerScripts directory.  These files are generated
when the BSP is built.

bootldr.dat     bootloader configuration file used to generate the
                file image.bin.  It controls the information placed
                in the bootloader header of the image.

image.ld        GNU linker script used to build an image that can
                be debugged and used with the bootloader.

image.lx        Green Hills linker script used to build an image
                that can be debugged and used with the bootloader.

rom.ld          GNU linker script used to build an image that will
                run from ROM.  The bootloader is not used with
                this type of image.

rom.lx          Green Hills linker script used to build an image
                that will run from ROM.  The bootloader is not used
                with this type of image.

