 
 
 
 
 
 
 
 
 
                           DPI VERSION 2.0 API - PROGRAMMERS REFERENCE
 
 
 
 
 
 
 
                                                    January 31st, 1994
 
 
                                                           Bert Wijnen
 
 
                                          IBM International Operations
                                                           Watsonweg 2
                                                      1423 ND Uithoorn
                                                       The Netherlands
 
                                                 Phone: +31-2975-53316
                                                 Fax:   +31-2975-62468
 
                                            IBM Vnet: WIJNEN at UITVM1
                                         Internet: wijnen@vnet.ibm.com
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page i]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     Table of contents
 
     1.0  INTRODUCTION  . . . . . . . . . . . . . . . . . . . . . . .  2
     1.1  Copyright and Disclaimer  . . . . . . . . . . . . . . . . .  2
     1.2  Who Should Read This Manual   . . . . . . . . . . . . . . .  2
     1.3  Freely Available Implementation   . . . . . . . . . . . . .  4
     1.4  Multiple Levels of the SNMP DPI API   . . . . . . . . . . .  6
     2.0  SNMP DPI API (VERSION 2.0)  . . . . . . . . . . . . . . . .  7
     2.1  API Audience  . . . . . . . . . . . . . . . . . . . . . . .  7
     2.1.1  API for Sub-agent Programmer  . . . . . . . . . . . . . .  9
     2.1.2  API for Agent Programmer  . . . . . . . . . . . . . . .   11
     2.2  Transport Related DPI API Functions   . . . . . . . . . .   13
     2.2.1  The DPIawait_packet_from_agent() Function   . . . . . .   14
     2.2.2  The DPIconnect_to_agent_NMQ() Function  . . . . . . . .   16
     2.2.3  The DPIconnect_to_agent_TCP() Function  . . . . . . . .   18
     2.2.4  The DPIconnect_to_agent_UDP() Function  . . . . . . . .   20
     2.2.5  The DPIdisconnect_from_agent() Function   . . . . . . .   22
     2.2.6  The DPIsend_packet_to_agent() Function  . . . . . . . .   24
     2.2.7  The lookup_host() Function  . . . . . . . . . . . . . .   26
     2.2.8  The query_DPI_port() Function   . . . . . . . . . . . .   28
     2.3  Basic DPI API Functions   . . . . . . . . . . . . . . . .   31
     2.3.1  The DPIdebug() Function   . . . . . . . . . . . . . . .   32
     2.3.2  The DPI_PACKET_LEN() macro  . . . . . . . . . . . . . .   33
     2.3.3  The fDPIparse() Function  . . . . . . . . . . . . . . .   34
     2.3.4  The fDPIset() Function  . . . . . . . . . . . . . . . .   36
     2.3.5  The mkDPIAreYouThere() Function   . . . . . . . . . . .   38
     2.3.6  The mkDPIbulk() Function  . . . . . . . . . . . . . . .   40
     2.3.7  The mkDPIclose() Function   . . . . . . . . . . . . . .   43
     2.3.8  The mkDPIget() Function   . . . . . . . . . . . . . . .   45
     2.3.9  The mkDPIhdr() Function   . . . . . . . . . . . . . . .   47
     2.3.10  The mkDPIhdr_version() Function  . . . . . . . . . . .   49
     2.3.11  The mkDPInext() Function   . . . . . . . . . . . . . .   52
     2.3.12  The mkDPIopen() Function   . . . . . . . . . . . . . .   54
     2.3.13  The mkDPIpacket() Function   . . . . . . . . . . . . .   57
     2.3.14  The mkDPIregister() Function   . . . . . . . . . . . .   59
     2.3.15  The mkDPIresponse() Function   . . . . . . . . . . . .   62
     2.3.16  The mkDPIset() Function  . . . . . . . . . . . . . . .   65
     2.3.17  The mkDPItrap() Function   . . . . . . . . . . . . . .   71
     2.3.18  The mkDPIunregister() Function   . . . . . . . . . . .   73
     2.3.19  The pDPIpacket() Function  . . . . . . . . . . . . . .   75
     2.4  DPI Structures  . . . . . . . . . . . . . . . . . . . . .   77
     2.4.1  The snmp_dpi_bulk_packet structure  . . . . . . . . . .   78
     2.4.2  The snmp_dpi_close_packet structure   . . . . . . . . .   80
     2.4.3  The snmp_dpi_get_packet structure   . . . . . . . . . .   81
     2.4.4  The snmp_dpi_next_packet structure  . . . . . . . . . .   83
     2.4.5  The snmp_dpi_hdr structure  . . . . . . . . . . . . . .   85
     2.4.6  The snmp_dpi_open_packet structure  . . . . . . . . . .   88
     2.4.7  The snmp_dpi_reg_packet structure   . . . . . . . . . .   90
     2.4.8  The snmp_dpi_resp_packet structure  . . . . . . . . . .   92
     2.4.9  The snmp_dpi_set_packet structure   . . . . . . . . . .   94
     2.4.10  The snmp_dpi_trap_packet structure   . . . . . . . . .   96
 
Wijnen                                                        [Page ii]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     2.4.11  The snmp_dpi_ureg_packet structure   . . . . . . . . .   98
     2.4.12  The snmp_dpi_u64 structure   . . . . . . . . . . . . .  100
     2.5  Character Set Selection   . . . . . . . . . . . . . . . .  101
     2.6  Constants and Values  . . . . . . . . . . . . . . . . . .  103
     2.6.1  DPI CLOSE Reason Codes  . . . . . . . . . . . . . . . .  103
     2.6.2  DPI Packet Types  . . . . . . . . . . . . . . . . . . .  104
     2.6.3  DPI RESPONSE Error Codes  . . . . . . . . . . . . . . .  105
     2.6.4  DPI UNREGISTER Reason Codes   . . . . . . . . . . . . .  107
     2.6.5  DPI SNMP Value Types  . . . . . . . . . . . . . . . . .  108
     2.6.6  Value Representation  . . . . . . . . . . . . . . . . .  109
     2.6.7  Return Codes from DPI Transport Related Functions   . .  110
     2.7  The snmp_dpi.h Include File   . . . . . . . . . . . . . .  111
     3.0  SNMP DPI 1.1 API  . . . . . . . . . . . . . . . . . . . .  113
     4.0  HOW TO CHANGE YOUR DPI SUB-AGENT TO DPI 2.0   . . . . . .  116
     5.0  A SIMPLE SAMPLE DPI SUB-AGENT   . . . . . . . . . . . . .  118
     5.1  Overview of Sub-agent Processing  . . . . . . . . . . . .  118
     5.1.1  Connecting to the agent   . . . . . . . . . . . . . . .  120
     5.2  Registering a sub-tree with the agent   . . . . . . . . .  123
     5.3  Processing requests from the agent  . . . . . . . . . . .  125
     5.3.1  Processing a GET request  . . . . . . . . . . . . . . .  127
     5.3.2  Processing a GETNEXT request  . . . . . . . . . . . . .  131
     5.3.3  Processing a SET/COMMIT/UNDO request  . . . . . . . . .  135
     5.3.4  Processing an UNREGISTER request  . . . . . . . . . . .  139
     5.3.5  Processing a CLOSE request  . . . . . . . . . . . . . .  139
     5.4  Generating a TRAP   . . . . . . . . . . . . . . . . . . .  140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page iii]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
       (C) COPYRIGHT International Business Machines Corp. 1994
 
     Permission to use, copy, modify, and distribute this software and
     its documentation for any lawful purpose and without fee is hereby
     granted, provided that this notice be retained unaltered, and that
     the names of IBM and all other contributors shall not be used in
     advertising or publicity pertaining to distribution of the software
     without specific written prior permission. No contributor makes any
     representations about the suitability of this software for any
     purpose.  It is provided "as is" without express or implied
     warranty.
 
     IBM AND ALL OTHER CONTRIBUTORS DISCLAIM ALL WARRANTIES WITH REGARD
     TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
     NON-INFRINGEMENT.
 
     IN NO EVENT SHALL IBM OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
     SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
     TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION
     WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page 1]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     1.0  INTRODUCTION
 
 
     1.1  COPYRIGHT AND DISCLAIMER
 
       (C) COPYRIGHT International Business Machines Corp. 1994
 
     Permission to use, copy, modify, and distribute this software and
     its documentation for any lawful purpose and without fee is hereby
     granted, provided that this notice be retained unaltered, and that
     the names of IBM and all other contributors shall not be used in
     advertising or publicity pertaining to distribution of the software
     without specific written prior permission. No contributor makes any
     representations about the suitability of this software for any
     purpose.  It is provided "as is" without express or implied
     warranty.
 
     IBM AND ALL OTHER CONTRIBUTORS DISCLAIM ALL WARRANTIES WITH REGARD
     TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
     NON-INFRINGEMENT.
 
     IN NO EVENT SHALL IBM OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
     SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
     TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION
     WITH, THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 
     1.2  WHO SHOULD READ THIS MANUAL
 
     This document describes an API on top of the SNMP DPI Version 2.0.
     The API has been implemented and is in use by several products.
     Some people consider it a low level API, and samples of a higher
     level API do exist.
 
     This API has two types of audiences:
 
     o   The DPI sub-agent programmer
     o   The programmer(s) who implement a DPI capable SNMP agent
 
     Some of the functions described in this document are used by both
     types of audiences.  Other functions are (normally) only used by
     one type of programmer.  In each function description, we have
     included a statement about the intended audience or user, so that
     you can quickly decide if the information is relevant to the type
     of work you are doing.
 
     The reader may also want to obtain a copy of the relevant RFCs.
 
 
 
 
Wijnen                                                         [Page 2]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     o   RFC1228 is the SNMP DPI 1.0 RFC
     o   RFC15xx is the SNMP DPI 2.0 RFC
     o   RFC1440 through RFC1452 are the SNMPv2 RFCs.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page 3]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     1.3  FREELY AVAILABLE IMPLEMENTATION
 
     DPI 2.0 has been implemented by IBM Research and the source code is
     freely available under the terms listed in 1.1, "Copyright and
     Disclaimer" on page 2.  You can obtain the code and documentation
     by anonymous FTP from:
 
          software.watson.ibm.com  (129.34.139.5)
 
     To obtain the source, perform the following steps:
 
          ftp software.watson.ibm.com
          user:     anonymous
          password: your_e-mail_address
          cd /public/dpi
          get README
          binary
          get dpi_api.tar (or compressed dpi_api.tar.Z)
          quit
 
     The code consists of the following source files:
 
     snmp_dpi.h  The public SNMP DPI 2.0 API as provided to the DPI
                 sub-agent programmer. The DPI sub-agent code must
                 include this file.
 
     snmp_mDPI.c The base DPI 2.0 encode/decode functions.  This is
                 system and platform independent code, ANSI C compliant.
                 This piece of the code is used both at the agent and at
                 the sub-agent side.
 
     snmp_dpi1.h To be included (done by by snmp_dpi.h) if the DPI
                 sub-agent programmer wants DPI version 1.x
                 compatibility.  It will be included if the programmer
                 defines:
 
                     SNMP_DPI_VERSION=1
                     SNMP_DPI_RELEASE=1
 
     snmp_qDPI.c System independent portion of the code for the
                 query_DPI_port() function.
 
     snmp_lDPI.c Sample of system specific code for the DPI API.  The
                 SNMP DPI 2.0 API defines functions like:
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page 4]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                     query_DPI_port()
                     lookup_host()
                     DPIconnect_to_agent_TCP()
                     DPIconnect_to_agent_UDP()
                     DPIconnect_to_agent_NMQ()
                     DPIdisconnect_from_agent()
                     DPIsend_packet_from_agent()
                     DPIawait_packet_from_agent()
 
                 Those functions cannot be implemented in a system
                 independent manner because unfortunately, the BSD
                 socket implementation is not 100% compatible on all
                 systems.
                 However, with some #ifdef logic, it is possible to make
                 them work on several platforms. The sample provided
                 currently compiles and works on:
 
                       OS/2 2.x with TCP/IP 2.0 for OS/2
                       AIX 3.2 and up       /* TODO: need to test */
                       AIX/ESA x.x and up   /* TODO: need to test */
                       AIX 1.3 for PS/2     /* TODO: need to test */
 
     snmp_lDPI.h Defines function prototypes, message texts and such for
                 use within the DPI internal code.
 
     dpi_sample.c A very basic sample SNMP DPI sub-agent to explain and
                 show how to use the SNMP DPI API.
 
     dpiSimple.mib The dpiSimple MIB that goes with the dpi_sample.c
                 source.
 
     This code can be used by people who want to implement the SNMP DPI
     version 2.0 API and/or an SNMP DPI 2.0 capable agent on their own
     platform.
 
     The DPI sub-agent programmer can use the snmp_dpi.h include file
     and the dpi_sample.c file as a sample on how to use the DPI API.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page 5]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     1.4  MULTIPLE LEVELS OF THE SNMP DPI API
 
     The primary objective of this guide is to describe the SNMP DPI 2.0
     API.  Some functions are implemented as macros. This is because the
     older DPI version 1.x had the same function names with different
     arguments. So the new implementation uses a new function name.  It
     is thus possible to provide either the DPI 1.x or the DPI 2.x API
     by properly defining the macros.
 
     By default, when you include the snmp_dpi.h include file, you will
     be exposed to the DPI 2.0 API. This is the recommended use of the
     SNMP DPI API, for which you will find the reference material in
     2.0, "SNMP DPI API (Version 2.0)" on page 7.  When you link-edit
     your object code into an executable file, you must then use the new
     DPI functions as provided in the snmp_mDPI.c, snmp_qDPI.c and
     snmp_lDPI.c source files.
 
     If you have DPI 1.x based code, then you may opt to keep using the
     old DPI 1.x snmp_dpi.h include file and the old DPI 1.x functions
     as provided in DPILIB (mkDPI.c and get_DPI.c). You will be able to
     communicate with an SNMP agent which implements DPI 2.0 based on
     the DPI 2.0 implementation by IBM Research.  For instance, the IBM
     Research new Platform Independent SNMP stack includes support for
     DPI 1.x sub-agents.
 
     However, you may want to recompile your DPI 1.x based code against
     the new snmp_dpi.h include file.
 
     If you choose for DPI 1.x compatibility, you must also use DPI 1.x
     version of the snmp_mDPI.c code (e.g. compiled with these flags).
 
     In 3.0, "SNMP DPI 1.1 API" on page 113 we have a short discussion
     of the items to be considered if you want to use the DPI 1.x
     compatibility mode.
 
     In 4.0, "How to change your DPI sub-agent to DPI 2.0" on page 116
     we discuss what kind of changes you must make to your source to
     migrate it to the SNMP DPI 2.0 API.  If you take a few minutes to
     look at it, you will see that this is not too big a task.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page 6]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     2.0  SNMP DPI API (VERSION 2.0)
 
     Some functions of the DPI API for version 2.0 are implemented as
     macros.  This is because the older DPI version 1 had the same
     function names, but with different arguments.
 
     The new implementation has a new function names which are not
     always the most intuitive.  By defining the macros with the more
     natural names for the functions (macros have same names as the
     functions were named in DPI version 1) we hide the non-intuitive
     names and at the same time we allow that by providing a different
     set of macros we can give DPI version 1 compatibility.
 
     The basic DPI functions are provided by platform independent code
     that is ANSI C compliant.
 
     However, once a DPI packet needs to be sent to an agent or
     sub-agent, then it depends on the platform and the chosen transport
     protocol how that is exactly implemented.
 
     Waiting for a DPI packet is also depends on those things, but
     besides that, some sub-agents want to control sending of and
     waiting for packets themselves, because they may need to be driven
     by other interrupts as well.
 
     So, there is a set of DPI transport related functions that may are
     implemented on all platforms to hide the platform dependent issues
     for those sub-agents that do not need detailed control about the
     transport themselves.
 
 
     2.1  API AUDIENCE
 
     There are basically two types of audiences for the DPI API.
 
     1.  The Sub-agent Programmer who writes code to implement a DPI
         sub-agent.
 
     2.  The Agent Programmer who wants to implement DPI support in an
         SNMP agent.
 
     First we have an overview of the functions and data structures
     normally used by a Sub-agent programmer.
 
     Then we have an overview of the functions and data structures
     normally used by a Agent programmer.
 
 
 
 
 
 
Wijnen                                                         [Page 7]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     Then we have description of all the functions and data structures
     and each description also lists the intended audience, so that you
     can quickly decide if you need to worry about a certain function.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                         [Page 8]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.1.1  API FOR SUB-AGENT PROGRAMMER
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     Basic DPI functions normally used by the programmer who implements
     a DPI sub-agent:
 
         2.3.1, "The DPIdebug() Function" on page 32
         2.3.2, "The DPI_PACKET_LEN() macro" on page 33
         2.3.3, "The fDPIparse() Function" on page 34
         2.3.4, "The fDPIset() Function" on page 36
         2.3.5, "The mkDPIAreYouThere() Function" on page 38
         2.3.7, "The mkDPIclose() Function" on page 43
         2.3.12, "The mkDPIopen() Function" on page 54
         2.3.14, "The mkDPIregister() Function" on page 59
         2.3.15, "The mkDPIresponse() Function" on page 62
         2.3.16, "The mkDPIset() Function" on page 65
         2.3.17, "The mkDPItrap() Function" on page 71
         2.3.18, "The mkDPIunregister() Function" on page 73
         2.3.19, "The pDPIpacket() Function" on page 75
 
     DPI transport related functions normally used by the programmer who
     implements a DPI sub-agent:
 
         2.2.1, "The DPIawait_packet_from_agent() Function" on page 14
         2.2.2, "The DPIconnect_to_agent_NMQ() Function" on page 16
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.2.4, "The DPIconnect_to_agent_UDP() Function" on page 20
         2.2.5, "The DPIdisconnect_from_agent() Function" on page 22
         2.2.6, "The DPIsend_packet_to_agent() Function" on page 24
         2.2.7, "The lookup_host() Function" on page 26
         2.2.8, "The query_DPI_port() Function" on page 28
 
     Data structures normally used by the programmer who implements a
     DPI sub-agent:
 
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.2, "The snmp_dpi_close_packet structure" on page 80
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
         2.4.1, "The snmp_dpi_bulk_packet structure" on page 78
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.4.11, "The snmp_dpi_ureg_packet structure" on page 98
         2.4.12, "The snmp_dpi_u64 structure" on page 100
 
     Constants an values normally of interest to the programmer who
     implements a DPI sub-agent:
 
 
 
Wijnen                                                         [Page 9]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.6.1, "DPI CLOSE Reason Codes" on page 103
         2.6.2, "DPI Packet Types" on page 104
         2.6.3, "DPI RESPONSE Error Codes" on page 105
         2.6.4, "DPI UNREGISTER Reason Codes" on page 107
         2.6.5, "DPI SNMP Value Types" on page 108
         2.6.6, "Value Representation" on page 109
         2.5, "Character Set Selection" on page 101
 
     See also 2.7, "The snmp_dpi.h Include File" on page 111.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 10]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.1.2  API FOR AGENT PROGRAMMER
 
     AUDIENCE
 
         DPI agent programmer.
 
     Functions normally used by the programmer who implements a DPI
     capable SNMP agent:
 
         2.3.1, "The DPIdebug() Function" on page 32
         2.3.2, "The DPI_PACKET_LEN() macro" on page 33
         2.3.3, "The fDPIparse() Function" on page 34
         2.3.4, "The fDPIset() Function" on page 36
         2.3.7, "The mkDPIclose() Function" on page 43
         2.3.8, "The mkDPIget() Function" on page 45
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.10, "The mkDPIhdr_version() Function" on page 49
         2.3.11, "The mkDPInext() Function" on page 52
         2.3.6, "The mkDPIbulk() Function" on page 40
         2.3.13, "The mkDPIpacket() Function" on page 57
         2.3.15, "The mkDPIresponse() Function" on page 62
         2.3.16, "The mkDPIset() Function" on page 65
         2.3.18, "The mkDPIunregister() Function" on page 73
         2.3.19, "The pDPIpacket() Function" on page 75
 
     Data structures normally used by the programmer who implements a
     DPI capable SNMP agent:
 
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.2, "The snmp_dpi_close_packet structure" on page 80
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
         2.4.1, "The snmp_dpi_bulk_packet structure" on page 78
         2.4.6, "The snmp_dpi_open_packet structure" on page 88
         2.4.7, "The snmp_dpi_reg_packet structure" on page 90
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.4.10, "The snmp_dpi_trap_packet structure" on page 96
         2.4.11, "The snmp_dpi_ureg_packet structure" on page 98
         2.4.12, "The snmp_dpi_u64 structure" on page 100
 
     Constants an values normally of interest to the programmer who
     implements a DPI capable SNMP agent:
 
         2.6.1, "DPI CLOSE Reason Codes" on page 103
         2.6.2, "DPI Packet Types" on page 104
         2.6.3, "DPI RESPONSE Error Codes" on page 105
         2.6.4, "DPI UNREGISTER Reason Codes" on page 107
         2.6.5, "DPI SNMP Value Types" on page 108
         2.6.6, "Value Representation" on page 109
 
 
 
Wijnen                                                        [Page 11]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.5, "Character Set Selection" on page 101
 
     See also 2.7, "The snmp_dpi.h Include File" on page 111.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 12]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2  TRANSPORT RELATED DPI API FUNCTIONS
 
     This section contains a description of each DPI transport related
     function that is available to the DPI sub-agent programmer.
 
     These functions try to hide any platform specific issues for the
     DPI sub-agent programmer so that the sub-agent can be made as
     portable as possible.
 
     If you need detailed control for sending and awaiting DPI packets,
     then you may have to do some of the transport related code
     yourself.
 
     As you can see, we recognize different types of transport.  Our
     functions are basically the same for any platform, except for the
     initial call to setup a connection.
 
     Not all the transport types may be supported on your platform.
     Please check with your platform DPI provider which ones are
     supported.
 
     RELATED INFORMATION
 
         2.2.1, "The DPIawait_packet_from_agent() Function" on page 14
         2.2.2, "The DPIconnect_to_agent_NMQ() Function" on page 16
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.2.4, "The DPIconnect_to_agent_UDP() Function" on page 20
         2.2.5, "The DPIdisconnect_from_agent() Function" on page 22
         2.2.7, "The lookup_host() Function" on page 26
         2.2.8, "The query_DPI_port() Function" on page 28
         2.2.6, "The DPIsend_packet_to_agent() Function" on page 24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 13]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.1  THE DPIAWAIT_PACKET_FROM_AGENT() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   int DPIawait_packet_from_agent(    /* await a DPI packet      */|
  |     int                   handle,    /* on this connection      */|
  |     int                   timeout,   /* timeout in seconds.     */|
  |     unsigned char       **message_p, /* receives ptr to data    */|
  |     unsigned long        *length);   /* receives length of data */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     handle      A handle as obtained with a DPIconnect_to_agent_xxxx()
                 call.
 
     timeout     A timeout value in seconds.  There are two special
                 values:
 
                 -1  causes the function to wait forever until a packet
                     arrives
                 0   Means that the function will only check if a packet
                     is waiting.  If not an immediate return is made.
                     If there is a packet that will be returned.
 
     message_p   The address of a ptr that will receive the address of a
                 static DPI packet buffer or, if there is no packet, a
                 NULL pointer.
 
     length      The address of an (unsigned long) integer that will
                 receive the length of the received DPI packet or, if
                 there is no packet, a zero value.
 
     RETURN VALUE
 
         If success, then a zero (DPI_RC_noError) is returned.  The
         callers buffer ptr and length will be set to point to the
         received DPI packet and to the length of that packet.
         If failure, then a negative integer is returned.  It indicates
         what kind of error occurred.  See 2.6.7, "Return Codes from DPI
 
 
 
 
