z/OS Communications Server: IP Programmer's Guide and Reference
Previous topic | Next topic | Contents | Contact z/OS | Library | PDF


SNMP DPI: Processing a GETNEXT request

z/OS Communications Server: IP Programmer's Guide and Reference
SC27-3659-02

Put your short description here; used for first paragraph and abstract.

When a DPI packet is parsed, the snmp_dpi_hdr structure shows in the packet_type that this is an SNMP_DPI_GETNEXT packet, and so the packet_body contains a pointer 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)
Assuming you have registered subtree dpiSimpleMIB and a GETNEXT arrives for one variable (dpiSimpleInteger.0) that is object 1 instance 0 in the subtree, the fields in the snmp_dpi_get_packet structure would have pointers 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, each one is represented in an snmp_dpi_next_packet structure and all the snmp_dpi_next_packet structures are chained by the next pointer. If the next pointer is not the snmp_dpi_next_packet_NULL_p pointer, there are more varBinds in the list.

Now you can analyze the varBind structure for whatever checking you want to do. You must find out which OID is the one that lexicographically follows the one in the request. It is that OID with its value that you must return as a response. Therefore, you must now also set the proper OID in the response. When you are ready to make a response that contains the new OID and the value of that variable, you must prepare a SET-varBind which is represented in an snmp_dpi_set_packet:
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)
You can use the mkDPIset() function to prepare such a structure. This function expects the following parameters:
  • A pointer 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, pass the snmp_dpi_set_packet_NULL_p pointer to indicate this.
  • A pointer to the desired subtree.
  • A pointer to the rest of the OID, in other words the piece that follows the subtree.
  • The value type of the value to be bound to the variable name. This must be one of the SNMP_TYPE_xxxx values as defined in the snmp_dpi.h include file.
  • The length of the value. For integer type values, this must be a length of 4. Work with 32-bit signed or unsigned integers except for the Counter64 type. For Counter 64 type, point to an snmp_dpi_u64 structure and pass the length of that structure.
  • A pointer to the value.
Memory for the varBind is dynamically allocated and the data itself is copied. Upon return, you can dispose of your own pointers and allocated memory as you please. If the call is successful, a pointer is returned as follows:
  • A new snmp_dpi_set_packet if it is the first or only varBind.
  • The existing snmp_dpi_set_packet that you passed on the call. In this case, the new packet has been chained to the end of the varBind list.

If the mkDPIset() call fails, a NULL pointer is returned.

When you have prepared the SET-varBind data, create a DPI RESPONSE packet using the mkDPIresponse() function, which expects these parameters:
  • A pointer to an snmp_dpi_hdr. Use the header of the parsed incoming packet. It is used to copy the packet_id from the request into the response, such that the agent can correlate the response to a request.
  • A return code that is an SNMP error code. If successful, this should be SNMP_ERROR_noError (value 0). If failure, it must be one of the SNMP_ERROR_xxxx values as defined in the snmp_dpi.h include file.

    A request for a nonexisting object or instance is not considered an error. Instead, pass the OID and value of the first OID that lexicographically follows the nonexisting object or instance.

    Reaching the end of the subtree is not considered an error. For example, if there is no NEXT OID, this is not an error. In this situation, return the original OID as received in the request and a value_type of SNMP_TYPE_endOfMibView. This value_type has an implicit value of NULL, so you can pass a 0 length and a NULL pointer for the value.

  • The index of the first varBind in error starts counting at 1. Pass 0 if no error occurred, or pass the proper index of the first varBind for which an error was detected.
  • A pointer to a chain of snmp_dpi_set_packets (varBinds) to be returned as response to the GETNEXT request. If an error was detected, an snmp_dpi_set_packet_NULL_p pointer may be passed.

The following code example returns a response. It is assumed that there are no errors in the request, but proper code should do the checking for that. Proper checking is done for lexicographic next object, but no checking is done for ULONG_MAX, or making sure that the instance ID is indeed valid (digits and periods). If the code gets to the end of our dpiSimpleMIB, an endOfMibView is returned as defined by the SNMP Version 2 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 we have done instance level registration, then we should    */
   /* never get a getNext. Anyway, if we do, then we skip this and   */
   /* return an endOfMibView.                                        */
   if (instance_level) {
 
         varBind_p = mkDPIset(               /* Make DPI set packet  */
                     varBind_p,              /* ptr to varBind chain */
                     pack_p->group_p,        /* ptr to subtree       */
                     pack_p->instance_p,     /* ptr to rest of OID   */
                     SNMP_TYPE_endOfMibView, /* value type           */
                     0L,                     /* length of value      */
                     (unsigned char *)0);    /* ptr to value         */
 
   } else {
 
       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   */
                                          /* 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 passed */
             instance = 0;                /* so we can use 0         */
             if (subid == 0) subid++;     /* if object 0, start at 1 */
          } /* endif */
       } else {                           /* no instance ID passed   */
          subid = 1;                      /* so do first object      */
          instance = 0;                   /* instance 0 (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 subtree          */
                     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 varBind chain */
                     pack_p->group_p,        /* ptr to subtree       */
                     DPI_SIMPLE_STRING,      /* ptr to rest of OID   */
                     SNMP_TYPE_DisplayString,/* value type           */
                     value2_len,             /* length of value      */
                     value2_p);              /* ptr to value         */
         break;
       case 3:
         varBind_p = mkDPIset(               /* Make DPI set packet  */
                     varBind_p,              /* ptr to varBind chain */
                     pack_p->group_p,        /* ptr to subtree       */
                     DPI_SIMPLE_COUNTER32,   /* ptr to rest of OID   */
                     SNMP_TYPE_Counter32,    /* value type           */
                     sizeof(value3),         /* length of value      */
                     value3);               /* ptr to value         */
         break;
#ifndef EXCLUDE_SNMP_SMIv2_SUPPORT
       case 4:                               /*                *Apr23*/
         varBind_p = mkDPIset(               /* Make DPI set packet  */
                     varBind_p,              /* ptr to varBind chain */
                     pack_p->group_p,        /* ptr to subtree       */
                     DPI_SIMPLE_COUNTER64,   /* ptr to rest of OID   */
                     SNMP_TYPE_Counter64,    /* value type           */
                     sizeof(value4),         /* length of value      */
                     value4);               /* ptr to value         */
         break;                              /*                *Apr23*/
#endif /* ndef EXCLUDE_SNMP_SMIv2_SUPPORT */
       default:
         varBind_p = mkDPIset(               /* Make DPI set packet  */
                     varBind_p,              /* ptr to varBind chain */
                     pack_p->group_p,        /* ptr to subtree       */
                     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 */
 
   } /* endif */
 
       if (!varBind_p) return(-1);        /* If it failed, return    */
 
       packet_p = mkDPIresponse(          /* Make DPIresponse packet */
                    hdr_p,                /* ptr parsed request      */
                    SNMP_ERROR_noError,   /* all is OK, no error     */
                    0L,                   /* index is zero, no error */
                    varBind_p);           /* varBind response data   */
 
       if (!packet_p) return(-1);         /* If it failed, return    */
 
       rc  = DPIsend_packet_to_agent(     /* send RESPONSE 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() */

Go to the previous page Go to the next page




Copyright IBM Corporation 1990, 2014