Sophie

Sophie

distrib > Fedora > 14 > i386 > media > os > by-pkgid > e04c30fdccbd194f92dd8f835139c4e8 > files > 13

openhpi-subagent-2.3.4-13.fc14.i686.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>C code</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REL="HOME"
TITLE="NetSNMP subagent development manual"
HREF="book1.html"><LINK
REL="PREVIOUS"
TITLE="Header file"
HREF="c188.html"><LINK
REL="NEXT"
TITLE="Creating and Writing (SNMP SET or user) to rows (and columns)"
HREF="x406.html"><link rel="stylesheet" href="/openhpi.css" type="text/css">
</head
><BODY
CLASS="CHAPTER"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><div id="banner"><div><h1>The OpenHPI Project</h1><small>Open Hardware Platform Interface</small></div></div><table><tr>
<!--#include virtual="/sidebar.html" -->
<td id="maincolumn"><div class="mainsegment">
<DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>NetSNMP subagent development manual</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="c188.html"
ACCESSKEY="P"
>&#60;&#60;&#60; Previous</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="x406.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="CHAPTER"
><H1
><A
NAME="AEN299"
></A
>C code</H1
><P
>      Reading this chapter from top to bottom is the best approach. 
    </P
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="INITIALIZE_TABLE"
>Initializiation process of sub-agent</A
></H1
><P
>	The sub-agent is initialized by the call</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>   33	  /* mib code: nit_netSnmpIETFWGTable from netSnmpIETFWGTable.c */
   34	  init_netSnmpIETFWGTable();  
	</PRE
></TD
></TR
></TABLE
><P
>	from the sub-agent daemon code.  This call in the generated code 
	calls the function which sets up the skeleton of the table. 
	It does <I
CLASS="EMPHASIS"
>not</I
> add any actual values in the columns.
	</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>/************************************************************
 *
 * Initialize the netSnmpIETFWGTable table by defining its contents 
	and how it's structured
 */
void
initialize_table_netSnmpIETFWGTable(void)
{
    netsnmp_table_registration_info *table_info;

    if(my_handler) {
        snmp_log(LOG_ERR, 
	"initialize_table_netSnmpIETFWGTable_handler called again\n");
        return;
    }

    memset(&#38; cb, 0x00, sizeof(cb));

    /** create the table structure itself */
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);

    /* if your table is read only, it's easiest to change the
       HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */
    my_handler = netsnmp_create_handler_registration(
				 "netSnmpIETFWGTable",
                                 netsnmp_table_array_helper_handler,
                                 netSnmpIETFWGTable_oid,
                                 netSnmpIETFWGTable_oid_len,
                                 HANDLER_CAN_RWRITE);
            
    if (!my_handler || !table_info) {
        snmp_log(LOG_ERR, "malloc failed in "
                 "initialize_table_netSnmpIETFWGTable_handler\n");
        return; /** mallocs failed */
    }

    /***************************************************
     * Setting up the table's definition
     */
    /*
     * TODO: add any external indexes here.
     */

    /*
     * internal indexes
     */
        /** index: nsIETFWGName */
        netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR);

    table_info-&#62;min_column = netSnmpIETFWGTable_COL_MIN;
    table_info-&#62;max_column = netSnmpIETFWGTable_COL_MAX;

    /***************************************************
     * registering the table with the master agent
     */
    cb.get_value = netSnmpIETFWGTable_get_value;
    cb.container = netsnmp_container_find("netSnmpIETFWGTable_primary:"
                                          "netSnmpIETFWGTable:"
                                          "table_container");
#ifdef netSnmpIETFWGTable_IDX2
    netsnmp_container_add_index(cb.container,
     netsnmp_container_find("netSnmpIETFWGTable_secondary:"
                            "netSnmpIETFWGTable:"
                            "table_container"));
    cb.container-&#62;next-&#62;compare = netSnmpIETFWGTable_cmp;
#endif
#ifdef netSnmpIETFWGTable_SET_HANDLING
    cb.can_set = 1;
#ifdef netSnmpIETFWGTable_ROW_CREATION
    cb.create_row = (UserRowMethod*)netSnmpIETFWGTable_create_row;
#endif
    cb.duplicate_row = (UserRowMethod*)netSnmpIETFWGTable_duplicate_row;
    cb.delete_row = (UserRowMethod*)netSnmpIETFWGTable_delete_row;
    cb.row_copy = (Netsnmp_User_Row_Operation *)
			netSnmpIETFWGTable_row_copy;