Wijnen                                                        [Page 14]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         Transport Related Functions" on page 110 for a list of possible
         error codes.
 
     DESCRIPTION
 
     The DPIawait_packet_from_agent() function is used at the sub-agent
     side to await a DPI packet from the DPI capable SNMP agent.  The
     programmer can specify how long to wait.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         int                  handle;
         unsigned char       *pack_p;
         unsigned long        length;
 
         handle = DPIconnect_to_agent_TCP("localhost", "public");
         if (handle < 0)
            printf("Error %d from connect\n",handle);
            exit(1);
         } /* endif */
         /* do useful stuff */
         rc = DPIawait_packet_from_agent(handle, -1,
                                   &pack_p, &length);
         if (rc) {
            printf("Error %d from await packet\n");
            exit(1);
         } /* endif */
         /* handle the packet */
 
     RELATED INFORMATION
 
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 15]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.2  THE DPICONNECT_TO_AGENT_NMQ() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   int DPIconnect_to_agent_NMQ(    /* Connect to DPI Named Queue */|
  |     char            *t_qname_p,   /* target (agent) queue name  */|
  |     char            *s_qname_p);  /* source (sub-agent) q name  */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     t_qname_p   A pointer to a NULL terminated character string
                 representing the target Queue Name where the DPI
                 capable SNMP agent is expecting DPI packets.
 
     s_qname_p   A pointer to a NULL terminated character string
                 representing the source Queue Name from which the
                 sub-agent will be sending DPI packets and where it
                 expects DPI packets as input.
 
     RETURN VALUE
 
         If success, an positive integer that represents the connection.
         It is to be used as a handle in subsequent calls to DPI
         transport related functions.
         If failure, then a negative integer is returned.  It indicates
         what kind of error occurred.  See 2.6.7, "Return Codes from DPI
         Transport Related Functions" on page 110 for a list of possible
         error codes.
 
     DESCRIPTION
 
     The DPIconnect_to_agent_NMQ() function is used at the sub-agent
     side to setup an NMQ (named queue) connection to the DPI capable
     SNMP agent.
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 16]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         int                  handle;
 
         handle = DPIconnect_to_agent_NMQ("DPIqueue", "MYqueue");
         if (handle < 0)
            printf("Error %d from connect\n",handle);
            exit(1);
         } /* endif */
 
     RELATED INFORMATION
 
         2.6.7, "Return Codes from DPI Transport Related Functions" on
         page 110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 17]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.3  THE DPICONNECT_TO_AGENT_TCP() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   int DPIconnect_to_agent_TCP(    /* Connect to DPI TCP port    */|
  |     char          *hostname_p,    /* target hostname/IP address */|
  |     char          *community_p);  /* community name             */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hostname_p  A pointer to a NULL terminated character string
                 representing the hostname (or IP address in dot
                 notation) of the host where the DPI capable SNMP agent
                 is running.
 
     community_p A pointer to a NULL terminated character string
                 representing the community name that is required to
                 obtain the dpiPort from the SNMP agent via an SNMP GET
                 request.
 
     RETURN VALUE
 
         If success, an positive integer that represents the connection.
         It is to be used as a handle in subsequent calls to DPI
         transport related functions.
         If failure, then a negative integer is returned.  It indicates
         what kind of error occurred.  See 2.6.7, "Return Codes from DPI
         Transport Related Functions" on page 110 for a list of possible
         error codes.
 
     DESCRIPTION
 
     The DPIconnect_to_agent_TCP() function is used at the sub-agent
     side to setup a TCP connection to the DPI capable SNMP agent.
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 18]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         int                  handle;
 
         handle = DPIconnect_to_agent_TCP("localhost", "loopback");
         if (handle < 0)
            printf("Error %d from connect\n",handle);
            exit(1);
         } /* endif */
 
     RELATED INFORMATION
 
         2.6.7, "Return Codes from DPI Transport Related Functions" on
         page 110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 19]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.4  THE DPICONNECT_TO_AGENT_UDP() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   int DPIconnect_to_agent_UDP(    /* Connect to DPI UDP port    */|
  |     char          *hostname_p,    /* target hostname/IP address */|
  |     char          *community_p);  /* community name             */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hostname_p  A pointer to a NULL terminated character string
                 representing the hostname (or IP address in dot
                 notation) of the host where the DPI capable SNMP agent
                 is running.
 
     community_p A pointer to a NULL terminated character string
                 representing the community name that is required to
                 obtain the dpiPort from the SNMP agent via an SNMP GET
                 request.
 
     RETURN VALUE
 
         If success, an positive integer that represents the connection.
         It is to be used as a handle in subsequent calls to DPI
         transport related functions.
         If failure, then a negative integer is returned.  It indicates
         what kind of error occurred.  See 2.6.7, "Return Codes from DPI
         Transport Related Functions" on page 110 for a list of possible
         error codes.
 
     DESCRIPTION
 
     The DPIconnect_to_agent_UDP() function is used at the sub-agent
     side to setup a UDP connection to the DPI capable SNMP agent.
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 20]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         int                  handle;
 
         handle = DPIconnect_to_agent_UDP("localhost", "loopback");
         if (handle < 0)
            printf("Error %d from connect\n",handle);
            exit(1);
         } /* endif */
 
     RELATED INFORMATION
 
         2.6.7, "Return Codes from DPI Transport Related Functions" on
         page 110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 21]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.5  THE DPIDISCONNECT_FROM_AGENT() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   void DPIdisconnect_from_agent(  /* disconnect from DPI (agent)*/|
  |     int                  handle); /* close this connection      */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     handle      A handle as obtained with a DPIconnect_to_agent_xxxx()
                 call.
 
     RETURN VALUE
 
         If success, an positive integer that represents the connection.
         It is to be used as a handle in subsequent calls to DPI
         transport related functions.
         If failure, then a negative integer is returned.  It indicates
         what kind of error occurred.  See 2.6.7, "Return Codes from DPI
         Transport Related Functions" on page 110 for a list of possible
         error codes.
 
     DESCRIPTION
 
     The DPIdisconnect_from_agent() function is used at the sub-agent
     side to terminate a connection to the DPI capable SNMP agent.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         int                  handle;
 
         handle = DPIconnect_to_agent_TCP("localhost", "loopback");
         if (handle < 0)
            printf("Error %d from connect\n",handle);
            exit(1);
         } /* endif */
         /* do useful stuff */
         DPIdisconnect_from_agent(handle);
 
 
 
 
Wijnen                                                        [Page 22]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     RELATED INFORMATION
 
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 23]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.6  THE DPISEND_PACKET_TO_AGENT() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   int DPIsend_packet_to_agent(       /* send  a DPI packet      */|
  |     int                   handle,    /* on this connection      */|
  |     unsigned char        *message_p, /* ptr to the packet data  */|
  |     unsigned long         length);   /* length of the packet    */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     handle      A handle as obtained with a DPIconnect_to_agent_xxxx()
                 call.
 
     message_p   A ptr to the buffer containing the DPI packet to be
                 sent.
 
     length      The length of the DPI packet to be sent.  The
                 DPI_PACKET_LEN macro is a useful macro to calculate the
                 length.
 
     RETURN VALUE
 
         If success, then a zero (DPI_RC_noError) is returned.
         If failure, then a negative integer is returned.  It indicates
         what kind of error occurred.  See 2.6.7, "Return Codes from DPI
         Transport Related Functions" on page 110 for a list of possible
         error codes.
 
     DESCRIPTION
 
     The DPIsend_packet_to_agent() function is used at the sub-agent
     side to send a DPI packet to the DPI capable SNMP agent.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         int                  handle;
         unsigned char       *pack_p;
 
 
 
 
Wijnen                                                        [Page 24]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         handle = DPIconnect_to_agent_TCP("localhost", "loopback");
         if (handle < 0)
            printf("Error %d from connect\n",handle);
            exit(1);
         } /* endif */
         pack_p = mkDPIopen("1.3.6.1.2.3.4.5",
                       "Sample DPI sub-agent"
                       0L,2L,,DPI_NATIVE_CSET,
                       0,(char *)0);
         if (pack_p) {
            rc = DPIsend_packet_to_agent(handle,pack_p,
                                DPI_PACKET_LEN(pack_p));
            if (rc) {
               printf("Error %d from await packet\n");
               exit(1);
            } /* endif */
         } else {
            printf("Can't make DPI OPEN packet\n");
            exit(1);
         } /* endif */
         /* await the response */
 
     RELATED INFORMATION
 
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.3.2, "The DPI_PACKET_LEN() macro" on page 33
         2.3.12, "The mkDPIopen() Function" on page 54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 25]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.7  THE LOOKUP_HOST() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned long    lookup_host(   /* find IP address in network */|
  |     char            *hostname_p); /* byte order for this host   */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hostname_p  A pointer to a NULL terminated character string
                 representing the hostname (or IP address in dot
                 notation) of the host where the DPI capable SNMP agent
                 is running.
 
     RETURN VALUE
 
         If success, then the IP address for is returned in network byte
         order, so ready to be used in a sockaddr_in structure.
         If failure, then a value of 0 is returned.
 
     DESCRIPTION
 
     The lookup_host() function is used to obtain the IP address (in
     network byte order) of a host (or IP address in dot notation).
 
     The DPI sub-agent programmer only needs to use this function if to
     code the connection setup and send or await the packet.  The
     programmer then obtains the DPI port number, finds the IP address
     of the agent with 2.2.7, "The lookup_host() Function" and then sets
     up a socket for communication.
 
     This function is implicitly executed by the
     DPIconnect_to_agent_TCP() and DPIconnect_to_agent_UDP() functions.
     It is this DPIconnect_to_agent_xxxx() function that the DPI
     sub-agent programmer would normally use.
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 26]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
       #include <snmp_dpi.h>
       #include /* other include files for BSD sockets and such */
       int                  handle;
       unsigned char       *pack_p;
       long int             dpi_port;
       int                  fd;
       struct sockaddr_in   s,t;              /* source and target   */
 
       dpi_port = query_DPI_port("localhost", /* get DPI port number */
                         "public",            /* for TCP, local host */
                         dpiPortForTCP);
       if (dpi_port < 0) exit(1);             /* error if negative   */
 
       host_addr = lookup_host("localhost");  /* find target IP addr */
       if (host_addr == 0) exit(1);           /* unknown, that's it  */
 
       fd = socket(AF_INET,SOCK_STREAM,0);    /* create a TCP socket */
       if (fd < 0) exit(1);                   /* failure to do so    */
 
       memset(&s,0,sizeof(s));
       s.sin_family      = AF_INET;           /* set AF_INET family  */
       s.sin_port        = 0;                 /* give us any port,   */
       s.sin_addr.s_addr = htonl(INADDR_ANY); /* any local IPaddress */
 
       rc = bind(fd,(struct sockaddr *)s,     /* bind our socket(fd) */
                 sizeof(s_sock));             /* defined in s socket */
       if (rc < 0) exit(1);                   /* failure, so exit    */
 
       memset(&d,0,sizeof(d));
       d.sin_family      = AF_INET;           /* set AF_INET family  */
       d.sin_port        = htons(dpi_port);   /* set requested port  */
       d.sin_addr.s_addr = host_addr;         /* destination IP addr */
                                              /* network byte order  */
       rc = connect(fd,(struct sockaddr *)d,  /* connect to target   */
                    sizeof(d));               /* based on d sock     */
       if (rc < 0) exit(1);                   /* failed, exit        */
       /* now we have a socket on which to send/receive DPI packets  */
 
     RELATED INFORMATION
 
         2.2.8, "The query_DPI_port() Function" on page 28
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.2.4, "The DPIconnect_to_agent_UDP() Function" on page 20
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 27]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.2.8  THE QUERY_DPI_PORT() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   long int query_DPI_port(        /* Query (GET) SNMP_DPI port  */|
  |     char          *hostname_p,    /* target hostname/IPaddress  */|
  |     char          *community_p,   /* communityname for GET      */|
  |     int            porttype);     /* port type, one of:         */|
  |                                   /*   dpiPortForTCP            */|
  |                                   /*   dpiPortForUDP            */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hostname_p  A pointer to a NULL terminated character string
                 representing the hostname (or IP address in dot
                 notation) of the host where the DPI capable SNMP agent
                 is running.
 
     community_p A pointer to a NULL terminated character string
                 representing the community name that is required to
                 obtain the dpiPort from the SNMP agent via an SNMP GET
                 request.
 
     porttype    The dpiPort object for a specific port type that you
                 want to obtain.  Currently there are two types, one for
                 a TCP port and one for a UDP port. The snmp_dpi.h
                 include file has two #define statements for these DPI
                 port types:
 
                     #define dpiPortForTCP        1
                     #define dpiPortForUDP        2
 
     RETURN VALUE
 
         If success, then the DPI port number for the specified protocol
         (TCP or UDP) is returned.
         If failure, then a value of -1 is returned.
 
     DESCRIPTION
 
 
 
 
Wijnen                                                        [Page 28]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     The query_DPI_port function is used to obtain the port number on
     which the DPI capable SNMP agent at the specified host is listening
     for connections (TCP) or packets (UDP).
 
     The DPI sub-agent programmer only needs to use this function if to
     code the connection setup and send or await the packet.  The
     programmer then obtains the DPI port number, finds the IP address
     of the agent with 2.2.7, "The lookup_host() Function" on page 26
     and then sets up a socket for communication.
 
     This function is implicitly executed by the
     DPIconnect_to_agent_TCP() and DPIconnect_to_agent_UDP() functions.
     It is this DPIconnect_to_agent_xxxx() function that the DPI
     sub-agent programmer would normally use.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 29]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
       #include <snmp_dpi.h>
       #include /* other include files for BSD sockets and such */
       int                  handle;
       unsigned char       *pack_p;
       long int             dpi_port;
       int                  fd;
       struct sockaddr_in   s,t;              /* source and target   */
 
       dpi_port = query_DPI_port("localhost", /* get DPI port number */
                         "public",            /* for TCP, local host */
                         dpiPortForTCP);
       if (dpi_port < 0) exit(1);             /* error if negative   */
 
       host_addr = lookup_host("localhost");  /* find target IP addr */
       if (host_addr == 0) exit(1);           /* unknown, that's it  */
 
       fd = socket(AF_INET,SOCK_STREAM,0);    /* create a TCP socket */
       if (fd < 0) exit(1);                   /* failure to do so    */
 
       memset(&s,0,sizeof(s));
       s.sin_family      = AF_INET;           /* set AF_INET family  */
       s.sin_port        = 0;                 /* give us any port,   */
       s.sin_addr.s_addr = htonl(INADDR_ANY); /* any local IPaddress */
 
       rc = bind(fd,(struct sockaddr *)s,     /* bind our socket(fd) */
                 sizeof(s_sock));             /* defined in s socket */
       if (rc < 0) exit(1);                   /* failure, so exit    */
 
       memset(&d,0,sizeof(d));
       d.sin_family      = AF_INET;           /* set AF_INET family  */
       d.sin_port        = htons(dpi_port);   /* set requested port  */
       d.sin_addr.s_addr = host_addr;         /* destination IP addr */
                                              /* network byte order  */
       rc = connect(fd,(struct sockaddr *)d,  /* connect to target   */
                    sizeof(d));               /* based on d sock     */
       if (rc < 0) exit(1);                   /* failed, exit        */
       /* now we have a socket on which to send/receive DPI packets  */
 
     RELATED INFORMATION
 
         2.2.7, "The lookup_host() Function" on page 26
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.2.4, "The DPIconnect_to_agent_UDP() Function" on page 20
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 30]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3  BASIC DPI API FUNCTIONS
 
     This section contains a description of each DPI function that is
     available to the DPI sub-agent programmer.
 
     It also includes a description of DPI functions that are normally
     not used by the DPI sub-agent programmer, but rather by the person
     who implements a DPI capable SNMP agent.
 
     Each description contains an AUDIENCE statement so that you can
     quickly see if it relates to the type of work you are doing.
 
     See 2.1.2, "API for Agent Programmer" on page 11 or 2.1.1, "API for
     Sub-agent Programmer" on page 9 for a specific list of functions
     and definitions per audience.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 31]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.1  THE DPIDEBUG() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   void DPIdebug(int level);                                       |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     level  If this value is zero, then tracing is turned off.  If it
            has any other value, then tracing is turned on at the
            specified level.  The higher the value, the more detail.  A
            higher level includes all lower levels of tracing.
            Currently there are two levels of detail:
 
            1  display packet creation and parsing.
 
            2  display hex dump of incoming and outgoing DPI packets.
 
     DESCRIPTION
 
     The DPIdebug() function turns DPI internal debugging/tracing on or
     off.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
 
         DPIdebug(2);
 
     RELATED INFORMATION
 
         2.7, "The snmp_dpi.h Include File" on page 111
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 32]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.2  THE DPI_PACKET_LEN() MACRO
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   int DPI_PACKET_LEN(unsigned char *packet_p)                     |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S).
 
     packet_p    A pointer to a (serialized) DPI packet.
 
     RETURN VALUE
 
         An integer representing the total DPI packet length.
 
     DESCRIPTION
 
     The DPI_PACKET_LEN macro generates C-code that returns an integer
     representing the length of a DPI packet.  It uses the first two
     octets (in network byte order) of the packet to calculate the
     length.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char *pack_p;
         int            length;
 
         pack_p = mkDPIclose(SNMP_CLOSE_goingDown);
         if (pack_p) {
            length = DPI_PACKET_LEN(pack_p);
            /* send packet to agent or sub-agent */
         } /* endif */
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 33]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.3  THE FDPIPARSE() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   void fDPIparse(snmp_dpi_hdr *hdr_p);                            |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hdr_p       A pointer to the parse tree.  The parse tree is
                 represented by an snmp_dpi_hdr structure.
 
     DESCRIPTION
 
     The fDPIparse() function frees a parse tree that was previously
     created by a call to pDPIpacket().  The parse tree may have been
     created in other ways too.  After calling fDPIparse(), no further
     references to the parse tree can be made.
 
     You must also realize that a (complete or partial) DPI parse tree
     is also implicitly freed by call to a DPI function that serializes
     a parse tree into a DPI packet.  The section that describes each
     function tells you if this is the case.  An example of such a
     function is mkDPIresponse().
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         snmp_dpi_hdr  *hdr_p;
         unsigned char *pack_p;         /* assume pack_p points to  */
                                        /* incoming DPI packet      */
         hdr_p = pDPIpacket(pack_p);
 
         /* handle the packet and when done do the following */
         if (hdr_p) fDPIparse(hdr_p);
 
     RELATED INFORMATION
 
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.3.19, "The pDPIpacket() Function" on page 75
 
 
 
Wijnen                                                        [Page 34]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.7, "The snmp_dpi.h Include File" on page 111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 35]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.4  THE FDPISET() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   void fDPIset(snmp_dpi_set_packet *packet_p);                    |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     packet_p    A pointer to the first snmp_dpi_set_packet structure in
                 a chain of such structures.
 
     DESCRIPTION
 
     The fDPIset() function is typically used if you must free a chain
     of one or more snmp_dpi_set_packet structures.  This may be the
     case if you are in the middle of preparing a chain of such
     structures for a DPI RESPONSE packet, but then run into an error
     before you can actually make the response.
 
     If you get to the point where you make a DPI response packet that
     you pass the chain of snmp_dpi_set_packet structures to, then the
     mkDPIresponse() function will free the chain of snmp_dpi_set_packet
     structures.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 36]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
       #include <snmp_dpi.h>
       unsigned char       *pack_p;
       snmp_dpi_hdr        *hdr_p;
       snmp_dpi_set_packet *set_p, *first_p;
       long int             num1 = 0, num2 = 0;
 
       hdr_p = pDPIpacket(pack_p);              /* assume pack_p     */
       /* analyze packet and assume all OK */   /* points to the     */
       /* now prepare response; 2 varBinds */   /* incoming packet   */
 
       set_p = mkDPIset(snmp_dpi_NULL_p,        /* create first one  */
                    "1.3.6.1.2.3.4.5.","1.0",   /* OID=1, instance=0 */
                    SNMP_TYPE_Integer32,
                    sizeof(num1), &num1);
       if (set_p) {                             /* if success, then  */
          first_p = set_p;                      /* save ptr to first */
          set_p   = mkDPIset(set_p,             /* chain next one    */
                      "1.3.6.1.2.3.4.5.","1.1", /* OID=1, instance=1 */
                      SNMP_TYPE_Integer32,
                      sizeof(num2), &num2);
          if (set_p) {                          /* success 2nd one   */
             pack_p = mkDPIresponse(hdr_p,      /* make response     */
                           SNMP_ERROR_noError,  /* It will also free */
                           0L, first_p);        /* the set_p tree    */
             /* send DPI response to agent */
          } else {                              /* 2nd mkDPIset fail */
             fDPIset(first_p);                  /* must free chain   */
          } /* endif */
       } /* endif */
 
     RELATED INFORMATION
 
         2.3.3, "The fDPIparse() Function" on page 34
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.3.15, "The mkDPIresponse() Function" on page 62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 37]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.5  THE MKDPIAREYOUTHERE() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char *mkDPIAreYouThere(void);                          |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     none
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() function that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIAreYouThere() function creates a serialized DPI
     ARE_YOU_THERE packet that can then be sent to the DPI peer
     (normally the agent).
 
     A sub-agent connected via TCP probably does not need this function,
     because normally when the agent breaks the "connection" you will
     receive an EOF on the file descriptor.  For unreliable
     "connections", like over UDP, this function may be useful to
     periodically poll the agent and verify that it still knows about
     the sub-agent.
 
     If your "connection" to the agent is still healthy, the agent will
     send a DPI RESPONSE with SNMP_ERROR_DPI_noError in the error code
     field and zero in the error index field.  The RESPONSE will have no
     varBind data.  If your "connection" is not healthy, the agent may
 
 
 
 
