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


SNMP DPI: Processing a SET/COMMIT/UNDO request

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

These three requests can come in one of these sequences:
  • SET, COMMIT
  • SET, UNDO
  • SET, COMMIT, UNDO

The normal sequence is SET and then COMMIT. When a SET request is received, preparations must be made to accept the new value. For example, check that request is for an existing object and instance, check the value type and contents to be valid, and allocate memory, but do not yet make the change.

If there are no SET errors, the next received request will be a COMMIT request. It is then that the change must be made, but keep enough information such that you can UNDO the change later if you get a subsequent UNDO request. The latter may happen if the agent discovers any errors with other subagents 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.

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, or SNMP_DPI_UNDO packet. In that case, the packet_body contains a pointer to a SET-varBind, represented in an snmp_dpi_set_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)
Assuming we have a registered subtree dpiSimpleMIB and a SET request comes in for one variable (dpiSimpleString.0) that is object 1 instance 0 in the subtree, 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), the pointers in the snmp_dpi_set_packet structure would have pointers and values, such as:
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     ->  pointer to the value to be set
next_p      ->  snmp_dpi_get_packet_NULL_p

If there are multiple varBinds in a SET request, each one is represented in an snmp_dpi_set_packet structure and all the snmp_dpi_set_packet structures are chained by the next pointer. If the next pointer is not the snmp_dpi_set_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 can 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 response with SNMP_ERROR_noError and an index of zero will do. If there is an error, a response with the SNMP_ERROR_xxxx error code and an index pointing to the varBind in error (counting starts at 1) will do.

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. The code also does not check if the varBind in the COMMIT 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 subagent may want to verify that for itself. Only one check is done that this is dpiSimpleString.0, and if it is not, a noCreation is returned.

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;                                  
       char                *i_p;                                        
                                                                        
       varBind_p =                        /* init the varBind chain  */ 
          snmp_dpi_set_packet_NULL_p;     /* to a NULL pointer       */ 
                                                                        
       if (instance_level) {                                            
          i_p = pack_p->group_p + strlen(DPI_SIMPLE_MIB);               
       } else {                                                         
          i_p = pack_p->instance_p;                                     
       }                                                                
                                                                        
       if (!i_p ││ (strcmp(i_p,"2.0") != 0))                            
       {                                                                
                                                                        
          if (i_p &&                                                    
             (strncmp(i_p,"1.",2) == 0))                                
          {                                                             
             error = SNMP_ERROR_notWritable;                            
          } else if (i_p &&                                             
             (strncmp(i_p,"2.",2) == 0))                                
          {                                                             
             error = SNMP_ERROR_noCreation;                             
          } else if (i_p &&                                             
             (strncmp(i_p,"3.",2) == 0))                                
          {                                                             
             error = SNMP_ERROR_notWritable;                            
          } else {                                                      
             error = SNMP_ERROR_noCreation;                             
          } /* endif */                                                 
                                                                        
          packet_p = mkDPIresponse(       /* Make DPIresponse packet */ 
                    hdr_p,                /* ptr parsed request      */ 
                    error,                /* all is OK, no error     */ 
                    1,                    /* index is 1, 1st varBind */ 
                    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          */ 
       }                                                                
                                                                        
       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 these memory areas */ 
         if (old_val_p) free(old_val_p);  /* if we allocated any     */ 
         new_val_p   = (char *)0;                                       
         old_val_p   = (char *)0;                                       
         new_val_len = 0;                                               
         old_val_len = 0;                                               
                                                                        
         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 and newly allocated */ 
                   pack_p->value_len);    /* memory area.            */ 
            new_val_len = pack_p->value_len;                            
         } 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 value for undo */ 
         cur_val_p = new_val_p;           /* make new value current  */ 
         new_val_p = (char *)0;           /* keep only 1 ptr around  */ 
         old_val_len = cur_val_len;       /* and keep lengths correct*/ 
         cur_val_len = new_val_len;                                     
         new_val_len = 0;                                               
         /* may need to convert from ASCII to native if OCTET_STRING */ 
         break;                                                         
       case SNMP_DPI_UNDO:                                              
         if (new_val_p) {                 /* free allocated memory   */ 
            free(new_val_p);                                            
            new_val_p   = (char *)0;                                    
            new_val_len = 0;                                            
         } /* endif */                                                  
         if (old_val_p) {                                               
            if (cur_val_p) free(cur_val_p);                             
            cur_val_p   = old_val_p;      /* reset to old value      */ 
            cur_val_len = old_val_len;                                  
            old_val_p   = (char *)0;                                    
            old_val_len = 0;                                            
         } /* endif */                                                  
         break;                                                         
       } /* endswitch */                                                
                                                                        
       packet_p = mkDPIresponse(          /* Make DPIresponse packet */ 
                    hdr_p,                /* ptr parsed request      */ 
                    error,                /* all is OK, no error     */ 
                    index,                /* 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_set() */                                                 

Go to the previous page Go to the next page




Copyright IBM Corporation 1990, 2014