/*
    cb.can_activate = (Netsnmp_User_Row_Action *)
			netSnmpIETFWGTable_can_activate;
    cb.can_deactivate = (Netsnmp_User_Row_Action *)
			netSnmpIETFWGTable_can_deactivate;
*/
    cb.can_delete = (Netsnmp_User_Row_Action *)
		netSnmpIETFWGTable_can_delete;

    cb.set_reserve1 = netSnmpIETFWGTable_set_reserve1;
    cb.set_reserve2 = netSnmpIETFWGTable_set_reserve2;
    cb.set_action = netSnmpIETFWGTable_set_action;
    cb.set_commit = netSnmpIETFWGTable_set_commit;
    cb.set_free = netSnmpIETFWGTable_set_free;
    cb.set_undo = netSnmpIETFWGTable_set_undo;
#endif
    DEBUGMSGTL(("initialize_table_netSnmpIETFWGTable",
                "Registering table netSnmpIETFWGTable "
                "as a table array\n"));
    netsnmp_table_container_register(my_handler, table_info, &#38; cb,
                                     cb.container, 1);
}&#13;</PRE
></TD
></TR
></TABLE
><P
>	The init routines performs a couple of basic steps.
	</P
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN310"
>Handler</A
></H2
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>    /* if your table is read only, it's easiest to change the
       HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */
    my_handler = netsnmp_create_handler_registration("netSnmpIETFWGTable",
                             netsnmp_table_array_helper_handler,
                             netSnmpIETFWGTable_oid,
                             netSnmpIETFWGTable_oid_len,
                             HANDLER_CAN_RWRITE);</PRE
></TD
></TR
></TABLE
><P
>Create a handler which contains the OID of the table,
	make it writeable, and which (if any) if the
	NET-SNMP library helper functions to use.
		</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>An OID - Object IDentifier is a an array of <I
CLASS="EMPHASIS"
>longs</I
>.
	The <I
CLASS="EMPHASIS"
>netSnmpIETFWGTable_oid</I
> is defined as:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>	oid netSnmpIETFWGTable_oid[] = { 1,3,6,1,4,1,8072,2,2,1 };</PRE
></TD
></TR
></TABLE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The <I
CLASS="EMPHASIS"
>netsnmp_table_array_helper_handler</I
> is one of many
	helper functions available. Consult the manpage - <I
CLASS="EMPHASIS"
>man netsnmp_table</I
>
	</P
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN323"
>Notify the helper function</A
></H2
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>        /** index: nsIETFWGName */
        netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR);

    table_info-&#62;min_column = netSnmpIETFWGTable_COL_MIN;
    table_info-&#62;max_column = netSnmpIETFWGTable_COL_MAX;</PRE
></TD
></TR
></TABLE
><P
>Notify the helper how many indexes tuples to have
		and which type they are.
		</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The netSnmpIETFWGTable_COL_MIN is defined in the automaticly generated header file.
	</P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The <I
CLASS="EMPHASIS"
>ASN_OCTET_STR </I
> and other types are defined in
	the net-snmp/library/asn1.h file</P
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="REGISTER_GET_OPERATION"
>Register the GET operation</A
></H2
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>    /***************************************************
     * registering the table with the master agent
     */
    cb.get_value = netSnmpIETFWGTable_get_value;</PRE
></TD
></TR
></TABLE
><P
>		This  registers the GET routine which will be responsible
		for providing the Net-SNMP library with the correct data
		for appropiate columnar nodes. Consult <A
HREF="x628.html"
>the Section called <I
>Getting values</I
></A
>.
		</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="REGISTER_COMPARE_FUNCTION"
>Register compare function</A
></H2
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>#ifdef netSnmpIETFWGTable_IDX2
    netsnmp_container_add_index(cb.container,
            netsnmp_container_find("netSnmpIETFWGTable_secondary:"
                                   "netSnmpIETFWGTable:"
                                   "table_container"));
    cb.container-&#62;next-&#62;compare = netSnmpIETFWGTable_cmp;
#endif</PRE
></TD
></TR
></TABLE
><P
>Register with the main NetSNMP code (by injecting
		the address of a user-written routine in the callback mechanism) 
		the OID compare routine. This
		routine is <I