Wijnen                                                        [Page 38]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     send a response with an error indication, or may just not send a
     response at all.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char *pack_p;
 
         pack_p = mkDPIAreYouThere();
         if (pack_p) {
            /* send the packet to the agent */
         } /* endif */
         /* wait for response with DPIawait_packet_from_agent() */
         /* normally the response should come back pretty quickly, */
         /* but it depends on the load of the agent */
 
     RELATED INFORMATION
 
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
         2.2.1, "The DPIawait_packet_from_agent() Function" on page 14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 39]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.6  THE MKDPIBULK() FUNCTION
 
     AUDIENCE
 
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char   *mkDPIbulk(        /* Make DPIbulk packet tree*/|
  |     long int        non-repeaters,   /* count of non-repeaters  */|
  |     long int        max-repetitions, /* max repetitions         */|
  |     snmp_dpi_next_packet *packet_p,  /* ptr to chain of NEXTs   */|
  |                                      /* containing the varBinds */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     non_repeaters   The number of varBinds (objects) in the chain of
                     snmp_dpi_next_packet structures for which you only
                     want one next object to be retrieved.
 
     max_repetitions The maximum number of next objects that you want
                     for each of the rest of the varBinds in the chain
                     of snmp_dpi_next_packet structures.
 
     packet_p        A pointer to a chain of snmp_dpi_next_packet
                     structures.  You must pass a valid pointer to an
                     existing chain.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() function that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIbulk() function creates a serialized DPI GETBULK packet
     that can then be sent to the DPI peer (sub-agent).
 
 
 
Wijnen                                                        [Page 40]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     In the following example let us assume that we want to obtain a
     table in which we expect 20 rows with the objects 1, 2, 3, 4 in
     each column.  We also want to obtain the one other object, that is
     the counter that represents the number of rows in the table.
     (Normally the request would have come in via an SNMP PDU, here we
     just show how to use the mkDPIbulk() function).
 
       EXAMPLE
 
       #include <snmp_dpi.h>
       unsigned char        *pack_p;
       snmp_dpi_hdr         *hdr_p;
       snmp_dpi_next_packet *first_p, nxt_p;
       long int              num = 0;
       int                   i;
 
       nxt_p   = snmp_dpi_next_packet_NULL_p;
       first_p = mkDPInext("1.3.6.1.2.3.4.5.", /* sub-tree to look at */
                           "1",                /* 1.0 is entryCount  */
                           SNMP_TYPE_NULL,
                           sizeof(num), &num);
       if (first_p) {
          nxt_p = first_p;
          for (i=1; i<5; i++) {
              char instance[8];
 
              sprintf(instance, "2.1.%d", i);  /* next table object  */
              nxt_p = mkDPInext(nxt_p,
                           "1.3.6.1.2.3.4.5.", instance,
                           SNMP_TYPE_NULL,
                           sizeof(num), &num);
              if (nxt_p) continue;       /* all ok, iterate for loop */
              else if (first_p) {        /* failed to mkDPInext      */
                 hdr_p = mkDPIhdr(SNMP_DPI_GETNEXT); /* trick to free*/
                 if (hdr_p) {                        /* allocated    */
                    hdr_p->data_u.next_p = first_p;  /* memory via   */
                    fDPIparse(hdr_p);                /* fDPIparse    */
                    first_p  = snmp_dpi_next_packet_NULL_p;/* reset  */
                    hdr_p    = snmp_hdr_NULL_p;            /* ptrs   */
              } /* endif */
          } /* endfor */
       } /* endif */
       if (first_p) {
          pack_p = mkDPIbulk(1,20,first_p); /* make DPI BULK packet  */
          if (pack_p)
             /* send packet to sub-agent */
          } /* endif */
       } /* endif */
 
     RELATED INFORMATION
 
 
 
Wijnen                                                        [Page 41]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.11, "The mkDPInext() Function" on page 52
         2.3.3, "The fDPIparse() Function" on page 34
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
         2.4.1, "The snmp_dpi_bulk_packet structure" on page 78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 42]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.7  THE MKDPICLOSE() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char *mkDPIclose(char reason_code);                    |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     reason_code The reason for closing the DPI connection.
                 See 2.6.1, "DPI CLOSE Reason Codes" on page 103 for a
                 list of valid reason codes.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() function that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIclose() function creates a serialized DPI CLOSE packet
     that can then be sent to the DPI peer.  As a result of sending the
     packet, the DPI connection will be closed.
 
     Sending a DPI CLOSE packet to the agent implies an automatic DPI
     UNREGISTER for all registered sub-trees on the connection being
     closed.
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 43]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char *pack_p;
 
         pack_p = mkDPIclose(SNMP_CLOSE_goingDown);
         if (pack_p) {
            /* send the packet to the agent */
         } /* endif */
 
     RELATED INFORMATION
 
         2.4.2, "The snmp_dpi_close_packet structure" on page 80
         2.6.1, "DPI CLOSE Reason Codes" on page 103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 44]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.8  THE MKDPIGET() FUNCTION
 
     AUDIENCE
 
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   snmp_dpi_get_packet  *mkDPIget(  /* Make DPI get packet tree  */|
  |     snmp_dpi_get_packet *packet_p, /* ptr to GET structure      */|
  |     char                *group_p,  /* ptr to group ID (sub-tree)*/|
  |     char             *instance_p); /* ptr to instance OID string*/|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     packet_p    A pointer to a chain of snmp_dpi_get_packet structures.
                 Pass a NULL pointer if this is the first structure to
                 be created.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the registered sub-tree that caused this GET
                 request to be passed to this DPI sub-agent.  The
                 sub-tree must have a trailing dot.
 
     instance_p  A pointer to a NULL terminated character string that
                 represents the rest (the piece following the sub-tree
                 part) of the OBJECT IDENTIFIER of the variable instance
                 being accessed.  Use of the term instance_p here should
                 not be confused with an OBJECT instance, because this
                 string may consist of a piece of the OBJECT IDENTIFIER
                 plus the INSTANCE IDENTIFIER.
 
     RETURN VALUE
 
         If success, and a chain of one or more packets was passed in
         the packet_p argument, then the same pointer as passed in
         packet_p is returned.  A new dynamically allocated structure
         has then been added to the end of that chain of
         snmp_dpi_get_packet structures.
         If success, and a NULL pointer was passed in the packet_p
         argument, then a pointer to a new dynamically allocated
         structure is returned.
         If failure, then a NULL pointer is returned.
 
 
 
 
Wijnen                                                        [Page 45]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     DESCRIPTION
 
     The mkDPIget() function is used at the agent side to prepare a
     chain of one or more snmp_dpi_get_packet structures.  This chain is
     normally anchored in an snmp_dpi_hdr structure that has its
     packet_type field set to SNMP_DPI_GET.  When all varBinds have been
     prepared into snmp_dpi_get_packet structures, a call can be made to
     mkDPIpacket() which will then serialize the DPI parse tree into a
     DPI packet that can be sent to the DPI peer (normally a sub-agent).
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
 
         hdr_p = mkDPIhdr(SNMP_DPI_GET);
         if (hdr_p) {
            hdr_p->data_u.get_p =
                   mkDPIget(snmp_dpi_get_packet_NULL_p,
                            "1.3.6.1.2.3.4.5.", "1.0");
            if (hdr_p->data_u.get_p) {
               pack_p = mkDPIpacket(hdr_p);
               if (pack_p) {
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 46]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.9  THE MKDPIHDR() FUNCTION
 
     AUDIENCE
 
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   snmp_dpi_hdr  *mkDPIhdr(       /* Make DPI hdr for parse tree*/ |
  |     int                 type);   /* packet type; SNMP_DPI_xxxx */ |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     type        Specifies what kind of DPI packet will be represented
                 by the parse tree.
                 See 2.6.2, "DPI Packet Types" on page 104 for a list of
                 currently defined DPI packet types
 
     RETURN VALUE
 
         If success, a pointer to a dynamically allocated snmp_dpi_hdr
         structure is returned.
         If failure, then a NULL pointer is returned.
 
     DESCRIPTION
 
     The mkDPIhdr() function is used at the agent side to prepare any
     type of DPI parse tree.  The parse tree needs to be completed
     afterwards for the specific DPI packet type.  Once that is done, a
     call to mkDPIpacket will serialize the parse tree into a DPI packet
     that can be sent to the DPI peer (normally a sub-agent).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 47]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
 
         hdr_p = mkDPIhdr(SNMP_DPI_GET);
         if (hdr_p) {
            hdr_p->data_u.get_p =
                   mkDPIget(snmp_dpi_get_packet_NULL_p,
                            "1.3.6.1.2.3.4.5.", "1.0");
            if (hdr_p->data_u.get_p) {
               pack_p = mkDPIpacket(hdr_p);
               if (pack_p) {
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.8, "The mkDPIget() Function" on page 45
         2.3.13, "The mkDPIpacket() Function" on page 57
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 48]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.10  THE MKDPIHDR_VERSION() FUNCTION
 
     AUDIENCE
 
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   snmp_dpi_hdr *mkDPIhdr_version( /* Make a DPI hdr (parse tree)*/|
  |     int             type,         /* packet type; SNMP_DPI_xxxx */|
  |     char            version,      /* for this specific version  */|
  |     char            release);     /* for this specific release  */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     type        Specifies what kind of DPI packet will be represented
                 by the parse tree.
                 See 2.6.2, "DPI Packet Types" on page 104 for a list of
                 currently defined DPI packet types
 
     version     DPI version of DPI packet to be created.
 
     release     DPI release of DPI packet to be created.
 
     RETURN VALUE
 
         If success, a pointer to a dynamically allocated snmp_dpi_hdr
         structure is returned.
         If failure, then a NULL pointer is returned.
 
     DESCRIPTION
 
     The mkDPIhdr_version() function is used at the agent side to
     prepare any type of DPI parse tree for a specific DPI version and
     release.  Specifically it is used if you want to support back level
     DPI sub-agents. In that case you must send DPI packets of a form
     that was defined for the DPI version and release that the sub-agent
     is using.
 
     The parse tree needs to be completed afterwards for the specific
     DPI packet type.  Once that is done, a call to mkDPIpacket will
     serialize the parse tree into a DPI packet that can be sent to the
     DPI peer (normally a sub-agent).
 
 
 
 
Wijnen                                                        [Page 49]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     It is the programmers responsibility to correctly use the version
     and release specification in such a way that the packets to be
     created are valid for the specified version and release.  For
     instance, a DPI OPEN is not valid for versions prior to DPI version
     2.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
 
         hdr_p = mkDPIhdr_version(SNMP_DPI_GET, 1, 1);
         if (hdr_p) {
            hdr_p->data_u.get_p =
                   mkDPIget(snmp_dpi_get_packet_NULL_p,
                            "1.3.6.1.2.3.4.5.", "1.0");
            if (hdr_p->data_u.get_p) {
               pack_p = mkDPIpacket(hdr_p);
               if (pack_p) {
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 50]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     RELATED INFORMATION
 
         2.3.8, "The mkDPIget() Function" on page 45
         2.3.13, "The mkDPIpacket() Function" on page 57
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 51]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.11  THE MKDPINEXT() FUNCTION
 
     AUDIENCE
 
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   snmp_dpi_next_packet *mkDPInext( /* Make DPI next packet tree */|
  |     snmp_dpi_next_packet *packet_p,/* ptr to NEXT structure     */|
  |     char                 *group_p, /* ptr to group ID (sub-tree)*/|
  |     char              *instance_p);/* ptr to instance OID string*/|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     packet_p    A pointer to a chain of snmp_dpi_next_packet
                 structures.  Pass a NULL pointer if this is the first
                 structure to be created.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the registered sub-tree that caused this GET
                 request to be passed to this DPI sub-agent.  The
                 sub-tree must have a trailing dot.
 
     instance_p  A pointer to a NULL terminated character string that
                 represents the rest (the piece following the sub-tree
                 part) of the OBJECT IDENTIFIER of the variable instance
                 being accessed.  Use of the term instance_p here should
                 not be confused with an OBJECT instance, because this
                 string may consist of a piece of the OBJECT IDENTIFIER
                 plus the INSTANCE IDENTIFIER.
 
     RETURN VALUE
 
         If success, and a chain of one or more packets was passed in
         the packet_p argument, then the same pointer as passed in
         packet_p is returned.  A new dynamically allocated structure
         has then been added to the end of that chain of
         snmp_dpi_next_packet structures.
         If success, and a NULL pointer was passed in the packet_p
         argument, then a pointer to a new dynamically allocated
         structure is returned.
         If failure, then a NULL pointer is returned.
 
 
 
 
Wijnen                                                        [Page 52]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     DESCRIPTION
 
     The mkDPInext() function is used at the agent side to prepare a
     chain of one or more snmp_dpi_next_packet structures.  This chain
     is normally anchored in an snmp_dpi_hdr structure that has its
     packet_type field set to SNMP_DPI_GETNEXT.  When all varBinds have
     been prepared into snmp_dpi_next_packet structures, a call can be
     made to mkDPIpacket() which will then serialize the DPI parse tree
     into a DPI packet that can be sent to the DPI peer (normally a
     sub-agent).
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
 
         hdr_p = mkDPIhdr(SNMP_DPI_GET);
         if (hdr_p) {
            hdr_p->data_u.next_p =
                   mkDPInext(snmp_dpi_next_packet_NULL_p,
                            "1.3.6.1.2.3.4.5.", "1.0");
            if (hdr_p->data_u.next_p) {
               pack_p = mkDPIpacket(hdr_p);
               if (pack_p) {
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 53]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.12  THE MKDPIOPEN() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char *mkDPIopen(       /* Make a DPI open packet     */|
  |     char          *oid_p,         /* sub-agent Identifier (OID) */|
  |     char          *description_p, /* sub-agent descriptive name */|
  |     unsigned long  timeout,       /* requested default timeout  */|
  |     unsigned long  max_varBinds,  /* max varBinds per DPI ndle  */|
  |     char           character_set, /* selected character set     */|
  |     #define DPI_NATIVE_CSET  0    /*   0 = native character set */|
  |     #define DPI_ASCII_CSET   1    /*   1 = ASCII  character set */|
  |                                                                   |
  |     unsigned long  password_len,  /* length of password (if any)*/|
  |     unsigned char *password_p);   /* ptr to password (if any)   */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     oid_p         A pointer to a NULL terminated character string
                   representing the OBJECT IDENTIFIER which uniquely
                   identifies the sub-agent.
 
     description_p A pointer to a NULL terminated character string,
                   which is a descriptive name for the sub-agent.  This
                   can be any DisplayString, which basically is an octet
                   string containing only characters from the ASCII NVT
                   set.
 
     timeout       The requested timeout for this sub-agent.  An agent
                   often has a limit for this value and it will use that
                   limit if this value is larger.  A timeout of zero has
                   a special meaning in the sense that the agent will
                   then use its own default timeout value.
 
     max_varBinds  The maximum number of varBinds per DPI packet that
                   the sub-agent is prepared to handle.  It must be a
                   positive number greater than zero.  If a value
                   greater than 1 is specified, then the agent will try
                   to combine as many varBinds (belonging to the same
 
 
 
 
Wijnen                                                        [Page 54]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                   sub-tree) per DPI packet as possible (up to this
                   value).
 
     character_set The character set that you want to use for
                   string-based data fields in the DPI packets and
                   structures.  The choices are:
 
                   DPI_NATIVE_CSET specifies that you want to use the
                                   native character set of the platform
                                   on which the agent that you connect
                                   to is running.
                   DPI_ASCII_CSET  specifies that you want to use the
                                   ASCII character set.  The agent will
                                   translate between ASCII and the
                                   native character set as required.
 
                   See 2.5, "Character Set Selection" on page 101 for
                   more information on character set selection.
 
     password_len  The length (in octets) of an optional password.  It
                   depends on the agent implementation if a password is
                   needed.  If not, then a zero length may be specified.
 
     password_p    A pointer to an octet string representing the
                   password for this sub-agent.  A password may include
                   any character value, including the NULL character.
                   If the password_len is zero, then this can be a NULL
                   pointer.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() functions that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIopen() function creates a serialized DPI OPEN packet that
     can then be sent to the DPI peer (a DPI capable SNMP agent).
 
     Normally you will want to use the native character set.  That makes
     it the easiest for the sub-agent developer.  However, if the agent
     and sub-agent each run on their own platform and those platforms
     use different native character sets then you must select the ASCII
 
 
 
Wijnen                                                        [Page 55]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     character set, so that you both know exactly how to represent
     string-based data that is being send back and forth.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char *pack_p;
 
         pack_p = mkDPIopen("1.3.6.1.2.3.4.5",
                       "Sample DPI sub-agent"
                       0L,2L, DPI_NATIVE_CSET,
                       0,(char *)0);
         if (pack_p) {
            /* send packet to the agent */
         } /* endif */
 
     RELATED INFORMATION
 
         2.4.6, "The snmp_dpi_open_packet structure" on page 88
         2.5, "Character Set Selection" on page 101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 56]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.13  THE MKDPIPACKET() FUNCTION
 
     AUDIENCE
 
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char      *mkDPIpacket(  /* Make a DPI packet      */  |
  |     snmp_dpi_hdr       *hdr_p);     /* ptr to a parse tree    */  |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hdr_p       A pointer to a DPI parse tree.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() functions that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIpacket() function creates a serialized DPI packet that can
     then be sent to the DPI peer (normally a sub-agent).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 57]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
 
         hdr_p = mkDPIhdr(SNMP_DPI_GET);
         if (hdr_p) {
            hdr_p->data_u.next_p =
                   mkDPInext(snmp_dpi_next_packet_NULL_p,
                            "1.3.6.1.2.3.4.5.", "1.0");
            if (hdr_p->data_u.next_p) {
               pack_p = mkDPIpacket(hdr_p);
               if (pack_p) {
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.11, "The mkDPInext() Function" on page 52
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 58]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.14  THE MKDPIREGISTER() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char  *mkDPIregister(  /* Make a DPI register packet */|
  |     unsigned short   timeout,     /* in seconds (16-bit)        */|
  |     long int         priority,    /* requested priority         */|
  |     char            *group_p,     /* ptr to group ID (sub-tree) */|
  |     char             bulk_select);/* Bulk selection (GETBULK)   */|
  |     #define DPI_BULK_NO   0       /*  map GETBULK into GETNEXTs */|
  |     #define DPI_BULK_YES  1       /*  pass GETBULK to sub-agent */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     timeout     The requested timeout in seconds.  An agent often has a
                 limit for this value and it will use that limit if this
                 value is larger.  The value zero has special meaning in
                 the sense that it tells the agent to use the timeout
                 value that was specified in the DPI OPEN packet.
 
     priority    The requested priority.  This field may contain any of
                 these values:
 
                 -1   Requests the best available priority.
                 0    Requests a better priority than the highest
                      priority currently registered.  Use this value to
                      obtain the SNMP DPI version 1 behavior.
                 nnn  Any other positive value.  You will receive that
                      priority if available, otherwise the next best
                      priority that is available.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the sub-tree to be registered.  This group
                 ID must have a trailing dot.
 
     bulk_select Specifies if you want the agent to pass GETBULK on to
                 the sub-agent or to map them into multiple GETNEXT
                 requests.  The choices are:
 
 
 
 
 
Wijnen                                                        [Page 59]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                 DPI_BULK_NO Do not pass any GETBULK requests, but
                             instead map a GETBULK request into multiple
                             GETNEXT requests.
                 DPI_BULK_YES Do pass a GETBULK request to the
                             sub-agent.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() functions that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIregister() function creates a serialized DPI REGISTER
     packet that can then be sent to the DPI peer (a DPI capable SNMP
     agent).
 
     The bulk_selection can be used to ask the agent to map an SNMP
     GETBULK request into multiple GETNEXT requests.  This makes it
     easier for the DPI sub-agent programmer because GETBULK processing
     doesn't need implementing.  At the other hand, if one expects that
     a single GETBULK might improve the performance a lot then one can
     tell the agent to pass such requests.  This might be the case if
     one expects a GETBULK to arrive (often) for a table for which one
     needs to do a kernel dive.  Using GETBULK one might be able to do
     just one dive instead of many (although one could anticipate the
     dive with a GETNEXT also and so obtain and cache the table upon the
     first GETNEXT request).  Be aware that according to the DPI 2.0
     RFC, not all agents need to support DPI_BULK_YES; they will return
     an appropriate error code in the DPI RESPONSE though if such is the
     case.
 
     Normally the SNMP agent sends a DPI RESPONSE packet back, which
     details if the register was successful or not.
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 60]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char *pack_p;
 
         pack_p = mkDPIregister(0,0L,"1.3.6.1.2.3.4.5."
                                DPI_BULK_NO);
         if (pack_p) {
            /* send packet to agent and await response */
         } /* endif */
 
     RELATED INFORMATION
 
         2.4.7, "The snmp_dpi_reg_packet structure" on page 90
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 61]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.15  THE MKDPIRESPONSE() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char    *mkDPIresponse( /* Make a DPI response packet*/|
  |     snmp_dpi_hdr     *hdr_p,       /* ptr to packet to respnd to*/|
  |     long int          error_code,  /* error code: SNMP_ERROR_xxx*/|
  |     long int          error_index, /* index to varBind in error */|
  |     snmp_dpi_set_packet *packet_p);/* ptr to varBinds, a chain  */|
  |                                    /* of dpi_set_packets        */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     hdr_p       A pointer to the parse tree of the DPI request to which
                 this DPI packet will be the response.  The function
                 uses this parse tree to copy the packet_id and the DPI
                 version and release, so that the DPI packet is
                 correctly formatted as a response.
 
     error_code  The error code.
                 See 2.6.3, "DPI RESPONSE Error Codes" on page 105 for a
                 list of valid codes.
 
     error_index Specifies the first varBind in error.  Counting starts
                 at 1 for the first varBind.  This field should be zero
                 if there is no error.
 
     packet_p    A pointer to a chain of snmp_dpi_set_packet structures.
                 This partial parse tree will be freed by the
                 mkDPIresponse() function.  So upon return you cannot
                 reference it anymore.  Pass a NULL pointer if there are
                 no varBinds to be returned.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
 
 
 
 
Wijnen                                                        [Page 62]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() functions that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIresponse() function is used at the sub-agent side to
     prepare a DPI RESPONSE packet to a GET, GETNEXT, GETBULK, SET,
     COMMIT or UNDO request.  The resulting packet can be sent to the
     DPI peer (normally a DPI capable SNMP agent).
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
         snmp_dpi_set_packet *set_p;
         long int             num;
 
         hdr_p = pDPIpacket(pack_p);     /* parse incoming packet */
                                         /* assume it's in pack_p */
         if (hdr_p) {
            /* analyze packet, assume GET, no error */
            set_p = mkDPIset(snmp_dpi_set_packet_NULL_p,
                             "1.3.6.1.2.3.4.5.", "1.0",
                             SNMP_TYPE_Integer32,
                             sizeof(num), &num);
            if (set_p) {
               pack_p = mkDPIresponse(hdr_p,
                             SNMP_ERROR_noError, 0L, set_p);
               if (pack_p) {
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     The mkDPIresponse() function is used at the agent side to prepare a
     DPI RESPONSE packet to an OPEN, REGISTER or UNREGISTER request.  In
     the case of a RESPONSE to a REGISTER request and if there is no
     error, then the actually assigned priority must be passed in the
     error_index argument.  The resulting packet can be sent to the DPI
     peer (normally a sub-agent).
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 63]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
         long int             priority;
 
         hdr_p = pDPIpacket(pack_p);     /* parse incoming packet */
                                         /* assume it's in pack_p */
         if (hdr_p) {
            /* analyze packet, assume REGISTER and OK */
            pack_p = mkDPIresponse(hdr_p,
                          SNMP_ERROR_DPI_noError,
                          priority,
                          snmp_dpi_set_packet_NULL_p);
            if (pack_p) {
               /* send packet to sub-agent */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.19, "The pDPIpacket() Function" on page 75
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 64]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.16  THE MKDPISET() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   snmp_dpi_set_packet *mkDPIset(    /* Make DPI set packet tree */|
  |     snmp_dpi_set_packet *packet_p,  /* ptr to SET structure     */|
  |     char                *group_p,   /* ptr to group ID(sub-tree)*/|
  |     char                *instance_p,/* ptr to instance OIDstring*/|
  |     int                  value_type,/* value type: SNMP_TYPE_xxx*/|
  |     int                  value_len, /* length of value          */|
  |     void                *value_p);  /* ptr to value             */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     packet_p    A pointer to a chain of snmp_dpi_set_packet structures.
                 Pass a NULL pointer if this is the first structure to
                 be created.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the registered sub-tree that caused this GET
                 request to be passed to this DPI sub-agent.  The
                 sub-tree must have a trailing dot.
 
     instance_p  A pointer to a NULL terminated character string that
                 represents the rest (the piece following the sub-tree
                 part) of the OBJECT IDENTIFIER of the variable instance
                 being accessed.  Use of the term instance_p here should
                 not be confused with an OBJECT instance, because this
                 string may consist of a piece of the OBJECT IDENTIFIER
                 plus the INSTANCE IDENTIFIER.
 
     value_type  The type of the value.
                 See 2.6.5, "DPI SNMP Value Types" on page 108 for a
                 list of currently defined value types.
 
     value_len   This is an unsigned 16-bit integer that specifies the
                 length (in octets) of the value pointed to by the value
                 field.  The length may be zero if the value if of type
                 SNMP_TYPE_NULL.
 
 
 
Wijnen                                                        [Page 65]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     value_p     A pointer to the actual value.  This field may contain
                 a NULL pointer if the value is of (implicit or
                 explicit) type SNMP_TYPE_NULL.
 
     RETURN VALUE
 
         If success, and a chain of one or more packets was passed in
         the packet_p argument, then the same pointer as passed in
         packet_p is returned.  A new dynamically allocated structure
         has then been added to the end of that chain of
         snmp_dpi_get_packet structures.
         If success, and a NULL pointer was passed in the packet_p
         argument, then a pointer to a new dynamically allocated
         structure is returned.
         If failure, then a NULL pointer is returned.
 
     DESCRIPTION
 
     The mkDPIset() function is used at the sub-agent side to prepare a
     chain of one or more snmp_dpi_set_packet structures.  This chain is
     then later used to create a DPI RESPONSE packet by a call to
     mkDPIresponse() which can then be sent to the DPI peer (normally a
     DPI capable SNMP agent).
 
     The chain of snmp_dpi_set_packet structures can also be used to
     create a DPI TRAP packet that includes varBinds as explained in
     2.3.17, "The mkDPItrap() Function" on page 71.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 66]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
         snmp_dpi_set_packet *set_p;
         long int             num;
 
         hdr_p = pDPIpacket(pack_p)      /* parse incoming packet */
                                         /* assume it's in pack_p */
         if (hdr_p) {
            /* analyze packet, assume GET, no error */
            set_p = mkDPIset(snmp_dpi_set_packet_NULL_p,
                             "1.3.6.1.2.3.4.5.", "1.0",
                             SNMP_TYPE_Integer32,
                             sizeof(num), &num);
            if (set_p) {
               pack_p = mkDPIresponse(hdr_p,
                             SNMP_ERROR_noError,
                             0L, set_p);
               if (pack_p)
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     The mkDPIset() function is used at the agent side to prepare a
     chain of one or more snmp_dpi_set_packet structures.  This chain is
     normally anchored in an snmp_dpi_hdr structure that has its
     packet_type field set to SNMP_DPI_SET, SNMP_DPI_COMMIT or
     SNMP_DPI_UNDO.  When all varBinds have been prepared into
     snmp_dpi_set_packet structures, a call can be made to mkDPIpacket()
     which will then serialize the DPI parse tree into a DPI packet that
     can be sent to the DPI peer (normally a sub-agent).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 67]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
         long int             num;
 
         hdr_p = mkDPIhdr(SNMP_DPI_SET);
         if (hdr_p) {
            hdr_p->data_u.set_p =
                   mkDPIset(snmp_dpi_set_packet_NULL_p,
                            "1.3.6.1.2.3.4.5.", "1.0",
                            SNMP_TYPE_Integer32,
                            sizeof(num), &num);
            if (hdr_p->data_u.set_p) {
               pack_p = mkDPIpacket(hdr_p);
               if (pack_p)
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     If you must chain many snmp_dpi_set_packet structures, you should
     realize that the packets are chained only by forward pointers.  So
     it might be wise to use the last structure in the existing chain as
     the pack_p argument. Then, the underlying code does not have to
     scan through a possibly long chain of structures in order to chain
     the new structure at the end.  In the next example let's assume we
     want to chain 20 snmp_dpi_set_packet structures as a response to a
     GETBULK.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 68]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
         snmp_dpi_set_packet *first_p;
         snmp_dpi_set_packet *set_p;
         long int             num[20];
         int                  i;
 
         hdr_p = pDPIpacket(pack_p);    /* parse incoming packet    */
                                        /* assume it's in pack_p    */
         if (hdr_p) {
            /* analyze packet, assume GETBULK, no error. In this    */
            /* example we do not check max_repetitions as we should */
            set_p   = snmp_dpi_set_packet_NULL_p;
            first_p = snmp_dpi_set_packet_NULL_p;
            for (i=0; i<20; i++) {
                char instance[5];
 
                sprintf(instance, "%1.%d", i+1);
                set_p = mkDPIset(set_p,
                             "1.3.6.1.2.3.4.5.", instance,
                             SNMP_TYPE_Integer32,
                             sizeof(num), &num[i]);
                if (set_p) {
                   if (first_p) continue; /* OK, iterate for loop  */
                   first_p = set_p;       /* remember first one    */
                } else if (first_p) {     /* failed to mkDPIset    */
                   fDPIset(first_p)       /* free allocated memory */
                   first_p = snmp_dpi_set_packet_NULL_p; /* reset  */
                } /* endif */
            } /* endfor */
            if (first_p) {
               pack_p = mkDPIresponse(hdr_p,
                             SNMP_ERROR_noError,
                             0L, first_p);
               if (pack_p)
                  /* send packet to sub-agent */
               } /* endif */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.15, "The mkDPIresponse() Function" on page 62
         2.3.17, "The mkDPItrap() Function" on page 71
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
Wijnen                                                        [Page 69]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.6.5, "DPI SNMP Value Types" on page 108
         2.6.6, "Value Representation" on page 109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 70]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.17  THE MKDPITRAP() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char      *mkDPItrap(   /* Make a DPI trap packet    */|
  |     long int            generic,   /* generic traptype  (32 bit)*/|
  |     long int            specific,  /* specific traptype (32 bit)*/|
  |     snmp_dpi_set_packet *packet_p, /* ptr to varBinds, a chain  */|
  |                                    /* of dpi_set_packets        */|
  |     char           *enterprise_p); /* ptr to enterprise OID     */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     generic      The generic trap type.  The range of this value is
                  0-6, where 6 (enterpriseSpecific) is the type that is
                  probably used most by DPI sub-agent programmers.  The
                  values 0-5 are well defined standard SNMP traps.
 
     specific     The (enterprise) specific trap type.  This can be any
                  value that is valid for the MIB sub-trees that the
                  sub-agent implements.
 
     packet_p     A pointer to a chain of snmp_dpi_set_structures,
                  representing the varBinds to be passed with the trap.
                  This partial parse tree will freed by the mkDPItrap()
                  function so you cannot reference it anymore upon
                  completion of the call.  A NULL pointer means that
                  there are no varBinds to be included in the trap.
 
     enterprise_p A pointer to a NULL terminated character string
                  representing the enterprise ID (OBJECT IDENTIFIER) for
                  which this trap is defined.  A NULL pointer can be
                  used. In this case, the sub-agent Identifier as passed
                  in the DPI OPEN packet will be used when the agent
                  receives the DPI TRAP packet.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
 
 
 
Wijnen                                                        [Page 71]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() functions that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPItrap() function is used at the sub-agent side to prepare a
     DPI TRAP packet.  The resulting packet can be sent to the DPI peer
     (normally a DPI capable SNMP agent).
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_set_packet *set_p;
         long int             num;
 
         set_p = mkDPIset(snmp_dpi_set_packet_NULL_p,
                          "1.3.6.1.2.3.4.5.", "1.0",
                          SNMP_TYPE_Integer32,
                          sizeof(num), &num);
         if (set_p) {
            pack_p = mkDPItrap(6,1,set_p, (char *)0);
            if (pack_p) {
               /* send packet to sub-agent */
            } /* endif */
         } /* endif */
 
     RELATED INFORMATION
 
         2.3.17, "The mkDPItrap() Function" on page 71
         2.4.10, "The snmp_dpi_trap_packet structure" on page 96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 72]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.18  THE MKDPIUNREGISTER() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   unsigned char *mkDPIunregister( /* Make DPI unregister packet */|
  |     char           reason_code;   /* unregister reason code     */|
  |     char          *group_p);      /* ptr to group ID (sub-tree) */|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     reason_code The reason for the unregister.
                 See 2.6.4, "DPI UNREGISTER Reason Codes" on page 107
                 for a list of the currently defined reason codes.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the sub-tree to be unregistered.  The
                 sub-tree must have a trailing dot.
 
     RETURN VALUE
 
         If success, then a pointer to a static DPI packet buffer is
         returned. The first two bytes of the buffer (in network byte
         order) contain the length of the remaining packet. The macro
         DPI_PACKET_LEN can be used to calculate the total length of the
         DPI packet.
         If failure, then a NULL pointer is returned.
 
     Be aware that the static buffer for the DPI packet is shared by
     other mkDPIxxxx() functions that create a serialized DPI packet.
 
     DESCRIPTION
 
     The mkDPIunregister() function creates a serialized DPI UNREGISTER
     packet that can then be sent to the DPI peer (a DPI capable SNMP
     agent or sub-agent).  Normally the SNMP peer then sends a DPI
     RESPONSE packet back, which details if the unregister was
     successful or not.
 
 
 
 
 
Wijnen                                                        [Page 73]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char *pack_p;
 
         pack_p = mkDPIunregister(
                       SNMP_UNREGISTER_goingDown,
                       "1.3.6.1.2.3.4.5.");
         if (pack_p) {
            /* send packet to agent or sub-agent and await response */
         } /* endif */
 
     RELATED INFORMATION
 
         2.4.11, "The snmp_dpi_ureg_packet structure" on page 98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 74]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.3.19  THE PDPIPACKET() FUNCTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  |   snmp_dpi_hdr *pDPIpacket(unsigned char *packet_p);              |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S).
 
     packet_p    A pointer to a (serialized) DPI packet.
 
     RETURN VALUE
 
         If success, a pointer to a DPI parse tree (snmp_dpi_hdr) is
         returned.  Memory for the parse tree has been dynamically
         allocated, and it is the callers responsibility to free it when
         no longer needed.  You can use the fDPIparse() function to free
         the parse tree.
 
         If failure, a NULL pointer is returned.
 
     DESCRIPTION
 
     The pDPIpacket() function parses the buffer pointed to by the
     packet_p argument.  It ensures that the buffer contains a valid DPI
     packet and that the packet is for a DPI version and release that is
     supported by the DPI functions in use.
 
       EXAMPLE
 
         #include <snmp_dpi.h>
         unsigned char       *pack_p;
         snmp_dpi_hdr        *hdr_p;
 
         hdr_p = pDPIpacket(pack_p);       /* parse incoming packet */
                                           /* assume it's in pack_p */
         if (hdr_p) {
            /* analyze packet, and handle it */
         }
 
 
 
 
Wijnen                                                        [Page 75]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     RELATED INFORMATION
 
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.7, "The snmp_dpi.h Include File" on page 111
         2.3.3, "The fDPIparse() Function" on page 34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 76]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4  DPI STRUCTURES
 
     This section contains a description of each structure that is used
     in the SNMP DPI API.
 
     It also includes structures that are normally not used by the DPI
     sub-agent programmer, but rather by the person who implements a DPI
     capable SNMP agent.
 
     Each description of structure clearly states the intended audience.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 77]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.1  THE SNMP_DPI_BULK_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_bulk_packet {                                        |
  |     long int          non_repeaters;   /* count of non-repeaters*/|
  |     long int          max_repetitions; /* max repeaters         */|
  |     struct dpi_next_packet *varBind_p; /* ptr to varBinds, chain*/|
  |                                        /* of dpi_next_packets   */|
  |   };                                                              |
  |   typedef struct dpi_bulk_packet       snmp_dpi_bulk_packet;      |
  |   #define snmp_dpi_bulk_packet_NULL_p  ((snmp_dpi_bulk_packet *)0)|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     non_repeaters   The number of varBinds in the chain of
                     dpi_next_packet structures that are to be treated
                     as a single GETNEXT.
 
     max_repetitions The max number of repetitions for the remaining set
                     of varBinds in dpi_next_packet structures treated
                     as a single GETNEXT.
 
     varBind_p       The pointer to the first varBind in the chain of
                     dpi_next_packet structures.
 
     DESCRIPTION
 
     The snmp_dpi_bulk_packet structure represents a parse tree for a
     DPI GETBULK packet.
 
     At the sub-agent side, the snmp_dpi_bulk_packet structure is
     normally created as a result of a call to pDPIpacket().  This is
     the case if the DPI packet is of type SNMP_DPI_GETBULK.  The
     snmp_dpi_hdr structure then contains a pointer to an
     snmp_dpi_bulk_packet structure, which in turn has a pointer to a
     chain of one or more snmp_dpi_next_packet structures.
 
     The DPI sub-agent programmer uses this structure to find out which
     variables instances are to be returned in a DPI RESPONSE.
 
 
 
 
Wijnen                                                        [Page 78]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     At the agent side, this structure is normally created with a call
     to the mkDPIbulk() function.  The programmer here normally does not
     inspect the structure itself.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.6, "The mkDPIbulk() Function" on page 40
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 79]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.2  THE SNMP_DPI_CLOSE_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_close_packet {                                       |
  |     char               reason_code;    /* reason for closing    */|
  |   };                                                              |
  |   typedef struct dpi_close_packet      snmp_dpi_close_packet;     |
  |   #define snmp_dpi_close_packet_NULL_p ((snmp_dpi_close_packet*)0)|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     reason_code The reason for the close.
                 See 2.6.1, "DPI CLOSE Reason Codes" on page 103 for a
                 list of valid reason codes.
 
     DESCRIPTION
 
     The snmp_dpi_close_packet structure represents a parse tree for a
     DPI CLOSE packet.
 
     The snmp_dpi_close_packet structure may be created as a result of a
     call to pDPIpacket().  This is the case if the DPI packet is of
     type SNMP_DPI_CLOSE.  The snmp_dpi_hdr structure then contains a
     pointer to a snmp_dpi_close_packet structure.
 
     An snmp_dpi_close_packet_structure is also created as a result of a
     mkDPIclose() call, but then the programmer never sees the structure
     since mkDPIclose() immediately creates a serialized DPI packet from
     it and then frees the structure.
 
     It is recommended that DPI programmer (both at the agent and at the
     sub-agent side) uses mkDPIclose() to create a DPI CLOSE packet.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.7, "The mkDPIclose() Function" on page 43
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
Wijnen                                                        [Page 80]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.3  THE SNMP_DPI_GET_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_get_packet {                                         |
  |     char                  *object_p;   /* ptr to OID string     */|
  |     char                  *group_p;    /* ptr to sub-tree(group)*/|
  |     char                  *instance_p; /* ptr to rest of OID    */|
  |     struct dpi_get_packet *next_p;     /* ptr to next in chain  */|
  |   };                                                              |
  |   typedef struct dpi_get_packet        snmp_dpi_get_packet;       |
  |   #define snmp_dpi_get_packet_NULL_p   ((snmp_dpi_get_packet *)0) |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     object_p    A pointer to a NULL terminated character string that
                 represents the full OBJECT IDENTIFIER of the variable
                 instance that is being accessed.  It basically is a
                 concatenation of the fields group_p and instance_p.
                 Using this field is not recommended because it is only
                 included for DPI version 1 compatibility and it maybe
                 withdrawn in a later version.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the registered sub-tree that caused this GET
                 request to be passed to this DPI sub-agent.  The
                 sub-tree must have a trailing dot.
 
     instance_p  A pointer to a NULL terminated character string that
                 represents the rest (the piece following the sub-tree
                 part) of the OBJECT IDENTIFIER of the variable instance
                 being accessed.  Use of the term instance_p here should
                 not be confused with an OBJECT instance, because this
                 string may consist of a piece of the OBJECT IDENTIFIER
                 plus the INSTANCE IDENTIFIER.
 
     next_p      A pointer to a possible next snmp_dpi_get_packet
                 structure.  If this next field contains the NULL ptr,
                 then this is the end of the chain.
 
     DESCRIPTION
 
 
 
Wijnen                                                        [Page 81]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     The snmp_dpi_get_packet structure represents a parse tree for a DPI
     GET packet.
 
     At the sub-agent side, the snmp_dpi_get_packet structure is
     normally created as a result of a call to pDPIpacket().  This is
     the case if the DPI packet is of type SNMP_DPI_GET.  The
     snmp_dpi_hdr structure then contains a pointer to a chain of one or
     more snmp_dpi_get_packet structures.
 
     The DPI sub-agent programmer uses this structure to find out which
     variables instances are to be returned in a DPI RESPONSE.
 
     At the agent side, this structure is normally created with a call
     to the mkDPIget() function.  The programmer here normally does not
     inspect the structure itself.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.8, "The mkDPIget() Function" on page 45
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 82]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.4  THE SNMP_DPI_NEXT_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_next_packet {                                        |
  |     char                   *object_p;  /* ptr to OID (string)   */|
  |     char                   *group_p;   /* ptr to sub-tree(group)*/|
  |     char                   *instance_p;/* ptr to rest of OID    */|
  |     struct dpi_next_packet *next_p;    /* ptr to next in chain  */|
  |   };                                                              |
  |   typedef struct dpi_next_packet       snmp_dpi_next_packet;      |
  |   #define snmp_dpi_next_packet_NULL_p  ((snmp_dpi_next_packet *)0)|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     object_p    A pointer to a NULL terminated character string that
                 represents the full OBJECT IDENTIFIER of the variable
                 instance that is being accessed.  It basically is a
                 concatenation of the fields group_p and instance_p.
                 Using this field is not recommended because it is only
                 included for DPI version 1 compatibility and it maybe
                 withdrawn in a later version.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the registered sub-tree that caused this
                 GETNEXT request to be passed to this DPI sub-agent.
                 This sub-tree must have a trailing dot.
 
     instance_p  A pointer to a NULL terminated character string that
                 represents the rest (the piece following the sub-tree
                 part) of the OBJECT IDENTIFIER of the variable instance
                 being accessed.  Use of the term instance_p here should
                 not be confused with an OBJECT instance, because this
                 string may consist of a piece of the OBJECT IDENTIFIER
                 plus the INSTANCE IDENTIFIER.  In this case of GETNEXT,
                 the instance_p may be the NULL pointer which means that
                 the request is for the first variable instance in the
                 registered sub-tree.
 
 
 
 
 
 
Wijnen                                                        [Page 83]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     next_p      A pointer to a possible next snmp_dpi_get_packet
                 structure.  If this next field contains the NULL ptr,
                 then this is the end of the chain.
 
     DESCRIPTION
 
     The snmp_dpi_next_packet structure represents a parse tree for a
     DPI GETNEXT packet.
 
     At the sub-agent side, the snmp_dpi_next_packet structure is
     normally created as a result of a call to pDPIpacket().  This is
     the case if the DPI packet is of type SNMP_DPI_GETNEXT.  The
     snmp_dpi_hdr structure then contains a pointer to a chain of one or
     more snmp_dpi_next_packet structures.
 
     The DPI sub-agent programmer uses this structure to find out which
     variables instances are to be returned in a DPI RESPONSE.
 
     At the agent side, this structure is normally created with a call
     to the mkDPInext() function.  The programmer here normally does not
     inspect the structure itself.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.11, "The mkDPInext() Function" on page 52
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 84]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.5  THE SNMP_DPI_HDR STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct snmp_dpi_hdr {                                           |
  |     unsigned char  proto_major;   /* always 2: SNMP_DPI_PROTOCOL*/|
  |     unsigned char  proto_version; /* DPI version                */|
  |     unsigned char  proto_release; /* DPI release                */|
  |     unsigned short packet_id;     /* 16-bit, DPI packet ID      */|
  |     unsigned char  packet_type;   /* DPI packet type            */|
  |     union {                                                       |
  |        snmp_dpi_reg_packet      *reg_p;                           |
  |        snmp_dpi_ureg_packet     *ureg_p;                          |
  |        snmp_dpi_get_packet      *get_p;                           |
  |        snmp_dpi_next_packet     *next_p;                          |
  |        snmp_dpi_next_packet     *bulk_p;                          |
  |        snmp_dpi_set_packet      *set_p;                           |
  |        snmp_dpi_resp_packet     *resp_p;                          |
  |        snmp_dpi_trap_packet     *trap_p;                          |
  |        snmp_dpi_open_packet     *open_p;                          |
  |        snmp_dpi_close_packet    *close_p;                         |
  |        unsigned char            *any_p;                           |
  |     } data_u;                                                     |
  |   };                                                              |
  |   typedef struct snmp_dpi_hdr    snmp_dpi_hdr;                    |
  |   #define snmp_dpi_hdr_NULL_p    ((snmp_dpi_hdr *)0)              |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     proto_major    This defines the major protocol, and for SNMP DPI it
                    is always 2.
 
     proto_version  This defines the DPI version.
 
     proto_release  This defines the DPI release.
 
     packet_id      This field contains the packet ID of the DPI packet.
                    When you create a response to a request, the packet
                    ID must be the same as that of the request. This is
                    taken care of if you use the mkDPIresponse()
                    function.
 
 
 
