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


SNMP DPI: Processing a GET request

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

When the DPI packet is parsed, the snmp_dpi_hdr structure will show in the packet_type that this is an SNMP_DPI_GET packet. In that case, the packet_body contains a pointer 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)
Assuming you have registered subtree 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) that is object 1 instance 0 in the subtree, the fields in the snmp_dpi_get_packet 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_get_packet_NULL_p

If there are multiple varBinds in a GET request, each one is represented in an snmp_dpi_get_packet structure and all the snmp_dpi_get_packet structures are chained using the next pointer. If the next pointer is not the snmp_dpi_get_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. When you are ready to make a response that contains the value of the variable, you prepare a SET-varBind, which is represented in an snmp_dpi_set_packet structure:
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 the only varBind in the chain, pass the snmp_dpi_set_packet_NULL_p pointer to indicate this.
  • A pointer to the subtree that you registered.
  • 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 the Counter64 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. So upon return you can dispose of our own pointers and allocated memory as you please. If the call is successful, a pointer is returned as follows:
  • To a new snmp_dpi_set_packet if it is the first or only varBind.
  • To 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, you can create a DPI RESPONSE packet using the mkDPIresponse() function that expects these parameters:
  • A pointer to an snmp_dpi_hdr. You should 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 which 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, you 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 you can pass a 0 length and a NULL pointer for the value in this case.

  • The index of the 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 GET request. If an error was detected, an snmp_dpi_set_packet_NULL_p pointer may be passed.

The following code example returns a response. You assume that there are no errors in the request, but proper code should do the checking for that. For instance, you return a noSuchInstance if the instance is not exactly what you expect and a noSuchObject if the object instance_ID is greater than 3. However, there might be no instance_ID at all and you 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;
       char                *i_p;
 
       varBind_p =                        /* init the varBind chain  */
          snmp_dpi_set_packet_NULL_p;     /* to a NULL pointer       */
 
       if (instance_level) {
          if (pack_p->instance_p) {
             printf("unexpected INSTANCE ptr \n");
             return(-1);
          }
          i_p = pack_p->group_p + strlen(DPI_SIMPLE_MIB);
       } else {
          i_p = pack_p->instance_p;
       }
 
       if (i_p && (strcmp(i_p,"1.0") == 0)) {
         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_Integer32, /* value type Integer 32   */
                     sizeof(value1),      /* length of value         */
                     value1);            /* ptr to value            */
       } else if (i_p && (strcmp(i_p,"2.0") == 0)) {
         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_DisplayString,/* value type           */
                     value2_len,             /* length of value      */
                     value2_p);              /* ptr to value         */
       } else if (i_p && (strcmp(i_p,"3.0") == 0)) {
         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_Counter32,    /* value type           */
                     sizeof(value3),         /* length of value      */
                     value3);               /* ptr to value         */
 
#ifndef EXCLUDE_SNMP_SMIv2_SUPPORT
       } else if (i_p && (strcmp(i_p,"4.0") == 0)) {
         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_Counter64,    /* value type           */
                     sizeof(value4),         /* length of value      */
                     value4);               /* ptr to value   *Apr23*/
       } else if (i_p && (strcmp(i_p,"4") > 0)) {
#else
       } else if (i_p && (strcmp(i_p,"3") > 0)) {
#endif /* ndef EXCLUDE_SNMP_SMIv2_SUPPORT */
         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_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 varBind chain */
                    pack_p->group_p,         /* ptr to subtree       */
                    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 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_get() */

Go to the previous page Go to the next page




Copyright IBM Corporation 1990, 2014