CLASS="EMPHASIS"
>NOT</I
> needed if your table rows
		only have one index value. If you do have more
		than one index value, and you do <I
CLASS="EMPHASIS"
>need</I
> 
		to sort the rows based on a custom sorting algorithm, then
		make sure that <I
CLASS="EMPHASIS"
>netSnmpIETFWGTable_cmp</I
>
		is properly implemented.
		</P
><P
>		If you do not need to use a custom sorting algorithm, and have
		more than one index value comment out 
		<I
CLASS="EMPHASIS"
>netSnmpIETFWGTable_IDX2</I
> 
		and let the NetSNMP library do the sorting.
		</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>The compare routine should <I
CLASS="EMPHASIS"
>ONLY</I
>
			be used during adding and removal of rows that have more than
			one index value. For more reasons why, consult this
			<A
HREF="http://www.net-snmp.org/faqs/rstory/array-user.html"
TARGET="_top"
>array-user Frequently Asked Questions Page</A
>.  
			</P
></TD
></TR
></TABLE
></DIV
><P
>	
		More on the compare function in <A
HREF="c299.html#NETSNMPIETFWGTABLE_IDX2"
>the Section called <I
>Generic compare function</I
></A
>.
		</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="ALTERNATION_AND_CREATION_OF_ROW_SUPPORT"
>Alternation and creation of row support</A
></H2
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>#ifdef netSnmpIETFWGTable_ROW_CREATION
    cb.create_row = (UserRowMethod*)netSnmpIETFWGTable_create_row;
#endif
	</PRE
></TD
></TR
></TABLE
><P
>	Without this routine being injected in the call-back mechanism,
	no row creation is possible. The row creation process is
	user-agnostic - the sub-agent code using internal routines or the SNMP-user using SET operation can create new rows.
	</P
><P
>	However, the SNMP SET operation has to go throughout a set
	of routines to determine if it has the valid syntax,
	the right type and length, and other user-defined tests. Those tests are not
	exercised when the sub-agent code uses the internal routines.
	</P
><P
>	The process by which the NetSNMP library uses to decide if the data is OK 
	is a four state based machine. The data is writen to a new row or
	an existing one, if it has passed the RESERVE1, RESERVE2, and ACTION
	phase. The ACTION phase does the modification and if anything goes wrong
	the process moves to UNDO phase - which restores the original data. 
	Otherwise a COMMIT is perfomed - which modifies the data.
	</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>This two-phase commit system is unique. Many other
		SNMP sub-agent librarys do not implement such technique and
		have only one SET operation which has to take care of 
		checking the type, size, limitation, perform the write, and
		undo if needed.
		</P
></TD
></TR
></TABLE
></DIV
><P
>	The following picture, from the Net-SNMP Tutorial webpage 
	clearly explains the states.
	</P
><DIV
CLASS="MEDIAOBJECT"
><P
><IMG
SRC="images/set-actions.jpg"></P
></DIV
><P
>They are also part of the call-back mechanism. It is 
	the developer responsibility to make sure that those
functions are properly implemented (more on this in <A
HREF="x406.html#SNMP_SET_WRITE_TO_A_ROW"
>the Section called <I
>SNMP SET writing to a row</I
></A
>).
	</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>    cb.set_reserve1 = netSnmpIETFWGTable_set_reserve1;
    cb.set_reserve2 = netSnmpIETFWGTable_set_reserve2;
    cb.set_action = netSnmpIETFWGTable_set_action;
    cb.set_commit = netSnmpIETFWGTable_set_commit;
    cb.set_free = netSnmpIETFWGTable_set_free;
    cb.set_undo = netSnmpIETFWGTable_set_undo;
	</PRE
></TD
></TR
></TABLE
><P
>	Consult <A
HREF="x406.html#RESERVE1"
>the Section called <I
>RESERVE1 function</I
></A
>, 
	<A
HREF="x406.html#RESERVE2"
>the Section called <I
>RESERVE2 function</I
></A
>, 
	<A
HREF="x406.html#ACTION"
>the Section called <I
>ACTION</I
></A
>, 
	<A
HREF="x406.html#COMMIT"
>the Section called <I
>COMMIT function</I
></A
> and 
	<A