Wijnen                                                        [Page 85]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     packet_type    Specifies what kind of DPI packet (parse tree) we
                    are dealing with.
                    See 2.6.2, "DPI Packet Types" on page 104 for a list
                    of currently defined DPI packet types
 
     data_u         This is a union of pointers to the different types
                    of data structures that are created based on the
                    packet_type field.  The pointers themselves have
                    names that are self_explanatory.
 
     The fields proto_major, proto_version, proto_release and packet_id
     are basically for DPI internal use.  So the DPI programmer normally
     needs not be concerned about them.  If you work with an unreliable
     DPI "connection" (like UDP), then you may want to use the packet_id
     field to ensure you are handling the correct packet.
 
     DESCRIPTION
 
     The snmp_dpi_hdr structure is the anchor of a DPI parse tree.
 
     At the sub-agent side, the snmp_dpi_hdr structure is normally
     created as a result of a call to pDPIpacket().
 
     The DPI sub-agent programmer uses this structure to interrogate
     packets.  Depending on the packet_type, the pointer to the chain of
     one or more packet_type specific structures that contain the actual
     packet data can be picked.
 
     At the agent side, for creating an out-going packet, this structure
     is normally created with a call to the mkDPIhdr() or the
     mkDPIhdr_version() function.  After that the structure is completed
     by setting a proper pointer to the a chain of one ore more packet
     type specific data structures.
 
     At the agent side, for an incoming packet, this structure is
     normally created with a Depending on the packet_type, you can pick
     up the pointer to the chain of one or more packet_type specific
     structures that contain the actual packet data.  In the case of an
     incoming SNMP DPI ARE_YOU_THERE packet, there is just the
     snmp_dpi_hdr without any packet specific data.
 
     The storage for a DPI parse tree is always dynamically allocated
     and it is then the callers responsibility to free this parse tree
     when it is no longer needed. You can use the fDPIparse() function
     to do that.  Be aware that some mkDPIxxxx functions do free the
     parse tree that is passed to them. An example is the mkDPIpacket()
     function.
 
     RELATED INFORMATION
 
 
 
 
Wijnen                                                        [Page 86]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.3, "The fDPIparse() Function" on page 34
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.10, "The mkDPIhdr_version() Function" on page 49
         2.4.2, "The snmp_dpi_close_packet structure" on page 80
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
         2.4.1, "The snmp_dpi_bulk_packet structure" on page 78
         2.4.6, "The snmp_dpi_open_packet structure" on page 88
         2.4.7, "The snmp_dpi_reg_packet structure" on page 90
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.4.10, "The snmp_dpi_trap_packet structure" on page 96
         2.4.11, "The snmp_dpi_ureg_packet structure" on page 98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 87]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.6  THE SNMP_DPI_OPEN_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_open_packet {                                        |
  |     char           *oid_p;         /* sub-agent ID, OID string  */|
  |     char           *description_p; /* sub-agent descriptive name*/|
  |     unsigned short  timeout;       /* requested timeout,seconds */|
  |     unsigned short  max_varBinds;  /* max varBinds I can handle */|
  |     char            character_set; /* character set selection   */|
  |     unsigned short  password_len;  /* length of password        */|
  |     unsigned char  *password_p;    /* ptr to password itself    */|
  |   };                                                              |
  |   typedef struct dpi_open_packet      snmp_dpi_open_packet;       |
  |   #define snmp_dpi_open_packet_NULL_p ((snmp_dpi_open_packet *)0) |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     oid_p         A pointer to a NULL terminated character string
                   representing the OBJECT IDENTIFIER which uniquely
                   identifies the sub-agent.
 
     description_p A pointer to a NULL terminated character string which
                   is a descriptive name for the sub-agent.  This can be
                   any DisplayString, which basically is an octet string
                   containing only characters from the ASCII NVT set.
 
     timeout       The requested timeout for this sub-agent.  An agent
                   often has a limit for this value and it will use that
                   limit if this value is larger.
 
     max_varBinds  The maximum number of varBinds per DPI packet that
                   the sub-agent is prepared to handle.  It must be a
                   positive number greater than zero.  If a value
                   greater than 1 is specified, then the agent will try
                   to combine as many varBinds (belonging to the same
                   sub-tree) per DPI packet as possible (up to this
                   value).
 
     character_set The selected character set for string based data:
 
 
 
 
 
