Processing a GET Request

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 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 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 it is object 1 instance 0 in our sub-tree, 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 a snmp_dpi_get_packet structure and all the snmp_dpi_get_packet structures are chained via the next pointer. As long as the next pointer is not the snmp_dpi_get_packet_NULL_p pointer, 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 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)

We can use the mkDPIset() function to prepare such a structure. This function expects the following parameters:

Memory for the varBind is dynamically allocated and the data itself is copied. So upon return we can dispose of our own pointers and allocated memory as we please. If the call is successful, a pointer is returned as follows:

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

Once we have prepared the SET-varBind data, we can create a DPI RESPONSE packet using the mkDPIresponse() function which expects these parameters:

The following code example 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, for example 4.0. However, 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 &&
      (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 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() */


[Back: Processing Requests from the Agent]
[Next: Processing a GETNEXT Request]