HREF="x406.html#FREE_AND_UNDO"
>the Section called <I
>FREE and UNDO function</I
></A
> for more details on what these functions do. </P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN373"
>Miscellaneous</A
></H2
><P
>	The above mentioned functions also require a couple of helper functions.
	Usually you don't need to modify them as the mib2c tool
	does a great job of implementing them. The routines in question are:
	</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>    cb.duplicate_row = (UserRowMethod*)netSnmpIETFWGTable_duplicate_row;
    cb.delete_row = (UserRowMethod*)netSnmpIETFWGTable_delete_row;
    cb.row_copy = (Netsnmp_User_Row_Operation *)
		netSnmpIETFWGTable_row_copy;
    cb.can_activate = (Netsnmp_User_Row_Action *)
		netSnmpIETFWGTable_can_activate;
    cb.can_deactivate = (Netsnmp_User_Row_Action *)
		netSnmpIETFWGTable_can_deactivate;
    cb.can_delete = (Netsnmp_User_Row_Action *)netSnmpIETFWGTable_can_delete;
	</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN377"
>Registering handler with container</A
></H2
><P
>		The last thing that must be done is to register
		the handler, table information (how many rows, columns, etc),
		and the call-back mechansim with the <I
CLASS="EMPHASIS"
>container</I
>.
	</P
><P
>		The container is the Net-SNMP library part of code that will
		keep our rows in memory. It will take care of sorting it (when
		rows are added or removed), providing a specific
		row for a GET/SET request (so you don't have to extract from the OID
		the index/column values and find the row by yourself), and more. This container
		mechanism provides a seperation of the sub-agent developer
		to have to deal with SNMP GET/SET details and instead concentrate
		on operating the data.
	</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>Look in <I
CLASS="EMPHASIS"
>net-snmp/library/container.h</I
>
		for more details. The macro calls which are defined in there 
		(CONTAINER_FIRST, CONTAINER_GET_SUBSET, etc) will be explained
		in more details in <A
HREF="x406.html#DEVELOPER_ROW_CREATION"
>the Section called <I
>Developer row creation</I
></A
>.
		</P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="N_TUPLE_INDEXES"
>Helper functions to handle n-tuple indexes</A
></H3
><P
>   Usually tables only require one index value (for example the enumeration of
   network driver). But in some cases there is a need for a second index, or third,
   or an index value coded as a string.
  </P
><P
>   The index values are used in determining the order of rows. If the  
   index value is a string in UNICODE of a foreign language - the ascending
   order the user expects might be completly different from ASCII sort order. Therefore
   the NetSNMP library provides a mechanism to register the developer's own sorting
   routine. More on this topic in the section below and in <A
HREF="x406.html#COMPARE_FUNCTION_EXPLANATION"
>the Section called <I
>Sorted</I
></A
>.
  </P
></DIV
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="NETSNMPIETFWGTABLE_IDX2"
>Generic compare function</A
></H2
><P
>	The secondary compare function is only used if <I
CLASS="EMPHASIS"
>netSnmpIETFWGTable_IDX2</I
> 
	is defined. This compare function is used by NetSNMP library
	when rows are being added or deleted that have more than one index value. 
	If this function is not enabled, the
	NetSNMP library will use its own generic compare function - which compares
	index tuples and returns an response based on ASCII ascending order.
	</P
><P
>	The goal of this compare function is to return an integer less than, 
	equal to, or greater than zero if lhs (first argument) is found, 
	respectively, to be less than, to match, or be greater than rhs (second argument).
	</P
><P
>	The implementation of this function is quite straightforward. You use
	your own method of figuring out which of passed <I
CLASS="EMPHASIS"
>context</I
>
	structures is less, matches or greater.
	</P
><P
>	Consult <A
HREF="http://www.net-snmp.org/faqs/rstory/array-user.html"
TARGET="_top"
>	array-user Frequently Asked Questions Page</A
> for more advanced information.
	</P
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="AEN400"
>Tree searching function</A
></H2
><P
>    	The tree searching function purpose is to find a <I
CLASS="EMPHASIS"
>context</I
>
	structure based on the custom arguments (defined by developer). 
	This function is not used by NetSNMP library - it is a helper function for 
	the developer if needed.
	</P
><P
>	It returns a matched <I
CLASS="EMPHASIS"
>context</I
> structure based on the
	arguments. 
    	</P
></DIV
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="c188.html"
ACCESSKEY="P"
>&#60;&#60;&#60; Previous</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="x406.html"
ACCESSKEY="N"
>Next &#62;&#62;&#62;</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Header file</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Creating and Writing (SNMP SET or user) to rows (and columns)</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>