Wijnen                                                        [Page 88]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                   DPI_NATIVE_CSET specifies that you want to use the
                                   native character set of the platform
                                   on which the agent that you connect
                                   to is running.
                   DPI_ASCII_CSET  specifies that you want to use the
                                   ASCII character set.  The agent will
                                   translate between ASCII and the
                                   native character set as required.
 
                   See 2.5, "Character Set Selection" on page 101 for
                   more information on character set selection.
 
     password_len  The length (in octets) of an optional password.  It
                   depends on the agent implementation if a password is
                   needed.  If not, then a zero length may be specified.
 
     password_p    A pointer to an octet string representing the
                   password for this sub-agent.  A password may include
                   any character value, including the NULL character.
                   If the password_len is zero, then this can be a NULL
                   pointer.
 
     DESCRIPTION
 
     The snmp_dpi_open_packet structure represents a parse tree for a
     DPI OPEN packet.
 
     The snmp_dpi_open_packet structure is normally created as a result
     of a call to pDPIpacket().  This is the case if the DPI packet is
     of type SNMP_DPI_OPEN.  The snmp_dpi_hdr structure then contains a
     pointer to a snmp_dpi_open_packet structure.
 
     Normally this will only happen at the agent side.  So the DPI
     sub-agent programmer need not be concerned with this structure. The
     mkDPIopen() function can be used to create a DPI OPEN packet.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.3, "The fDPIparse() Function" on page 34
         2.3.12, "The mkDPIopen() Function" on page 54
         2.5, "Character Set Selection" on page 101
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 89]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.7  THE SNMP_DPI_REG_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_reg_packet {                                         |
  |     unsigned short         timeout; /* requested timout; seconds*/|
  |     long int               priority;/* requested priority       */|
  |     char                  *group_p; /* ptr to sub-tree (group)  */|
  |     struct dpi_reg_packet *next_p;  /* ptr to next in chain     */|
  |     char                   bulk;    /* GETBULK selection yes/no */|
  |   };                                                              |
  |   typedef struct dpi_reg_packet        snmp_dpi_reg_packet;       |
  |   #define snmp_dpi_reg_packet_NULL_p   ((snmp_dpi_reg_packet *)0) |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     timeout     The requested timeout in seconds.  An agent often has a
                 limit for this value and it will use that limit if this
                 value is larger.
 
     priority    The requested priority.  This field may contain any of
                 these values:
 
                 -1   Requests the best available priority.
                 0    Requests a better priority than the highest
                      priority currently registered.  Use this value to
                      obtain the SNMP DPI version 1 behavior.
                 nnn  Any other positive value.  You will receive that
                      priority if available or the next best priority
                      that is available.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the sub-tree to be registered.  This
                 sub-tree must have a trailing dot.
 
     next_p      A pointer to a possible next snmp_dpi_reg_packet
                 structure.  If this next field contains the NULL ptr,
                 then this is the end of the chain.  Currently, we do
                 not support multiple registrations in one DPI packet,
                 so this field should always be zero.
 
 
 
 
 
Wijnen                                                        [Page 90]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     bulk        The GETBULK selection.  The field may contain one of
                 these values:
 
                 DPI_BULK_NO Do not pass any GETBULK requests; instead
                             map a GETBULK request into multiple GETNEXT
                             requests.
                 DPI_BULK_YES Do pass a GETBULK request to the
                             sub-agent.
 
     DESCRIPTION
 
     The snmp_dpi_reg_packet structure represents a parse tree for a DPI
     REGISTER packet.
 
     The snmp_dpi_reg_packet structure is normally created as a result
     of a call to pDPIpacket().  This is the case if the DPI packet is
     of type SNMP_DPI_REGISTER.  The snmp_dpi_hdr structure then
     contains a pointer to a snmp_dpi_reg_packet structure.
 
     Normally, this will only happen at the agent side, so the DPI
     sub-agent programmer need not be concerned with this structure.  To
     create a DPI REGISTER pactket, the programmer is advised to use the
     mkDPIregister() function.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.14, "The mkDPIregister() Function" on page 59
         2.5, "Character Set Selection" on page 101
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 91]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.8  THE SNMP_DPI_RESP_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_resp_packet {                                        |
  |     char                   error_code; /* like: SNMP_ERROR_xxx  */|
  |     unsigned long int      error_index;/* 1st varBind in error  */|
  |     #define resp_priority  error_index /* if respons to register*/|
  |     struct dpi_set_packet *varBind_p;  /* ptr to varBind, chain */|
  |                                        /* of dpi_set_packets    */|
  |   };                                                              |
  |   typedef struct dpi_resp_packet       snmp_dpi_resp_packet;      |
  |   #define snmp_dpi_resp_packet_NULL_p  ((snmp_dpi_resp_packet *)0)|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     error_code    The return code or the error code.
                   See 2.6.3, "DPI RESPONSE Error Codes" on page 105 for
                   a list of valid codes.
 
     error_index   Specifies the first varBind is in error.  Counting
                   starts at 1 for the first varBind.  This field should
                   be zero (SNMP_ERROR_noError) if there is no error.
 
     resp_priority This is a redefinition of the error_index field.  If
                   the response it to a DPI REGISTER request and the
                   error_code is equal to SNMP_ERROR_DPI_noError, then
                   this field contains the priority that was actually
                   assigned.
 
     varBind_p     A pointer to the a chain of one ore more
                   snmp_dpi_set_structures, representing varBinds of the
                   response.  This field contains a NULL pointer if
                   there are no varBinds in the response.
 
     DESCRIPTION
 
     The snmp_dpi_resp_packet structure represents a parse tree for a
     DPI RESPONSE packet.
 
 
 
 
 
Wijnen                                                        [Page 92]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     The snmp_dpi_resp_packet structure is normally created as a result
     of a call to pDPIpacket().  This is the case if the DPI packet is
     of type SNMP_DPI_RESPONSE.  The snmp_dpi_hdr structure then
     contains a pointer to a snmp_dpi_resp_packet structure.
 
     Most of the time this only happens at the agent side.  At the DPI
     sub-agent side, a DPI RESPONSE should only be expected at
     initialization and termination time when the sub-agent has issued a
     DPI OPEN, DPI REGISTER or DPI UNREGISTER request.
 
     The DPI programmer is advised to use the mkDPIresponse() function
     to prepare a DPI RESPONSE packet.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.15, "The mkDPIresponse() Function" on page 62
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 93]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.9  THE SNMP_DPI_SET_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_set_packet {                                         |
  |     char             *object_p;    /* ptr to Object ID (string) */|
  |     char             *group_p;     /* ptr to sub-tree (group)   */|
  |     char             *instance_p;  /* ptr to rest of OID        */|
  |     unsigned char     value_type;  /* value type: SNMP_TYPE_xxx */|
  |     unsigned short    value_len;   /* value length              */|
  |     char             *value_p;     /* ptr to the value itself   */|
  |     struct dpi_set_packet *next_p; /* ptr to next in chain      */|
  |   };                                                              |
  |   typedef struct dpi_set_packet       snmp_dpi_set_packet;        |
  |   #define snmp_dpi_set_packet_NULL_p  ((snmp_dpi_set_packet *)0)  |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     object_p    A pointer to a NULL terminated character string that
                 represents the full OBJECT IDENTIFIER of the variable
                 instance that is being accessed.  It basically is a
                 concatenation of the fields group_p and instance_p.
                 Using this field is not recommended because it is only
                 included for DPI version 1 compatibility and it maybe
                 withdrawn in a later version.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the registered sub-tree that caused this
                 SET, COMMIT or UNDO request to be passed to this DPI
                 sub-agent.  The sub-tree must have a trailing dot.
 
     instance_p  A pointer to a NULL terminated character string that
                 represents the rest (the piece following the sub-tree
                 part) of the OBJECT IDENTIFIER of the variable instance
                 being accessed.  Use of the term instance_p here should
                 not be confused with an OBJECT instance because this
                 string may consist of a piece of the OBJECT IDENTIFIER
                 plus the INSTANCE IDENTIFIER.
 
 
 
 
 
 
Wijnen                                                        [Page 94]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     value_type  The type of the value.
                 See 2.6.5, "DPI SNMP Value Types" on page 108 for a
                 list of currently defined value types.
 
     value_len   This is an unsigned 16-bit integer that specifies the
                 length (in octets) of the value pointed to by the value
                 field.  The length may be zero if the value if of type
                 SNMP_TYPE_NULL.
 
     value_p     A pointer to the actual value.  This field may contain
                 a NULL pointer if the value if of type SNMP_TYPE_NULL.
                 See 2.6.6, "Value Representation" on page 109 for
                 information on how the data is represented for the
                 various value types.
 
     next_p      A pointer to a possible next snmp_dpi_set_packet
                 structure.  If this next field contains the NULL
                 pointer, then this is the end of the chain.
 
     DESCRIPTION
 
     The snmp_dpi_set_packet structure represents a parse tree for a DPI
     SET request.
 
     The snmp_dpi_set_packet structure may be created as a result of a
     call to pDPIpacket().  This is the case if the DPI packet is of
     type SNMP_DPI_SET, SNMP_DPI_COMMIT or SNMP_DPI_UNDO.  The
     snmp_dpi_hdr structure then contains a pointer to a chain of one
     ore more snmp_dpi_set_packet structures.
 
     This structure can also be created with a mkDPIset() call, which is
     typically used when preparing varBinds for a DPI RESPONSE packet.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.16, "The mkDPIset() Function" on page 65
         2.6.5, "DPI SNMP Value Types" on page 108
         2.6.6, "Value Representation" on page 109
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 95]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.10  THE SNMP_DPI_TRAP_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_trap_packet {                                        |
  |     long int               generic;     /* generic trap type    */|
  |     long int               specific;    /* specific trap type   */|
  |     struct dpi_set_packet *varBind_p;   /* ptr to varBind chain */|
  |     char                  *enterprise_p;/* ptr to enterpriseID  */|
  |   };                                                              |
  |   typedef struct dpi_trap_packet        snmp_dpi_trap_packet;     |
  |   #define snmp_dpi_trap_packet_NULL_p  ((snmp_dpi_trap_packet *)0)|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     generic       The generic trap type.  The range of this value is
                   0-6, where 6 (enterpriseSpecific) is the type that is
                   probably used most by DPI sub-agent programmers.  The
                   values 0-5 are well defined standard SNMP traps.
 
     specific      The (enterprise) specific trap type.  This can be any
                   value that is valid for the MIB sub-trees that the
                   sub-agent implements.
 
     varBind_p     A pointer to a chain of one or more
                   snmp_dpi_set_packet structures, representing the
                   varBind(s) to be included in the trap.  A NULL
                   pointer means that there are no varBinds included in
                   the trap.
 
     enterprise_p  A pointer to a NULL terminated character string
                   representing the enterprise ID (OBJECT IDENTIFIER)
                   for which this trap is defined.  A NULL pointer can
                   be used. In this case, the sub-agent Identifier as
                   passed in the DPI OPEN packet will be used when the
                   agent receives this packet.
 
     DESCRIPTION
 
     The snmp_dpi_trap_packet structure represents a parse tree for a
     DPI TRAP packet.
 
 
 
 
Wijnen                                                        [Page 96]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     At the agent side, the snmp_dpi_trap_packet structure is normally
     created as a result of a call to pDPIpacket().  This is the case if
     the DPI packet is of type SNMP_DPI_TRAP.  The snmp_dpi_hdr
     structure then contains a pointer to a snmp_dpi_trap_packet
     structure.
 
     The DPI sub-agent programmer should not be concerned with this
     structure.  A programmer is advised to prepare a DPI TRAP packet
     using the mkDPItrap() function.  In that case the structure isn't
     seen.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.17, "The mkDPItrap() Function" on page 71
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 97]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.11  THE SNMP_DPI_UREG_PACKET STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct dpi_ureg_packet {                                        |
  |     char                   reason_code;/* reason for unregister */|
  |     char                  *group_p;    /* ptr to sub-tree(group)*/|
  |     struct dpi_reg_packet *next_p;     /* ptr to next in chain  */|
  |   };                                                              |
  |   typedef struct dpi_ureg_packet       snmp_dpi_ureg_packet;      |
  |   #define snmp_dpi_ureg_packet_NULL_p  ((snmp_dpi_ureg_packet *)0)|
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     reason_code The reason for the unregister.
                 See 2.6.4, "DPI UNREGISTER Reason Codes" on page 107
                 for a list of the currently defined reason codes.
 
     group_p     A pointer to a NULL terminated character string that
                 represents the sub-tree to be unregistered.  This
                 sub-tree must have a trailing dot.
 
     next_p      A pointer to a possible next snmp_dpi_ureg_packet
                 structure.  If this next field contains the NULL ptr,
                 then this is the end of the chain.  Currently we do not
                 support multiple unregister requests in one DPI packet,
                 so this field should always be zero.
 
     DESCRIPTION
 
     The snmp_dpi_ureg_packet structure represents a parse tree for a
     DPI UNREGISTER request.
 
     The snmp_dpi_ureg_packet structure is normally created as a result
     of a call to pDPIpacket().  This is the case if the DPI packet is
     of type SNMP_DPI_UNREGISTER.  The snmp_dpi_hdr structure then
     contains a pointer to a snmp_dpi_ureg_packet structure.
 
     The DPI programmer is advised to use the mkDPIunregister() function
     to create a DPI UNREGISTER packet.
 
 
 
 
Wijnen                                                        [Page 98]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.3.18, "The mkDPIunregister() Function" on page 73
         2.4.5, "The snmp_dpi_hdr structure" on page 85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                        [Page 99]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.4.12  THE SNMP_DPI_U64 STRUCTURE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     STRUCTURE DEFINITION
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   struct snmp_dpi_u64 {           /* for unsigned 64-bit int */   |
  |     unsigned long high;           /* - high order 32 bits    */   |
  |     unsigned long low;            /* - low order  32 bits    */   |
  |   };                                                              |
  |   typedef struct snmp_dpi_u64     snmp_dpi_u64;                   |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     STRUCTURE MEMBERS
 
     high      The high order (most significant) 32 bits
 
     low       The low order (least significant) 32 bits
 
     DESCRIPTION
 
     The snmp_dpi_u64 structure represents an unsigned 64-bit integer as
     need for values with a type of SNMP_TYPE_Counter64.
 
     The snmp_dpi_u64 structure may be created as a result of a call to
     pDPIpacket().  This is the case if the DPI packet is of type
     SNMP_DPI_SET and one of the values has a type of
     SNMP_TYPE_Counter64.  The value_p pointer of the
     snmp_dpi_set_packet structure will then point to an snmp_dpi_u64
     structure.
 
     The DPI programmer must also use an snmp_dpi_u64 structure as the
     argument to a mkDPIset() call if he wants to create a value of type
     SNMP_TYPE_Counter64.
 
     RELATED INFORMATION
 
         2.3.19, "The pDPIpacket() Function" on page 75
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.6.5, "DPI SNMP Value Types" on page 108
         2.6.6, "Value Representation" on page 109
 
 
 
 
 
 
Wijnen                                                       [Page 100]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.5  CHARACTER SET SELECTION
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     Base on the character set used on the platform where agent and
     sub-agent are running, there are basically three scenarios that you
     may be faced with:
 
     1.  Both run on an ASCII based platform.
 
         In reality a lot of platforms use the ASCII character set, and
         for those platforms, the character set selection is kind of a
         moot point. Just use the native character set in that case,
         which is then ASCII anyway.
 
     2.  The both run on the same non-ASCII based platform.
 
         It is expected that the agent and the sub-agent normally run on
         the same machine or at least on the same platform.  In that
         case, it is easiest to use the native character set for data
         that is represented as strings.  If such native character set
         is not the ASCII character set, then the agent must translate
         from ASCII to the native character set (and vice versa) as
         needed.
 
     3.  One runs on ASCII based platform, the other on a non-ASCII
         based platform.
 
         If the agent and sub-agent each run on their own platform and
         those platforms use different native character sets (like IBM
         PS/2 OS/2 uses ASCII and IBM Mainframe MVS uses EBCDIC) then
         you must select the ASCII character set, so that you both know
         exactly how to represent string-based data that is being send
         back and forth.  The entity that is not ASCII based must do the
         translation from ASCII to the native character set (and vice
         versa) as needed.
 
     When the DPI sub-agent sends a DPI OPEN packet, it must specify the
     character set it wants to use.  The sub-agent here needs to know or
     figure out in an implementation dependent manner if the agent is
     running on a system with the same character set as the sub-agent
     (if you connect to the agent loopback or localhost, you might
     assume that you are using the same character set).  The sub-agent
     has two choices:
 
 
 
 
 
 
Wijnen                                                       [Page 101]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     DPI_NATIVE_CSET specifies that you want to use the native character
                     set of the platform on which the agent that you
                     connect to is running.
     DPI_ASCII_CSET  specifies that you want to use the ASCII character
                     set.  The agent will translate between ASCII and
                     the native character set as required.  If the
                     sub-agent is on a non-ASCII based platform, it may
                     have to translate also.
 
     The DPI packets have a number of fields that are represented as
     strings.  The fields that will/must be represented in the selected
     character set are:
 
     o   The null terminated string pointed to by the description_p,
         enterprise_p, group_p, instance_p, and oid_p arguments in the
         various mkDPIxxxx(...)  functions.
     o   The string pointed to by the value_p argument in the
         mkDPIset(...) function, that is if the value_type argument
         specifies that the value is a SNMP_TYPE_DisplayString or a
         SNMP_TYPE_OBJECT_IDENTIFIER.
     o   The null terminated string pointed to by the description_p,
         enterprise_p, group_p, instance_p, and oid_p pointers in the
         various snmp_dpi_xxxx_packet structures.
     o   The string pointed to by the value_P pointer in the
         snmp_dpi_set_packet structure, that is if the value_type field
         specifies that the value is a SNMP_TYPE_DisplayString or a
         SNMP_TYPE_OBJECT_IDENTIFIER.
 
     RELATED INFORMATION
 
         2.3.12, "The mkDPIopen() Function" on page 54
         2.4.6, "The snmp_dpi_open_packet structure" on page 88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 102]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6  CONSTANTS AND VALUES
 
     This section describes all the constants and names for values as
     they are defined in the snmp_dpi.h include file.
 
 
     2.6.1  DPI CLOSE REASON CODES
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     These are the currently defined DPI CLOSE reason codes as defined
     in the snmp_dpi.h include file:
 
         #define SNMP_CLOSE_otherReason                     1
         #define SNMP_CLOSE_goingDown                       2
         #define SNMP_CLOSE_unsupportedVersion              3
         #define SNMP_CLOSE_protocolError                   4
         #define SNMP_CLOSE_authenticationFailure           5
         #define SNMP_CLOSE_byManager                       6
         #define SNMP_CLOSE_timeout                         7
         #define SNMP_CLOSE_openError                       8
 
     These codes are used in the reason_code argument for the
     mkDPIclose() function and in the reason_code field in the
     snmp_dpi_close_packet structure.
 
     RELATED INFORMATION
 
         2.4.2, "The snmp_dpi_close_packet structure" on page 80
         2.3.7, "The mkDPIclose() Function" on page 43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 103]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6.2  DPI PACKET TYPES
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     These are the currently defined DPI packet types as defined in the
     snmp_dpi.h include file:
 
         #define SNMP_DPI_GET            1
         #define SNMP_DPI_GET_NEXT       2 /* old DPI 1.x style   */
         #define SNMP_DPI_GETNEXT        2
         #define SNMP_DPI_SET            3
         #define SNMP_DPI_TRAP           4
         #define SNMP_DPI_RESPONSE       5
         #define SNMP_DPI_REGISTER       6
         #define SNMP_DPI_UNREGISTER     7
         #define SNMP_DPI_OPEN           8
         #define SNMP_DPI_CLOSE          9
         #define SNMP_DPI_COMMIT        10
         #define SNMP_DPI_UNDO          11
         #define SNMP_DPI_GETBULK       12
         #define SNMP_DPI_TRAPV2        13 /* reserved, not ....    */
         #define SNMP_DPI_INFORM        14 /* reserved, implemented */
         #define SNMP_DPI_ARE_YOU_THERE 15
 
     These packet types are used in the type argument for the mkDPIhdr()
     function and in the packet_type field in the snmp_dpi_hdr
     structure.
 
     RELATED INFORMATION
 
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.3.9, "The mkDPIhdr() Function" on page 47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 104]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6.3  DPI RESPONSE ERROR CODES
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     In case of an error on an SNMP request like GET, GETNEXT, GETBULK,
     SET, COMMIT, UNDO the RESPONSE can have one of these currently
     defined error codes.  They are define in the snmp_dpi.h include
     file:
 
         #define SNMP_ERROR_noError             0
         #define SNMP_ERROR_tooBig              1
         #define SNMP_ERROR_noSuchName          2
         #define SNMP_ERROR_badValue            3
         #define SNMP_ERROR_readOnly            4
         #define SNMP_ERROR_genErr              5
         #define SNMP_ERROR_noAccess            6
         #define SNMP_ERROR_wrongType           7
         #define SNMP_ERROR_wrongLength         8
         #define SNMP_ERROR_wrongEncoding       9
         #define SNMP_ERROR_wrongValue          10
         #define SNMP_ERROR_noCreation          11
         #define SNMP_ERROR_inconsistentValue   12
         #define SNMP_ERROR_resourceUnavailable 13
         #define SNMP_ERROR_commitFailed        14
         #define SNMP_ERROR_undoFailed          15
         #define SNMP_ERROR_authorizationError  16
         #define SNMP_ERROR_notWritable         17
         #define SNMP_ERROR_inconsistentName    18
 
     In case of an error on a DPI only request (OPEN, REGISTER,
     UNREGISTER, ARE_YOU_THERE) the RESPONSE can have one of these
     currently defined error codes.  They are define in the snmp_dpi.h
     include file:
 
         #define SNMP_ERROR_DPI_noError                             0
         #define SNMP_ERROR_DPI_otherError                        101
         #define SNMP_ERROR_DPI_notFound                          102
         #define SNMP_ERROR_DPI_alreadyRegistered                 103
         #define SNMP_ERROR_DPI_higherPriorityRegistered          104
         #define SNMP_ERROR_DPI_mustOpenFirst                     105
         #define SNMP_ERROR_DPI_notAuthorized                     106
         #define SNMP_ERROR_DPI_viewSelectionNotSupported         107
         #define SNMP_ERROR_DPI_getBulkSelectionNotSupported      108
         #define SNMP_ERROR_DPI_duplicateSubAgentIdentifier       109
         #define SNMP_ERROR_DPI_invalidDisplayString              110
         #define SNMP_ERROR_DPI_characterSetSelectionNotSupported 111
 
 
 
 
Wijnen                                                       [Page 105]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     These codes are used in the error_code argument for the
     mkDPIresponse() function and in the error_code field in the
     snmp_dpi_resp_packet structure.
 
     RELATED INFORMATION
 
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
         2.3.15, "The mkDPIresponse() Function" on page 62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 106]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6.4  DPI UNREGISTER REASON CODES
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     These are the currently defined DPI UNREGISTER reason codes.  They
     are define in the snmp_dpi.h include file:
 
         #define SNMP_UNREGISTER_otherReason                1
         #define SNMP_UNREGISTER_goingDown                  2
         #define SNMP_UNREGISTER_justUnregister             3
         #define SNMP_UNREGISTER_newRegistration            4
         #define SNMP_UNREGISTER_higherPriorityRegistered   5
         #define SNMP_UNREGISTER_byManager                  6
         #define SNMP_UNREGISTER_timeout                    7
 
     These codes are used in the reason_code argument for the
     mkDPIunregister() function and in the reason_code field in the
     snmp_dpi_ureg_packet structure.
 
     RELATED INFORMATION
 
         2.4.11, "The snmp_dpi_ureg_packet structure" on page 98
         2.3.18, "The mkDPIunregister() Function" on page 73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 107]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6.5  DPI SNMP VALUE TYPES
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     These are the currently defined value types as as defined in the
     snmp_dpi.h include file:
 
       #define SNMP_TYPE_MASK           0x7f  /* mask to isolate type*/
       #define SNMP_TYPE_Integer32    (128|1) /* 32-bit INTEGER      */
       #define SNMP_TYPE_OCTET_STRING      2  /* OCTET STRING        */
       #define SNMP_TYPE_OBJECT_IDENTIFIER 3  /* OBJECT IDENTIFIER   */
       #define SNMP_TYPE_NULL              4  /* NULL, no value      */
       #define SNMP_TYPE_IpAddress         5  /* IMPLICIT OCTETSTRING*/
       #define SNMP_TYPE_Counter32    (128|6) /* 32-bit Counter      */
       #define SNMP_TYPE_Gauge32      (128|7) /* 32-bit Gauge        */
       #define SNMP_TYPE_TimeTicks    (128|8) /* 32-bit TimeTicks in */
                                              /* hundredths of a sec */
       #define SNMP_TYPE_DisplayString     9  /* DisplayString (TC)  */
       #define SNMP_TYPE_BIT_STRING        10 /* BIT STRING          */
       #define SNMP_TYPE_NsapAddress       11 /* IMPLICIT OCTETSTRING*/
       #define SNMP_TYPE_UInteger32   (128|12)/* 32-bit INTEGER      */
       #define SNMP_TYPE_Counter64         13 /* 64-bit Counter      */
       #define SNMP_TYPE_Opaque            14 /* IMPLICIT OCTETSTRING*/
       #define SNMP_TYPE_noSuchObject      15 /* IMPLICIT NULL       */
       #define SNMP_TYPE_noSuchInstance    16 /* IMPLICIT NULL       */
       #define SNMP_TYPE_endOfMibView      17 /* IMPLICIT NULL       */
 
     These value types are used in the value_type argument for the
     mkDPIset() function and in the value_type field in the
     snmp_dpi_set_packet structure.
 
     RELATED INFORMATION
 
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.3.16, "The mkDPIset() Function" on page 65
         2.6.6, "Value Representation" on page 109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 108]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6.6  VALUE REPRESENTATION
 
     Values in the snmp_dpi_set_packet structure are represented as
     follows:
 
     o   32-bit integers are defined as long int or unsigned long int
         (we assume that a long int is 4 bytes).
     o   64-bit integers are represented as an snmp_dpi_u64 (so-far we
         only deal with unsigned 64 bit integers in SNMP) structure that
         has two fields, the high order piece and the low order piece,
         each of type unsigned long int (we assume these are 4-bytes).
     o   Object Identifiers are NULL terminated strings in the selected
         character set, representing the OID in ASN.1 dotted notation.
         The length includes the terminating NULL.
         Example ASCII: '312e332e362e312e322e312e312e312e3000'h
         represents "1.3.6.1.2.1.1.1.0" which is sysDescr.0.
         Example EBCDIC: 'f14bf34bf64bf14bf24bf14bf14bf14bf000'h
         represents "1.3.6.1.2.1.1.1.0" which is sysDescr.0.
     o   DisplayStrings are in the selected character set.  The length
         specifies the length of the string.
         Example ASCII: '6162630d0a'h represents "abc\r\n", no NULL.
         Example EBCDIC: '8182830d25'h represents "abc\r\n", no NULL.
     o   IpAddress, NsapAddress and Opaque are implicit OCTET_STRING, so
         they are a sequence of octets/bytes.  This means for instance
         that the IP address is in network byte order.
     o   NULL has a zero length for the value, no value data, so a NULL
         pointer in the value_p field.
     o   noSuchObject, noSuchInstance and endOfMibView are implicit NULL
         and represented as such.
     o   BIT_STRING is an OCTET_STRING of the form uubbbb...bb, where
         the first octet (uu) is 0x00-0x07 and indicates the number of
         unused bits in the last octet (bb). The bb octets represent the
         bit string itself, where bit zero (0) comes first and so on.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 109]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.6.7  RETURN CODES FROM DPI TRANSPORT RELATED FUNCTIONS
 
     AUDIENCE
 
         DPI sub-agent programmer.
 
     These are the currently defined values for the return codes from
     DPI transport related functions.  They are defined in the
     snmp_dpi.h include file:
 
       #define DPI_RC_OK                0 /* all OK, no error         */
       #define DPI_RC_NOK              -1 /* some other error         */
       #define DPI_RC_NO_PORT          -2 /* can't figure out DPIport */
       #define DPI_RC_NO_CONNECTION    -3 /* no connection to DPIagent*/
       #define DPI_RC_EOF              -4 /* EOF receivd on connection*/
       #define DPI_RC_IO_ERROR         -5 /* Some I/O error on connect*/
       #define DPI_RC_INVALID_HANDLE   -6 /* unknown/invalid handle   */
       #define DPI_RC_TIMEOUT          -7 /* timeout occurred         */
       #define DPI_RC_PACKET_TOO_LARGE -8 /* packed too large, dropped*/
 
     These values are used as return codes for the transport related DPI
     functions.
 
     RELATED INFORMATION
 
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.2.4, "The DPIconnect_to_agent_UDP() Function" on page 20
         2.2.2, "The DPIconnect_to_agent_NMQ() Function" on page 16
         2.2.1, "The DPIawait_packet_from_agent() Function" on page 14
         2.2.6, "The DPIsend_packet_to_agent() Function" on page 24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 110]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     2.7  THE SNMP_DPI.H INCLUDE FILE
 
     AUDIENCE
 
         DPI sub-agent programmer.
         DPI agent programmer.
 
     The snmp_dpi.h include file defines the SNMP DPI API to the DPI
     programmer.
 
     SYNTAX
 
  +-------------------------------------------------------------------+
  |                                                                   |
  |   #include <snmp_dpi.h>                                           |
  |                                                                   |
  +-------------------------------------------------------------------+
 
     PARAMETER(S)
 
     None
 
     DESCRIPTION
 
     The snmp_dpi.h include file defines the SNMP DPI API to the DPI
     programmer. It has all the function proto-type statements, and it
     also has the definitions for the snmp_dpi structures.
 
     RELATED INFORMATION
 
     Macros, functions, structures, constants and values defined in the
     snmp_dpi.h include file:
 
         2.2.1, "The DPIawait_packet_from_agent() Function" on page 14
         2.2.3, "The DPIconnect_to_agent_TCP() Function" on page 18
         2.2.4, "The DPIconnect_to_agent_UDP() Function" on page 20
         2.2.2, "The DPIconnect_to_agent_NMQ() Function" on page 16
         2.3.1, "The DPIdebug() Function" on page 32
         2.2.5, "The DPIdisconnect_from_agent() Function" on page 22
         2.3.2, "The DPI_PACKET_LEN() macro" on page 33
         2.2.6, "The DPIsend_packet_to_agent() Function" on page 24
         2.3.3, "The fDPIparse() Function" on page 34
         2.3.4, "The fDPIset() Function" on page 36
         2.3.5, "The mkDPIAreYouThere() Function" on page 38
         2.3.7, "The mkDPIclose() Function" on page 43
         2.3.8, "The mkDPIget() Function" on page 45
         2.3.9, "The mkDPIhdr() Function" on page 47
         2.3.10, "The mkDPIhdr_version() Function" on page 49
         2.3.11, "The mkDPInext() Function" on page 52
         2.3.12, "The mkDPIopen() Function" on page 54
 
 
 
Wijnen                                                       [Page 111]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         2.3.6, "The mkDPIbulk() Function" on page 40
         2.3.13, "The mkDPIpacket() Function" on page 57
         2.3.14, "The mkDPIregister() Function" on page 59
         2.3.15, "The mkDPIresponse() Function" on page 62
         2.3.16, "The mkDPIset() Function" on page 65
         2.3.17, "The mkDPItrap() Function" on page 71
         2.3.18, "The mkDPIunregister() Function" on page 73
         2.3.19, "The pDPIpacket() Function" on page 75
         2.4.2, "The snmp_dpi_close_packet structure" on page 80
         2.4.3, "The snmp_dpi_get_packet structure" on page 81
         2.4.4, "The snmp_dpi_next_packet structure" on page 83
         2.4.1, "The snmp_dpi_bulk_packet structure" on page 78
         2.4.5, "The snmp_dpi_hdr structure" on page 85
         2.2.7, "The lookup_host() Function" on page 26
         2.4.6, "The snmp_dpi_open_packet structure" on page 88
         2.2.8, "The query_DPI_port() Function" on page 28
         2.4.7, "The snmp_dpi_reg_packet structure" on page 90
         2.4.8, "The snmp_dpi_resp_packet structure" on page 92
         2.4.9, "The snmp_dpi_set_packet structure" on page 94
         2.4.10, "The snmp_dpi_trap_packet structure" on page 96
         2.4.11, "The snmp_dpi_ureg_packet structure" on page 98
         2.6.1, "DPI CLOSE Reason Codes" on page 103
         2.6.2, "DPI Packet Types" on page 104
         2.6.3, "DPI RESPONSE Error Codes" on page 105
         2.6.4, "DPI UNREGISTER Reason Codes" on page 107
         2.6.5, "DPI SNMP Value Types" on page 108
         2.5, "Character Set Selection" on page 101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 112]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     3.0  SNMP DPI 1.1 API
 
     The DPI API for SNMP DPI version 1.1 is reasonably well documented
     (at least for the sub-agent programmer) in the latest Programmers
     Reference manuals for the IBM TCP/IP products for OS/2, VM and MVS.
 
     You can keep your existing DPI 1.1 sub-agent and communicate with a
     DPI capable agent that supports DPI 1.1 in addition to DPI 2.0. For
     example, the IBM Research new Platform Independent SNMP stack
     provides support for multiple versions of DPI, namely version 1.0,
     version 1.1 and version 2.0.
 
     Normally you would compile your DPI 1.1 sub-agent with the DPI 1.1
     snmp_dpi.h include file and link-edit it with the provided DPILIB
     at the DPI 1.1 level.  You can continue to do this until you are
     ready to migrate to DPI version 2.0.
 
     You can also compile your DPI API 1.1 based sub-agents with the new
     include files and then link them with the new object files.  You do
     this by requesting DPI version 1.1 compatibility via a few -D
     compiler flags.  What happens in this case is that the DPI 1.1
     functions are mapped onto the DPI 2.0 function via a set of macro
     definitions, which are defined in the snmp_dpi1.h include file.
     This include file is automatically include if you ask for DPI 1.1
     compatibility.  However, a number of field names in the
     snmp_dpi_xxxx_packet structures have changed so that the names are
     now more consistent throughout the DPI code. The new names also
     comply with POSIX such that you can see from the name if the value
     is a pointer or a union.  The names that have changed and that
     affect the sub-agent code are listed in Table 1 on page 114.  There
     is no clean approach to make this change transparent, you probably
     will have to change the names in your code.  You may want to try a
     simple set of defines like:
 
       #define packet_body  data_u
       #define dpi_get      get_p
       #define dpi_set      set_p
       #define dpi_next     next_p
       #define dpi_response resp_p
       #define dpi_trap     trap_p
       #define group_id     group_p
       #define object_id    object_p
       #define value        value_p
       #define type         value_type
       #define next         next_p
       #define enterprise   enterprise_p
 
     But they may conflict with other definitions that you have, in
     which case you must change your code.
 
 
 
Wijnen                                                       [Page 113]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     +-----------------------------------------------------------------+
     | Table 1. Changed field names in snmp_dpi_xxxx_packet            |
     |          structures.                                            |
     +---------------+----------------+--------------------------------+
     | OLD NAME      | NEW NAME       | DATA STRUCTURE (XXXX)          |
     +---------------+----------------+--------------------------------+
     | group_id      | group_p        | getnext                        |
     +---------------+----------------+--------------------------------+
     | object_id     | object_p       | get, getnext, set              |
     +---------------+----------------+--------------------------------+
     | value         | value_p        | set                            |
     +---------------+----------------+--------------------------------+
     | type          | value_type     | set                            |
     +---------------+----------------+--------------------------------+
     | next          | next_p         | set                            |
     +---------------+----------------+--------------------------------+
     | enterprise    | enterprise_p   | trap                           |
     +---------------+----------------+--------------------------------+
     | packet_body   | data_u         | dpi_hdr                        |
     +---------------+----------------+--------------------------------+
     | dpi_get       | get_p          | hdr (packet_body)              |
     +---------------+----------------+--------------------------------+
     | dpi_getnext   | next_p         | hdr (packet_body)              |
     +---------------+----------------+--------------------------------+
     | dpi_set       | set_p          | hdr (packet_body)              |
     +---------------+----------------+--------------------------------+
     | dpi_trap      | trap_p         | hdr (packet_body)              |
     +---------------+----------------+--------------------------------+
 
     The advantage of using recompiling with the new include files and
     using the new DPI code is that this new DPI code has a more
     extensive error detection capability.  You must however use object
     files of the new DPI code that also have been compiled with the DPI
     1.1 compatibility.  To create your DPI 1.1 based sub-agent with the
     new code, perform the following steps:
 
     o   compile -DSNMP_DPI_VERSION=1 -DSNMP_DPI_RELEASE=1 yourcode.c
     o   compile -DSNMP_DPI_VERSION=1 -DSNMP_DPI_RELEASE=1 snmp_mDPI.c
     o   compile -DSNMP_DPI_VERSION=1 -DSNMP_DPI_RELEASE=1 snmp_qDPI.c
     o   compile -DSNMP_DPI_VERSION=1 -DSNMP_DPI_RELEASE=1 snmp_lDPI.c
     o   linkedit yourcode.obj snmp_mDPI.obj snmp_qDPI.obj snmp_lDPI.obj
 
     The new executable should now be able to communicate as a DPI 1.1
     sub-agent with an agent that support DPI 1.1.
 
     Instead of using the compile flag options:
 
         -DSNMP_DPI_VERSION=1 -DSNMP_DPI_RELEASE=0
         -DSNMP_DPI_VERSION=1 -DSNMP_DPI_RELEASE=1
 
 
 
 
Wijnen                                                       [Page 114]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     you can also use a preprocessor #define directive to specify that
     you want DPI 1.1 compatibility:
 
          #define SNMP_DPI_VERSION 1
          #define SNMP_DPI_RELEASE 1  /* 1 or 0 is valid */
          #include <snmp_dpi.h>
 
     The #define directives must precede the #include <snmp_dpi.h>,
     because it is in that include file that the level of the SNMP DPI
     API is defined. If you specify DPI 1.x compatibility, it also
     includes an additional <snmp_dpi1.h> include file.
 
     If you want to convert to DPI 2.0 (which prepares you also for
     SNMPv2), then you must make changes to your code.  See 4.0, "How to
     change your DPI sub-agent to DPI 2.0" on page 116 for more
     information.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 115]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     4.0  HOW TO CHANGE YOUR DPI SUB-AGENT TO DPI 2.0
 
     When you want to change your DPI 1.x based sub-agent code to the
     DPI 2.0 level, then you may use these guidelines of steps to do:
 
     o   Things you MUST do:
 
         -   Add a mkDPIopen() call and send the created packet to the
             agent.  This opens your "DPI connection" with the agent.
             Wait for the response and ensure that the open is accepted.
             You need to pass a sub-agent ID (Object Identifier) which
             must be a unique ASN.1 OID.  See 2.3.12, "The mkDPIopen()
             Function" on page 54 for more information.
         -   Change your mkDPIregister() calls and pass the arguments
             according to the new function prototype.  You must also
             expect a RESPONSE to the REGISTER request.  See 2.3.14,
             "The mkDPIregister() Function" on page 59 for more
             information.
         -   Change mkDPIset() and/or mkDPIlist() calls to the new
             mkDPIset() call. Basically all mkDPIset() calls are now of
             the DPI 1.1 mkDPIlist() form.  See 2.3.16, "The mkDPIset()
             Function" on page 65 for more information.
         -   Change mkDPItrap() and mkDPItrape() calls to the new
             mkDPItrap() call. Basically all mkDPItrap() calls are now
             of the DPI 1.1 mkDPItrape() form.  See 2.3.17, "The
             mkDPItrap() Function" on page 71 for more information.
         -   Add code to recognize DPI RESPONSE packets (they should be
             expected as a result of OPEN, REGISTER, UNREGISTER
             requests).
         -   Add code to unregister your sub-tree(s) and close the "DPI
             connection" when you want to terminate the sub-agent.  See
             2.3.18, "The mkDPIunregister() Function" on page 73 and
             2.3.7, "The mkDPIclose() Function" on page 43 for more
             information.
         -   Change your code to use the new SNMPv2 error codes as
             defined in the snmp_dpi.h include file.
         -   Change your code that handles a GET request.  It should
             return a varBind with SNMP_TYPE_noSuchObject or
             SNMP_TYPE_noSuchInstance instead of an error
             SNMP_ERROR_noSuchName if the object or the instance do not
             exist.  This is not considered an error any more, and so
             you should return an SNMP_ERROR_noError with an error index
             of zero.
         -   Change your code that handles a GETNEXT request.  It should
             return a varBind with SNMP_TYPE_endOfMibView instead of an
             error SNMP_ERROR_noSuchName if you reach the end of your
             MIB or sub-tree.  This is not considered an error any more,
             and so you should return an SNMP_ERROR_noError with an
             error index of zero.
 
 
 
Wijnen                                                       [Page 116]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     o   Things you might want to consider, but are not mandatory.
 
         -   Do not reference the object ID pointer (object_p) in the
             snmp_dpi_xxxx_packet structures anymore.  Instead start
             using the group_p and instance_p pointers.  The object_p
             pointer may be removed in a future version of the DPI API.
         -   Check 2.2, "Transport Related DPI API Functions" on page 13
             to see if you want to use those functions instead of using
             your own code for those functions.
         -   Consider using more than 1 varBind per DPI packet.  You can
             specify this on the REGISTER request.  You must then be
             prepared to handle multiple varBinds per DPI packet. The
             varBinds are chained via the various snmp_dpi_xxxx_packet
             structures.  See 2.3.14, "The mkDPIregister() Function" on
             page 59 for more information.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 117]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
     5.0  A SIMPLE SAMPLE DPI SUB-AGENT
 
     In this chapter we will discuss the implementation of a very basic
     and simple sample DPI sub-agent.
 
     The code "dpi_sample.c" is included with the freely available code
     package.
 
 
     5.1  OVERVIEW OF SUB-AGENT PROCESSING
 
     This overview assumes that the sub-agent communicates with the
     agent over a TCP connection. Other connection implementations are
     possible, and in that case, the processing approach may be a bit
     different.
 
     We also take the most simplistic sample in the sense that we will
     request the agent to send us at most one varBind per DPI packet, so
     we do not need to loop through a list of varBinds.  Potentially,
     you may gain performance improvements if you allow for multiple
     varBinds per DPI packet (on GET, GETNEXT, SET requests), but to do
     so, your code will have to loop through the varBind list and so it
     becomes somewhat more complicated.  We assume that the DPI
     sub-agent programmer can handle that once he or she understands the
     basics of the DPI API.
 
     For our simple sub-agent we have defined a dpiSimple mib as follows
 
       DPISimple-MIB DEFINITIONS ::= BEGIN
 
          IMPORTS
               MODULE-IDENTITY, OBJECT-TYPE, snmpModules, enterprises
                          FROM SNMPv2-SMI
               DisplayString
                          FROM SNMPv2-TC
 
          ibm      OBJECT IDENTIFIER ::= { enterprises 2 }
          ibmDPI   OBJECT IDENTIFIER ::= { ibm 2 }
          dpi20MIB OBJECT IDENTIFIER ::= { ibmDPI 1 }
 
       -- dpiSimpleMIB MODULE-IDENTITY
       --   LAST-UPDATED "9401310000Z"
       --   ORGANIZATION "IBM Research - T.J. Watson Research Center"
       --   CONTACT-INFO "           Bert Wijnen
       --                 Postal:    IBM International Operations
       --                            Watsonweg 2
       --                            1423 ND Uithoorn
       --                            The Netherlands
       --                 Tel:       +31 2975 53316
 
 
 
Wijnen                                                       [Page 118]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       --                 Fax:       +31 2975 62468
       --                 E-mail:    wijnen@vnet.ibm.com
       --                            (IBM internal: wijnen at nlvm1)"
       --   DESCRIPTION
       --          "The MIB module describing DPI Simple Objects for
       --           the dpi_sample.c program"
       --   ::= { snmpModules x }
 
          dpiSimpleMIB OBJECT IDENTIFIER ::= { dpi20MIB 5 }
 
          dpiSimpleInteger         OBJECT-TYPE
               SYNTAX  INTEGER
               ACCESS  read-only
               STATUS  mandatory
               DESCRIPTION
                   "A sample integer32 value"
               ::= { dpiSimpleMIB 1 }
 
          dpiSimpleString          OBJECT-TYPE
               SYNTAX  DisplayString
               ACCESS  read-write
               STATUS  mandatory
               DESCRIPTION
                   "A sample Display String"
               ::= { dpiSimpleMIB 2 }
 
          dpiSimpleCounter32       OBJECT-TYPE
               SYNTAX  Counter     -- Counter32 is SNMPv2
               ACCESS  read-only
               STATUS  mandatory
               DESCRIPTION
                   "A sample 32-bit counter"
               ::= { dpiSimpleMIB 3 }
 
          dpiSimpleCounter64       OBJECT-TYPE
               SYNTAX  Counter     -- Counter64 is SNMPv2,
                                   -- No SMI support for it yet
               ACCESS  read-only
               STATUS  mandatory
               DESCRIPTION
                   "A sample 64-bit counter"
               ::= { dpiSimpleMIB 4 }
       END
 
     To make things more readable, we have defined the following names
     in our dpi_sample.c source file.
 
 
 
 
 
 
 
Wijnen                                                       [Page 119]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       #define DPI_SIMPLE_SUBAGENT   "1.3.6.1.4.1.2.2.1.5"
       #define DPI_SIMPLE_MIB        "1.3.6.1.4.1.2.2.1.5."
       #define DPI_SIMPLE_INTEGER    "1.0"  /* dpiSimpleInteger.0   */
       #define DPI_SIMPLE_STRING     "2.0"  /* dpiSimpleInteger.0   */
       #define DPI_SIMPLE_COUNTER32  "3.0"  /* dpiSimpleCounter32.0 */
       #define DPI_SIMPLE_COUNTER64  "4.0"  /* dpiSimpleCounter64.0 */
 
     In addition, we have defined the following variables as global
     variable in our dpi_sample.c source file.
 
       static long int      value1      = 5;         /* readOnly  */
       #define              value2_p      cur_val_p  /* readWrite */
       static char         *cur_val_p   = (char *)0;
       static char         *new_val_p   = (char *)0;
       static char         *old_val_p   = (char *)0;
       static unsigned long value3      = 1;         /* readOnly  */
       static snmp_dpi_u64  value4      = {1L,1L};   /* readOnly  */
 
 
     5.1.1  CONNECTING TO THE AGENT
 
     Before a sub-agent can receive or send any DPI packets from/to the
     SNMP DPI capable agent, it must "connect" to the agent and then
     identify itself to the agent.
 
     Setting up the connection is one simple call to the the function
     DPIconnect_to_agent_TCP(). It expects two arguments:
 
     o   a hostname (name or IpAdress in dot notation) that specifies
         where the agent is running. Often, the name "loopback" or
         "localhost" can be used if the sub-agent runs on the same
         system as the agent.
     o   a community name which is used to obtain the dpi TCP port from
         the agent. Internally that is done by sending a regular SNMP
         GET request to the agent. In an open environment, we probably
         can use the well know community name "public".
 
     The function returns an negative error code if an error occurs.  If
     the connection setup is successful, then it returns a handle which
     represents the connection, and which we must use on subsequent
     calls to send or await DPI packets.
 
     The second step is to identify the sub-agent to the agent. This is
     done by making a DPI-OPEN packet, sending it to the agent and then
     awaiting the response from the agent. The agent may accept or deny
     the OPEN request.  Making a DPI-OPEN packet is done by calling
     mkDPIopen() which expects seven arguments:
 
     o   A unique sub-agent identification (an Object Identifier).
     o   A description. Might be the NULL string ("")
 
 
 
Wijnen                                                       [Page 120]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     o   Overall sub-agent timeout in seconds. The agent uses this value
         as a timeout value for a response when it sends a request to
         the sub-agent. Note that the agent may have a maximum value for
         this timeout that will be used if you exceed it.
     o   The maximum number of varBinds per DPI packet that the
         sub-agent is willing (or is able) to handle.
     o   The character set we want to use.  In most cases you want to
         use the native character set.
     o   Length of a password (zero means no password)
     o   Ptr to the password (or NULL if no password)
 
     It depends on the agent if sub-agents must specify a password to
     open up a connection.  The function returns a ptr to a static
     buffer holding the DPI packet if success. If it fails, it returns a
     NULL ptr.
 
     Once the DPI-OPEN packet has been created, you must send it to the
     agent. You can use the DPIsend_packet_to_agent() function which
     expects three arguments:
 
     o   The handle of a connection (from DPIconnect_to_agent_TCP)
     o   A ptr to the DPI packet (from mkDPIopen)
     o   The length of the packet.  The snmp_dpi.h include file provides
         a macro DPI_PACKET_LEN that calculates the packet length of a
         DPI packet.
 
     This function returns DPI_RC_OK (value zero) if success, otherwise
     an appropriate DPI_RC_xxxx error code as defined in snmp_dpi.h.
 
     Now we must wait for a response to the DPI-OPEN. To await such a
     response, you call the DPIawait_packet_from_agent() function, which
     expects four arguments:
 
     o   The handle of a connection (from DPIconnect_to_agent_TCP)
     o   A timeout in seconds (max time to wait for response)
     o   A ptr to a ptr, which will receive a ptr to a static buffer
         containing the awaited DPI packet. If the system fails to
         receive a packet, then a NULL ptr will be stored.
     o   A ptr to a long integer (32-bit) which will receive the length
         of the awaited packet. On a failure it will be set to zero.
 
     This function returns DPI_RC_OK (value zero) if success, otherwise
     an appropriate DPI_RC_xxxx error code as defined in snmp_dpi.h.
 
     The last step is to ensure that we indeed got a DPI-RESPONSE back
     from the agent, and if we did then we must ensure that the agent
     indeed accepted us as a valid sub-agent. This will be shown by the
     error_code field in the DPI response packet.
 
 
 
 
 
Wijnen                                                       [Page 121]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     The following code sample demonstrates how to setup a connection
     and then "open" it by identifying yourself to the agent.
 
       #include <snmp_dpi.h>              /* DPI 2.0 API definitions */
       static int handle;                 /* handle has global scope */
 
       static void do_connect_and_open(void)
       {
          unsigned char *packet_p;
          int            rc;
          unsigned long  length;
          snmp_dpi_hdr  *hdr_p;
 
          handle = DPIconnect_to_agent_TCP( /* (TCP) connect to agent*/
                      "loopback",           /* on this host          */
                      "public");            /* snmp community name   */
 
          if (handle < 0) exit(1);          /* If it failed, exit    */
 
          packet_p = mkDPIopen(             /* Make DPI-OPEN packet  */
                       DPI_SIMPLE_SUBAGENT, /* Our identification    */
                      "Simple DPI subAgent",/* description           */
                       5L,                  /* Our overall timeout   */
                       1L,                  /* max varBinds/packet   */
                       DPI_NATIVE_CSET,     /* native character set  */
                       0L,                  /* password length       */
                       (unsigned char *)0); /* ptr to password       */
 
          if (!packet_p) exit(1);           /* If it failed, exit    */
 
          rc  = DPIsend_packet_to_agent(    /* send OPEN packet      */
                   handle,                  /* on this connection    */
                   packet_p,                /* this is the packet    */
                   DPI_PACKET_LEN(packet_p));  /* this is its length */
 
          if (rc != DPI_RC_OK) exit(1);     /* If it failed, exit    */
 
          rc  = DPIawait_packet_from_agent( /* wait for response     */
                   handle,                  /* on this connection    */
                   3,                       /* timeout in seconds    */
                   &packet_p,               /* receives ptr to packet*/
                   &length);                /* receives packet length*/
 
          if (rc != DPI_RC_OK) exit(1);     /* If it failed, exit    */
 
          hdr_p = pDPIpacket(packet_p);     /* parse DPI packet      */
          if (hdr_p == snmp_dpi_hdr_NULL_p) /* If we fail to parse it*/
             exit(1);                       /* then exit             */
 
          if (hdr_p->packet_type != SNMP_DPI_RESPONSE) exit(1);
 
 
 
Wijnen                                                       [Page 122]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
 
          rc = hdr_p->data_u.resp_p->error_code;
          if (rc != SNMP_ERROR_DPI_noError) exit(1);
 
       } /* end of do_connect_and_open() */
 
 
     5.2  REGISTERING A SUB-TREE WITH THE AGENT
 
     After we have setup a connection to the agent and after we have
     identified ourselves, we must register one or more MIB sub-trees
     for which we want to be responsible (handle all SNMP requests).
 
     To do so, the sub-agent must create a DPI-REGISTER packet and send
     it to the agent. The agent will then send a response to indicate
     success or failure of the register request.
 
     To create a DPI-REGISTER packet, the sub-agent uses a call to the
     mkDPIregister() function, which expects these arguments:
 
     o   A timeout value (in seconds) for this sub-tree. If you specify
         zero, then your overall timeout value (specified in DPI-OPEN)
         is used. Here you can specify a different value if you expect
         longer processing time for a specific sub-tree.
     o   A requested priority. Multiple sub-agents may register the same
         sub-tree at different priorities (0 is better than 1 and so
         on).  The agent considers the sub-agent with the best priority
         to be the active sub-agent for the sub-tree. If you specify -1,
         then you ask for the best priority available. If you specify 0,
         then you ask for a better priority than any existing sub-agent
         may already have.
     o   The MIB sub-tree which you want to control. You must specify
         this one with a trailing dot.
     o   Your choice of GETBULK processing. You can ask the agent to map
         a GETBULK into multiple GETNEXT packets or to pass the GETBULK
         to you.
 
     The function returns a ptr to a static buffer holding the DPI
     packet if success. If it fails, it returns a NULL ptr.
 
     Now we must send this DPI-REGISTER packet to the agent. We use the
     DPIsend_packet_to_agent() function to do so, in a similar way as we
     did send the DPI_OPEN packet. Then we wait for a response from the
     agent. Again, we use the DPIawait_packet_from_agent() function in
     the same way as we awaited a response on the DPI-OPEN request. Once
     we have received the response, we must check the return code to
     ensure that registration was successful.
 
     The following code sample demonstrates how to register one MIB
     sub-tree with the agent.
 
 
 
Wijnen                                                       [Page 123]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       #include <snmp_dpi.h>             /* DPI 2.0 API definitions */
       static int handle;                /* handle has global scope */
 
       static void do_register(void)
       {
          unsigned char *packet_p;
          int            rc;
          unsigned long  length;
          snmp_dpi_hdr  *hdr_p;
 
          packet_p = mkDPIregister(          /* Make DPI register    */
                       3,                    /* timeout in seconds   */
                       0,                    /* requested priority   */
                       DPI_SIMPLE_MIB,       /* ptr to the sub-tree  */
                       DPI_BULK_NO);         /* GetBulk into GetNext */
 
          if (!packet_p) exit(1);            /* If it failed, exit   */
 
          rc  = DPIsend_packet_to_agent(     /* send OPEN packet     */
                   handle,                   /* on this connection   */
                   packet_p,                 /* this is the packet   */
                   DPI_PACKET_LEN(packet_p));/* this is its length   */
 
          if (rc != DPI_RC_OK) exit(1);      /* If it failed, exit   */
 
          rc  = DPIawait_packet_from_agent(  /* wait for response    */
                   handle,                   /* on this connection   */
                   3,                        /* timeout in seconds   */
                   &packet_p,                /* gets ptr to packet   */
                   &length);                 /* gets packet length   */
 
          if (rc != DPI_RC_OK) exit(1);      /* If it failed, exit   */
 
          hdr_p = pDPIpacket(packet_p);      /* parse DPI packet     */
          if (hdr_p == snmp_dpi_hdr_NULL_p)  /* Failed to parse it   */
             exit(1);                        /* so exit              */
 
          if (hdr_p->packet_type != SNMP_DPI_RESPONSE) exit(1);
 
          rc = hdr_p->data_u.resp_p->error_code;
          if (rc != SNMP_ERROR_DPI_noError) exit(1);
       } /* end of do_register() */
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 124]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     5.3  PROCESSING REQUESTS FROM THE AGENT
 
     After we have registered our sample MIB sub-tree with the agent, we
     must expect that SNMP requests for that sub-tree will be passed for
     processing by the us. The requests will arrive in the form of DPI
     packets on the connection that the we have established. So we go
     into a while loop to await DPI packets from the agent.
 
     The sub-agent cannot know in advance which kind of packet arrives
     from the agent. So we await a DPI packet (forever), then we parse
     the packet, check the packet type and process the request based on
     the DPI packet type. A call to pDPIpacket (which expects as
     argument a ptr to the encoded/serialized DPI packet) returns us a
     ptr to a DPI parse tree. The ptr points to a snmp_dpi_hdr structure
     which looks as follows:
 
       struct snmp_dpi_hdr {
         unsigned char  proto_major;
         unsigned char  proto_version;
         unsigned char  proto_release;
         unsigned short packet_id;
         unsigned char  packet_type;
         union {
            snmp_dpi_reg_packet      *reg_p;
            snmp_dpi_ureg_packet     *ureg_p;
            snmp_dpi_get_packet      *get_p;
            snmp_dpi_next_packet     *next_p;
            snmp_dpi_next_packet     *bulk_p;
            snmp_dpi_set_packet      *set_p;
            snmp_dpi_resp_packet     *resp_p;
            snmp_dpi_trap_packet     *trap_p;
            snmp_dpi_open_packet     *open_p;
            snmp_dpi_close_packet    *close_p;
            unsigned char            *any_p;
         } data_u;
       };
       typedef struct snmp_dpi_hdr    snmp_dpi_hdr;
       #define snmp_dpi_hdr_NULL_p    ((snmp_dpi_hdr *)0)
 
     Given the DPI parse tree we decide how to process the DPI packet.
     The following code sample demonstrates the high level process of a
     DPI sub-agent.
 
       #include <snmp_dpi.h>              /* DPI 2.0 API definitions */
       static int handle;                 /* handle has global scope */
 
       main(int argc, char *argv[], char *envp[])
       {
         unsigned char *packet_p;
         int            rc = 0;
 
 
 
Wijnen                                                       [Page 125]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         unsigned long  length;
         snmp_dpi_hdr  *hdr_p;
 
         if (argc>1) {                     /* if use passed one parm */
            if (strcmp(argv[1],"-d")==0)   /* being -d, then we      */
                DPIdebug(2);               /* turn on DPI debugging  */
         } /* endif */                     /* which shows us things  */
 
         do_connect_and_open();            /* connect and DPI-OPEN   */
 
         do_register();                    /* register our sub-tree  */
 
         while (rc == 0) {                 /* do forever             */
          rc = DPIawait_packet_from_agent( /* wait for a DPI packet  */
                  handle,                  /* on this connection     */
                  -1,                      /* wait forever           */
                  &packet_p,               /* receives ptr to packet */
                  &length);                /* receives packet length */
 
          if (rc != DPI_RC_OK) exit(1);    /* If it failed, exit     */
 
          hdr_p = pDPIpacket(packet_p);    /* parse DPI packet       */
          if (hdr_p == snmp_dpi_hdr_NULL_p)/* If we fail to parse it */
             exit(1);                      /* then exit              */
 
          switch(hdr_p->packet_type) {     /* handle by DPI type     */
          case SNMP_DPI_GET:
            rc = do_get(hdr_p,
                        hdr_p->data_u.get_p);
            break;
          case SNMP_DPI_GETNEXT:
            rc = do_next(hdr_p,
                         hdr_p->data_u.next_p);
            break;
          case SNMP_DPI_SET:
          case SNMP_DPI_COMMIT:
          case SNMP_DPI_UNDO:
            rc = do_set(hdr_p,
                        hdr_p->data_u.set_p);
            break;
          case SNMP_DPI_CLOSE:
            rc = do_close(hdr_p,
                          hdr_p->data_u.close_p);
            break;
          case SNMP_DPI_UNREGISTER:
            rc = do_unreg(hdr_p,
                          hdr_p->data_u.ureg_p);
            break;
          default:
            printf("Unexpected DPI packet type %d\n",
 
 
 
Wijnen                                                       [Page 126]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                   hdr_p->packet_type);
            rc = -1;
          } /* endswitch */
          if (rc) exit(1);
         } /* endwhile */
 
         return(0);
       } /* end of main() */
 
 
     5.3.1  PROCESSING A GET REQUEST
 
     A get request is pretty easy to process. When the DPI packet is
     parsed, the snmp_dpi_hdr structure will show in the packet_type
     that this is a SNMP_DPI_GET packet. In that case, the packet_body
     contains a ptr to a GET-varBind, which is represented in an
     snmp_dpi_get_packet structure:
 
       struct dpi_get_packet {
         char                   *object_p;   /* ptr to OIDstring     */
         char                   *group_p;    /* ptr to sub-tree      */
         char                   *instance_p; /* ptr to rest of OID   */
         struct dpi_get_packet  *next_p;     /* ptr to next in chain */
       };
       typedef struct dpi_get_packet       snmp_dpi_get_packet;
       #define snmp_dpi_get_packet_NULL_p  ((snmp_dpi_get_packet *)0)
 
     So, assuming we have registered example sub-tree
     1.3.6.1.4.1.2.2.1.5 and a GET request comes in for one variable
     1.3.6.1.4.1.2.2.1.5.1.0 (so that is object 1 instance 0 in our
     sub-tree), then the fields in the snmp_dpi_get_packet would have
     ptrs that point to:
 
         object_p   ->  "1.3.6.1.4.1.2.2.1.5.1.0"
         group_p    ->  "1.3.6.1.4.1.2.2.1.5"
         instance_p ->  "1.0"
         next_p     ->  snmp_dpi_get_packet_NULL_p
 
     If there are multiple varBinds in a GET request, then each one is
     represented in a snmp_dpi_get_packet structure and all the
     snmp_dpi_get_packet structures are chained via the next ptr.  As
     long as the next ptr is not the snmp_dpi_get_packet_NULL_p pointer
     then there are more varBinds in the list.
 
     Now we can analyze the varBind structure for whatever checking we
     want to do. Once we are ready to make a response that contains the
     value of the variable, then we first prepare a SET-varBind which is
     represented in an snmp_dpi_set_packet structure:
 
 
 
 
 
Wijnen                                                       [Page 127]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       struct dpi_set_packet {
         char                   *object_p;   /* ptr to OIDstring     */
         char                   *group_p;    /* ptr to sub-tree      */
         char                   *instance_p; /* ptr to rest of OID   */
         unsigned char           value_type; /* SNMP_TYPE_xxxx       */
         unsigned short          value_len;  /* value length         */
         char                   *value_p;    /* ptr to value itself  */
         struct dpi_set_packet  *next_p;     /* ptr to next in chain */
       };
       typedef struct dpi_set_packet       snmp_dpi_set_packet;
       #define snmp_dpi_set_packet_NULL_p  ((snmp_dpi_set_packet *)0)
 
     We can use the mkDPIset() function to prepare such a structure.
     This function expects the following arguments:
 
     o   a ptr to an existing snmp_dpi_set_packet structure if the new
         varBind must be added to an existing chain of varBinds.  If
         this is the first (or the only) varBind in the chain, then pass
         the snmp_dpi_set_packet_NULL_p ptr to indicate this.
     o   a ptr to the sub-tree that we registered.
     o   a ptr to the rest of the OID, in other words the piece that
         follows the sub-tree.
     o   the value type of the value to be bound to the variable name.
         This is must be one of the SNMP_TYPE_xxxx values as defined in
         the snmp_dpi.h include file.
     o   the length of the value (for integer type values this must be a
         length of 4. So we always work with 32-bit signed or unsigned
         integers (except of course for the Counter64 type, for those we
         must point to a snmp_dpi_u64 structure and pass the length of
         that structure).
     o   a ptr to the value.
 
     Memory for the varBind is dynamically allocated and the data itself
     is copied. So upon return we can dispose of our own ptrs and
     allocated memory as we please. If the call is successful, then a
     ptr is returned:
 
     o   to a new snmp_dpi_set_packet if it is the first/only varBind
     o   to the existing snmp_dpi_set_packet that we passed on the call.
         In this case, the new packed has been chained to the end of the
         varBind list.
 
     If the mkDPIset() call fails, a NULL ptr is returned.
 
     Once we have prepared the SET-varBind data, we can create a DPI
     RESPONSE packet using the mkDPIresponse() function which expects
     these arguments:
 
     o   a ptr to an snmp_dpi_hdr. We should use the hdr of the parsed
         incoming packet. It is used to copy the packet_id from the
 
 
 
Wijnen                                                       [Page 128]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         request into the response, such that the agent can correlate
         the response to a request.
 
     o   a return code (snmp error code). If success, this should be
         SNMP_ERROR_noError (value zero). If failure, it must be one of
         the SNMP_ERROR_xxxx values as defined in the snmp_dpi.h include
         file.
         Note that a request for a non-existing object or instance is
         not considered an error. Instead, we must pass a value type of
         SNMP_TYPE_noSuchObject or SNMP_TYPE_noSuchInstance
         respectively.  These two value types have an implicit value of
         NULL, so we can pass a zero length and a NULL ptr for the value
         in this case.
 
     o   The index of the varBind in error (starts counting at 1).  Pass
         zero if no error occurred, else pass the proper index of the
         first varBind for which an error was detected.
 
     o   a ptr to a (chain of) snmp_dpi_set_packets (varBinds) to be
         returned as response to the GET request.  If an error was
         detected, then an snmp_dpi_set_packet_NULL_p ptr may be passed.
 
     The following code sample returns a response. We assume that there
     are no errors in the request, but proper code should do the
     checking for that. For instance, we return a noSuchInstance if the
     instance is not exactly what we expect and a noSuchObject if the
     object instance_ID is greater than 3 (like 4.0). But there might be
     no instance_ID at all and we should check for that too.
 
       static int do_get(snmp_dpi_hdr *hdr_p,
                         snmp_dpi_get_packet *pack_p)
       {
         unsigned char       *packet_p;
         int                  rc;
         snmp_dpi_set_packet *varBind_p;
 
         varBind_p =                        /* init the varBind chain*/
            snmp_dpi_set_packet_NULL_p;     /* to a NULL pointer     */
 
         if (pack_p->instance_p &&
             (strcmp(pack_p->instance_p,"1.0") == 0))
         {
           varBind_p = mkDPIset(            /* Make DPI set packet   */
                       varBind_p,           /* ptr to varBind chain  */
                       pack_p->group_p,     /* ptr to sub-tree       */
                       pack_p->instance_p,  /* ptr to rest of OID    */
                       SNMP_TYPE_Integer32, /* value type Integer 32 */
                       sizeof(value1),      /* length of value       */
                       &value1);            /* ptr to value          */
         } else if (pack_p->instance_p &&
 
 
 
Wijnen                                                       [Page 129]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
             (strcmp(pack_p->instance_p,"2.0") == 0))
         {
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
                       pack_p->group_p,        /* ptr to sub-tree    */
                       pack_p->instance_p,     /* ptr to rest of OID */
                       SNMP_TYPE_DisplayString,/* value type         */
                       strlen(value2_p),       /* length of value    */
                       value2_p);              /* ptr to value       */
         } else if (pack_p->instance_p &&
             (strcmp(pack_p->instance_p,"3.0") == 0))
         {
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
                       pack_p->group_p,        /* ptr to sub-tree    */
                       pack_p->instance_p,     /* ptr to rest of OID */
                       SNMP_TYPE_Counter32,    /* value type         */
                       sizeof(value3),         /* length of value    */
                       &value3);               /* ptr to value       */
         } else if (pack_p->instance_p &&
             (strcmp(pack_p->instance_p,"3")>0))
         {
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                      varBind_p,               /* ptr to varBindchain*/
                      pack_p->group_p,         /* ptr to sub-tree    */
                      pack_p->instance_p,      /* ptr to rest of OID */
                      SNMP_TYPE_noSuchObject,  /* value type         */
                      0L,                      /* length of value    */
                      (unsigned char *)0);     /* ptr to value       */
         } else {
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                      varBind_p,               /* ptr to varBindchain*/
                      pack_p->group_p,         /* ptr to sub-tree    */
                      pack_p->instance_p,      /* ptr to rest of OID */
                      SNMP_TYPE_noSuchInstance,/* value type         */
                      0L,                      /* length of value    */
                      (unsigned char *)0);     /* ptr to value       */
         } /* endif */
 
         if (!varBind_p) return(-1);        /* If it failed, return  */
 
         packet_p = mkDPIresponse(          /* Make DPIresponse pack */
                      hdr_p,                /* ptr parsed request    */
                      SNMP_ERROR_noError,   /* all is OK, no error   */
                      0L,                   /* index zero, no error  */
                      varBind_p);           /* varBind response data */
 
         if (!packet_p) return(-1);         /* If it failed, return  */
 
         rc  = DPIsend_packet_to_agent(     /* send OPEN packet      */
 
 
 
Wijnen                                                       [Page 130]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                  handle,                   /* on this connection    */
                  packet_p,                 /* this is the packet    */
                  DPI_PACKET_LEN(packet_p));/* and this is its length*/
 
         return(rc);                        /* return retcode        */
       } /* end of do_get() */
 
 
     5.3.2  PROCESSING A GETNEXT REQUEST
 
     A getnext request is more difficult to process. When a DPI packet
     is parsed, the snmp_dpi_hdr structure shows in the packet_type that
     this is a SNMP_DPI_GETNEXT packet, and so the packet_body contains
     a ptr to a GETNEXT-varBind, which is represented in an
     snmp_dpi_next_packet structure:
 
       struct dpi_next_packet {
         char                   *object_p;    /* ptr to OIDstring    */
         char                   *group_p;     /* ptr to sub-tree     */
         char                   *instance_p;  /* ptr to rest of OID  */
         struct dpi_next_packet *next_p;      /* ptr to next in chain*/
       };
       typedef struct dpi_next_packet      snmp_dpi_next_packet;
       #define snmp_dpi_next_packet_NULL_p ((snmp_dpi_next_packet *)0)
 
     So, assuming we have registered example sub-tree dpiSimpleMIB and a
     GETNEXT arrives for one variable dpiSimpleInteger.0 (so that is
     object 1 instance 0 in our sub-tree), then the fields in the
     snmp_dpi_get_packet structure would have ptrs pointing to:
 
       object_p    ->  "1.3.6.1.4.1.2.2.1.5.1.0"
       group_p     ->  "1.3.6.1.4.1.2.2.1.5"
       instance_p  ->  "1.0"
       next_p      ->  snmp_dpi_next_packet_NULL_p
 
     If there are multiple varBinds in a GETNEXT request, then each one
     is represented in a snmp_dpi_get_packet structure and all the
     snmp_dpi_get_packet structures are chained via the next ptr.  As
     long as the next ptr is not the snmp_dpi_next_packet_NULL_p pointer
     then there are more varBinds in the list.
 
     Now we can analyze the varBind structure for whatever checking we
     want to do. Then we must find out which OID is the one that
     lexicographically follows the one in the request. And it is that
     OID with its value that we must return as a response. So we must
     now also set the proper OID in the response.  Once we are ready to
     make a response that contains the new OID and the value of that
     variable we must then prepare a SET-varBind which is represented in
     an snmp_dpi_set_packet:
 
 
 
 
Wijnen                                                       [Page 131]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
       struct dpi_set_packet {
         char                   *object_p;   /* ptr to OIDstring     */
         char                   *group_p;    /* ptr to sub-tree      */
         char                   *instance_p; /* ptr to rest of OID   */
         unsigned char           value_type; /* SNMP_TYPE_xxxx       */
         unsigned short          value_len;  /* value length         */
         char                   *value_p;    /* ptr to value itself  */
         struct dpi_set_packet  *next_p;     /* ptr to next in chain */
       };
       typedef struct dpi_set_packet        snmp_dpi_set_packet;
       #define snmp_dpi_set_packet_NULL_p   ((snmp_dpi_set_packet *)0)
 
     We can use the mkDPIset() function to prepare such a structure.
     This function expects the following arguments:
 
     o   A ptr to an existing snmp_dpi_set_packet structure if the new
         varBind must be added to an existing chain of varBinds.  If
         this is the first or only varBind in the chain, then we pass
         the snmp_dpi_set_packet_NULL_p ptr to indicate this.
     o   a ptr to the sub-tree that we registered.  a ptr to the rest of
         the OID, in other words the piece that follows the sub-tree.
     o   the value type of the value to be bound to the variable name.
         This is must be one of the SNMP_TYPE_xxxx values as defined in
         the snmp_dpi.h include file.
     o   the length of the value (for integer type values this must be a
         length of 4. So we always work with 32-bit signed or unsigned
         integers (except of course for the Counter64 type, for those we
         must point to a snmp_dpi_u64 structure and pass the length of
         that structure).
     o   a ptr to the value.
 
     Memory for the varBind is dynamically allocated and the data itself
     is copied. Upon return we can dispose of our own ptrs and allocated
     memory as we please. If the call is successful, then a ptr is
     returned:
 
     o   to a new snmp_dpi_set_packet if it is the first/only varBind
     o   to the existing snmp_dpi_set_packet that we passed on the call.
         In this case, the new packed has been chained to the end of the
         varBind list.
 
     If the mkDPIset() call fails, a NULL ptr is returned.
 
     Once we have prepared the SET-varBind data, we can create a DPI
     RESPONSE packet using the mkDPIresponse() function, which expects
     these arguments:
 
     o   a ptr to an snmp_dpi_hdr. We should use the hdr of the parsed
         incoming packet. It is used to copy the packet_id from the
 
 
 
 
Wijnen                                                       [Page 132]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         request into the response, such that the agent can correlate
         the response to a request.
     o   a return code (snmp error code). If success, this should be
         SNMP_ERROR_noError (value zero). If failure, it must be one of
         the SNMP_ERROR_xxxx values as defined in the snmp_dpi.h include
         file.
         Note that a request for a non-existing object or instance is
         not considered an error. Instead, we must pass the OID and
         value of the first OID that lexicographically follows the
         non-existing object and/or instance.
         Also, reaching the end of our sub-tree (there is no NEXT OID)
         is not considered an error. In this situation we must return
         the original OID (as received in request) and a value_type of
         SNMP_TYPE_endOfMibView. This value_type has an implicit value
         of NULL, so we can pass a zero length and a NULL ptr for the
         value.
     o   The index of the first varBind in error (start counting at 1).
         Pass zero if no error occurred, else pass the proper index of
         the first varBind for which an error was detected.
     o   a ptr to a (chain of) snmp_dpi_set_packet(s) (varBinds) to be
         returned as response to the GETNEXT request.  If an error was
         detected, then an snmp_dpi_set_packet_NULL_p ptr may be passed.
 
     The following code sample returns a response. We assume that there
     are no errors in the request, but proper code should do the
     checking for that. We do proper checking for lexicographic next
     object, but we do no checking for ULONG_MAX, or making sure that
     the instance ID is indeed valid (digits and dots).  If we get to
     the end of our dpiSimpleMIB then we must return an endOfMibView, as
     defined by the SNMPv2 rules.
 
       static int do_next(snmp_dpi_hdr *hdr_p,
                          snmp_dpi_next_packet *pack_p)
       {
         unsigned char       *packet_p;
         int                  rc;
         unsigned long        subid;        /* subid is unsigned     */
         unsigned long        instance;     /* same with instance    */
         char                *cp;
         snmp_dpi_set_packet *varBind_p;
 
         varBind_p =                        /* init the varBind chain*/
            snmp_dpi_set_packet_NULL_p;     /* to a NULL pointer     */
 
         if (pack_p->instance_p) {          /* we have an instance ID*/
            cp = pack_p->instance_p;        /* pick up ptr           */
            subid = strtoul(cp, &cp, 10);   /* convert subid (object)*/
            if (*cp == '.') {               /* followed by a dot ?   */
               cp++;                        /* point after it if yes */
               instance=strtoul(cp,&cp,10); /* convert real instance */
 
 
 
Wijnen                                                       [Page 133]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                                            /* not that we need it,we*/
               subid++;                     /* only have instance 0, */
                                            /* so NEXT is next object*/
               instance = 0;                /* and always instance 0 */
            } else {                        /* no real instance      */
               instance = 0;                /* passed, so we use 0   */
               if (subid == 0) subid++;     /* if object 0, subid 1  */
            } /* endif */
         } else {                           /* no instance ID passed */
            subid = 1;                      /* so do first object    */
            instance = 0;                   /* 0 is all we have      */
         } /* endif */
 
         /* we have set subid and instance such that we can basically*/
         /* process the request as a GET now. Actually, we don't even*/
         /* need instance, because all out object instances are zero.*/
 
         if (instance != 0) printf("Strange instance: %lu\n",instance);
 
         switch (subid) {
         case 1:
           varBind_p = mkDPIset(            /* Make DPI set packet   */
                       varBind_p,           /* ptr to varBind chain  */
                       pack_p->group_p,     /* ptr to sub-tree       */
                       DPI_SIMPLE_INTEGER,  /* ptr to rest of OID    */
                       SNMP_TYPE_Integer32, /* value type Integer 32 */
                       sizeof(value1),      /* length of value       */
                       &value1);            /* ptr to value          */
           break;
         case 2:
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
                       pack_p->group_p,        /* ptr to sub-tree    */
                       DPI_SIMPLE_STRING,      /* ptr to rest of OID */
                       SNMP_TYPE_DisplayString,/* value type         */
                       strlen(value2_p),       /* length of value    */
                       value2_p);              /* ptr to value       */
           break;
         case 3:
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
                       pack_p->group_p,        /* ptr to sub-tree    */
                       DPI_SIMPLE_COUNTER32,   /* ptr to rest of OID */
                       SNMP_TYPE_Counter32,    /* value type         */
                       sizeof(value3),         /* length of value    */
                       &value3);               /* ptr to value       */
           break;
         default:
           varBind_p = mkDPIset(               /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
 
 
 
Wijnen                                                       [Page 134]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                       pack_p->group_p,        /* ptr to sub-tree    */
                       pack_p->instance_p,     /* ptr to rest of OID */
                       SNMP_TYPE_endOfMibView, /* value type         */
                       0L,                     /* length of value    */
                       (unsigned char *)0);    /* ptr to value       */
           break;
         } /* endswitch */
 
         if (!varBind_p) return(-1);        /* If it failed, return  */
 
         packet_p = mkDPIresponse(          /* Make DPIresponse pack */
                      hdr_p,                /* ptr parsed request    */
                      SNMP_ERROR_noError,   /* all is OK, no error   */
                      0L,                   /* index zero, no error  */
                      varBind_p);           /* varBind response data */
 
         if (!packet_p) return(-1);         /* If it failed, return  */
 
         rc  = DPIsend_packet_to_agent(     /* send OPEN packet      */
                  handle,                   /* on this connection    */
                  packet_p,                 /* this is the packet    */
                  DPI_PACKET_LEN(packet_p));/* and this is its length*/
 
         return(rc);                        /* return retcode        */
       } /* end of do_next() */
 
 
     5.3.3  PROCESSING A SET/COMMIT/UNDO REQUEST
 
     These three requests can come in one of these sequences:
 
     o   SET, COMMIT
     o   SET, UNDO
     o   SET, COMMIT, UNDO
 
     Normal sequence is SET and then COMMIT. When we receive a SET
     request, we must make preparations to accept the new value like
     check that it is for an existing object and instance, check the
     value type and contents to be valid, allocate memory etc), but we
     must not yet effectuate the change.  If all goes well, the next
     request we receive will be a COMMIT request. It is then that we
     must effectuate the change, but we must then also keep enough
     information such that we can UNDO the change later if we get a
     subsequent UNDO request. The latter may happen if the agent
     discovers any errors with other sub-agents while processing
     requests that belong to the same original SNMP SET packet (all the
     varBinds in the same SNMP request PDU must be processed "as if
     atomic").
 
 
 
 
 
Wijnen                                                       [Page 135]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     When the DPI packet is parsed, the snmp_dpi_hdr structure shows in
     the packet_type that this is an SNMP_DPI_SET, SNMP_DPI_COMMIT
     SNMP_DPI_UNDO packet. In that case, the packet_body contains a ptr
     to a SET-varBind, represented in an snmp_dpi_get_packet structure
     (COMMIT and UNDO have same varBind data as SET upon which they
     follow):
 
       struct dpi_set_packet {
         char                   *object_p;   /* ptr to OIDstring     */
         char                   *group_p;    /* ptr to sub-tree      */
         char                   *instance_p; /* ptr to rest of OID   */
         unsigned char           value_type; /* SNMP_TYPE_xxxx       */
         unsigned short          value_len;  /* value length         */
         char                   *value_p;    /* ptr to value itself  */
         struct dpi_set_packet  *next_p;     /* ptr to next in chain */
       };
       typedef struct dpi_set_packet        snmp_dpi_set_packet;
       #define snmp_dpi_set_packet_NULL_p   ((snmp_dpi_set_packet *)0)
 
     So, assuming we have registered example sub-tree dpiSimpleMIB and a
     GET request comes in for one variable dpiSimpleString.0 (so that is
     object 1 instance 0 in our sub-tree), and also assuming that the
     agent knows about our compiled dpiSimpleMIB so that it knows this
     is a DisplayString as opposed to just an arbitrary OCTET_STRING,
     then the ptrs in the snmp_dpi_set_packet structure would have ptrs
     and values like:
 
       object_p    ->  "1.3.6.1.4.1.2.2.1.5.2.0"
       group_p     ->  "1.3.6.1.4.1.2.2.1.5"
       instance_p  ->  "2.0"
       value_type  ->  SNMP_TYPE_DisplayString
       value_len   ->  8
       value_p     ->  ptr to the value to be set.
       next_p      ->  snmp_dpi_get_packet_NULL_p
 
     If there are multiple varBinds in a SET request, then each one is
     represented in a snmp_dpi_set_packet structure and all the
     snmp_dpi_set_packet structures are chained via the next ptr.  As
     long as the next ptr is not the snmp_dpi_set_packet_NULL_p pointer
     then there are more varBinds in the list.
 
     Now we can analyze the varBind structure for whatever checking we
     want to do. Once we are ready to make a response that contains the
     value of the variable, we may prepare a new SET-varBind.  However,
     by definition, the response to a successful SET is exactly the same
     as the SET request. So there is no need to return any varBinds. A
     simple response with SNMP_ERROR_noError and an index of zero will
     do. In case that there is an error, then a simple response with the
     SNMP_ERROR_xxxx error code and an index pointing to the varBind in
     error (counting starts at 1) will do.
 
 
 
Wijnen                                                       [Page 136]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     The following code sample returns a response. We assume that there
     are no errors in the request, but proper code should do the
     checking for that. We also do not check if the varBind in the
     COMMIT and/or UNDO is the same as that in the SET request.  A
     proper agent would make sure that that is the case, but a proper
     sub-agent may want to verify that for itself.  We only do one
     simple check that this is dpiSimpleString.0, and if it is not, we
     return a noCreation.  This may not be correct, the mainline does
     not even return a response.
 
       static int do_set(snmp_dpi_hdr *hdr_p,
                         snmp_dpi_set_packet *pack_p)
       {
         unsigned char       *packet_p;
         int                  rc;
         int                  index       = 0;
         int                  error       = SNMP_ERROR_noError;
         snmp_dpi_set_packet *varBind_p;
 
         varBind_p =                        /* init the varBind chain*/
            snmp_dpi_set_packet_NULL_p;     /* to a NULL pointer     */
 
         if (!pack_p->instance_p ||
             (strcmp(pack_p->instance_p,"2.0") != 0))
         {
 
            if (pack_p->instance_p &&
               (strncmp(pack_p->instance_p,"1.",2) == 0))
            {
               error = SNMP_ERROR_notWritable;
            } else if (pack_p->instance_p &&
               (strncmp(pack_p->instance_p,"2.",2) == 0))
            {
               error = SNMP_ERROR_noCreation;
            } else if (pack_p->instance_p &&
               (strncmp(pack_p->instance_p,"3.",2) == 0))
            {
               error = SNMP_ERROR_notWritable;
            } else {
               error = SNMP_ERROR_noCreation;
            } /* endif */
 
            packet_p = mkDPIresponse(       /* Make DPIresponse pack */
                      hdr_p,                /* ptr parsed request    */
                      error,                /* all is OK, no error   */
                      1,                    /* index 1, 1st varBind  */
                      varBind_p);           /* varBind response data */
 
            if (!packet_p) return(-1);      /* If it failed, return  */
 
 
 
 
Wijnen                                                       [Page 137]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
            rc  = DPIsend_packet_to_agent(  /* send OPEN packet      */
                  handle,                   /* on this connection    */
                  packet_p,                 /* this is the packet    */
                  DPI_PACKET_LEN(packet_p));/* and this is its length*/
 
            return(rc);                     /* return retcode        */
         }
 
         switch (hdr_p->packet_type) {
         case SNMP_DPI_SET:
           if ((pack_p->value_type != SNMP_TYPE_DisplayString) &&
               (pack_p->value_type != SNMP_TYPE_OCTET_STRING))
           {  /* check octet string in case agent has no compiled MIB*/
              error = SNMP_ERROR_wrongType;
              break;                        /* from switch           */
           } /* endif */
           if (new_val_p) free(new_val_p);  /* free allocated memory */
           if (old_val_p) free(old_val_p);  /* if we allocated any   */
 
           new_val_p =                      /* allocate memory for   */
               malloc(pack_p->value_len);   /* new value to set      */
           if (new_val_p) {                 /* If success, then also */
              memcpy(new_val_p,             /* copy new value to our */
                     pack_p->value_p,       /* own + newly allocated */
                     pack_p->value_len);    /* memory area.          */
           } else {                         /* Else failed to malloc,*/
              error = SNMP_ERROR_genErr;    /* so that is a genErr   */
              index = 1;                    /* at first varBind      */
           } /* endif */
           break;
         case SNMP_DPI_COMMIT:
           old_val_p = cur_val_p;           /* save old one for undo */
           cur_val_p = new_val_p;           /* make new value current*/
           new_val_p = (char *)0;           /* keep only 1 ptr around*/
         /* may need to convert from ASCII to native if OCTET_STRING */
           break;
         case SNMP_DPI_UNDO:
           if (new_val_p) free(new_val_p);  /* free allocated memory */
           cur_val_p = old_val_p;           /* reset to old value    */
           break;
         } /* endswitch */
 
         packet_p = mkDPIresponse(          /* Make DPIresponse pack */
                      hdr_p,                /* ptr parsed request    */
                      error,                /* all is OK, no error   */
                      index,                /* index zero, no error  */
                      varBind_p);           /* varBind response data */
 
         if (!packet_p) return(-1);         /* If it failed, return  */
 
 
 
 
Wijnen                                                       [Page 138]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
         rc  = DPIsend_packet_to_agent(     /* send OPEN packet      */
                  handle,                   /* on this connection    */
                  packet_p,                 /* this is the packet    */
                  DPI_PACKET_LEN(packet_p));/* this is its length    */
 
         return(rc);                        /* return retcode        */
       } /* end of do_set() */
 
 
     5.3.4  PROCESSING AN UNREGISTER REQUEST
 
     An agent can send an UNREGISTER packet if some other sub-agent does
     a register for the same sub-tree at a higher priority. An agent can
     also send an UNREGISTER if for instance an SNMP manager tells it to
     "invalidate" the sub-agent connection or the registered sub-tree.
 
     Here is a very simple sample piece of code to handle such a packet.
 
       #include <snmp_dpi.h>          /* DPI 2.0 API definitions */
 
       static int do_unreg(snmp_dpi_hdr *hdr_p,
                           snmp_dpi_ureg_packet *pack_p)
       {
         printf("DPI UNREGISTER received from agent, reason=%d\n",
                 pack_p->reason_code);
         printf("    sub-tree=%s\n",pack_p->group_p);
         DPIdisconnect_from_agent(handle);
         return(-1); /* causes exit in main loop */
       } /* end of do_unreg() */
 
 
     5.3.5  PROCESSING A CLOSE REQUEST
 
     An agent can send a CLOSE packet if it encounters an error or for
     some other reason. It can also do so if an SNMP MANAGER tells it to
     "invalidate" the sub-agent connection.
 
     Here is a very simple sample piece of code to handle such a packet.
 
       #include <snmp_dpi.h>           /* DPI 2.0 API definitions */
 
       static int do_close(snmp_dpi_hdr *hdr_p,
                           snmp_dpi_close_packet *pack_p)
       {
         printf("DPI CLOSE received from agent, reason=%d\n",
                pack_p->reason_code);
 
         DPIdisconnect_from_agent(handle);
         return(-1); /* causes exit in main loop */
       } /* end of do_close() */
 
 
 
Wijnen                                                       [Page 139]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     5.4  GENERATING A TRAP
 
     A trap can be issued at any time. To do so, you must create a trap
     packet and send it to the agent. With the TRAP, you can pass all
     sorts of varBinds if you want. In this sample, we pass two varBinds
     one with integer data and one with an octet string.  You can also
     pass an Enterprise ID, but with DPI 2.0, the agent will use your
     sub-agent ID as the enterprise ID if you do not pass one with the
     trap. In most cases that will probably be fine.
 
     So we must first prepare a varBind list (chain) that contains the
     two variables that we want to pass along with the trap.  To do so
     we must prepare a chain of two snmp_dpi_set_packet structures,
     which looks like:
 
       struct dpi_set_packet {
         char                   *object_p;   /* ptr to OIDstring     */
         char                   *group_p;    /* ptr to sub-tree      */
         char                   *instance_p; /* ptr to rest of OID   */
         unsigned char           value_type; /* SNMP_TYPE_xxxx       */
         unsigned short          value_len;  /* value length         */
         char                   *value_p;    /* ptr to value itself  */
         struct dpi_set_packet  *next_p;     /* ptr to next in chain */
       };
       typedef struct dpi_set_packet        snmp_dpi_set_packet;
       #define snmp_dpi_set_packet_NULL_p   ((snmp_dpi_set_packet *)0)
 
     p.  We can use the mkDPIset() function to prepare such a structure.
     This function expects the following arguments:
 
     o   A ptr to an existing snmp_dpi_set_packet structure if the new
         varBind must be added to an existing chain of varBinds.  If
         this is the first (or the only) varBind in the chain, then pass
         the snmp_dpi_set_packet_NULL_p ptr to indicate this.
     o   a ptr to the sub-tree that we registered.
     o   a ptr to the rest of the OID, in other words the piece that
         follows the sub-tree.
     o   the value type of the value to be bound to the variable name.
         This is must be one of the SNMP_TYPE_xxxx values as defined in
         the snmp_dpi.h include file.
     o   the length of the value (for integer type values this must be a
         length of 4. So we always work with 32-bit signed or unsigned
         integers (except of course for the Counter64 type, for those we
         must point to a snmp_dpi_u64 structure and pass the length of
         that structure).
     o   a ptr to the value.
 
     Memory for the varBind is dynamically allocated and the data itself
     is copied. So upon return we can dispose of our own ptrs and
 
 
 
 
Wijnen                                                       [Page 140]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
     allocated memory as we please. If the call is successful, then a
     ptr is returned:
 
     o   to a new snmp_dpi_set_packet if it is the first/only varBind
     o   to the existing snmp_dpi_set_packet that we passed on the call.
         In this case, the new packed has been chained to the end of the
         varBind list.
 
     If the mkDPIset() call fails, a NULL ptr is returned.
 
     Once we have prepared the SET-varBind data, we can create a DPI
     TRAP packet. To do so we can use the mkDPItrap() function which
     expects these arguments:
 
     o   the generic trap code, use 6 for enterpriseSpecific trap type.
     o   the specific trap type. This is a type that is defined by the
         MIB which we are implementing. So in our sample we just use a
         1.
     o   a ptr to a chain of varBinds or the NULL ptr if no varBinds
         need to be passed with the trap
     o   a ptr to the enterprise OID if we want to use a different
         enterprise ID than the OID we used to identify ourselves as a
         sub-agent at DPI-OPEN time.
 
     The following  code sample creates an enterpriseSpecific trap with
     specific type 1, and passes two varBinds, the first one with our
     object 1, instance 0, Integer32 value; the second one with our
     object 2, instance 0, Octet String. We pass no enterprise ID.
 
       static int do_trap(void)
       {
         unsigned char       *packet_p;
         int                  rc;
         snmp_dpi_set_packet *varBind_p;
 
         varBind_p =                        /* init the varBindchain */
            snmp_dpi_set_packet_NULL_p,     /* to a NULL pointer     */
 
         varBind_p = mkDPIset(              /* Make DPI set packet   */
                       varBind_p,           /* ptr to varBind chain  */
                       DPI_SIMPLE_MIB,      /* ptr to sub-tree       */
                       DPI_SIMPLE_INTEGER,  /* ptr to rest of OID    */
                       SNMP_TYPE_Integer32, /* value type Integer 32 */
                       sizeof(value1),      /* length of value       */
                       &value1);            /* ptr to value          */
 
         if (!varBind_p) return(-1);        /* If it failed, return  */
 
         varBind_p = mkDPIset(                 /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
 
 
 
Wijnen                                                       [Page 141]

SNMP-DPI API                  Version 2.0                  January 1994
 
 
                       DPI_SIMPLE_MIB,         /* ptr to sub-tree    */
                       DPI_SIMPLE_STRING,      /* ptr to rest of OID */
                       SNMP_TYPE_DisplayString,/* value type         */
                       strlen(value2_p),       /* length of value    */
                       value2_p);              /* ptr to value       */
 
         if (!varBind_p) return(-1);        /* If it failed, return  */
 
         varBind_p = mkDPIset(                 /* Make DPI set packet*/
                       varBind_p,              /* ptr to varBindchain*/
                       DPI_SIMPLE_MIB,         /* ptr to sub-tree    */
                       DPI_SIMPLE_COUNTER32,   /* ptr to rest of OID */
                       SNMP_TYPE_Counter32,    /* value type         */
                       sizeof(value3),         /* length of value    */
                       &value3);               /* ptr to value       */
 
         if (!varBind_p) return(-1);        /* If it failed, return  */
 
         packet_p = mkDPItrap(              /* Make DPItrap packet   */
                      6,                    /* enterpriseSpecific    */
                      1,                    /* specific type = 1     */
                      varBind_p,            /* varBind data, and use */
                      (char *)0);           /* default enterpriseID  */
 
         if (!packet_p) return(-1);         /* If it failed, return  */
 
         rc  = DPIsend_packet_to_agent(     /* send OPEN packet      */
                  handle,                   /* on this connection    */
                  packet_p,                 /* this is the packet    */
                  DPI_PACKET_LEN(packet_p));/* and this is its length*/
 
         return(rc);                        /* return retcode        */
       } /* end of do_trap() */
 
     
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Wijnen                                                       [Page 142]

