Using SNMP Manager APIs--Example

The examples in this topic provides routines that may aid in the use of SNMP manager APIs. These examples are for the SNMP manager APIs snmpGet, snmpSet, snmpGetnext, Start of change snmpDiscover_v3, snmpFreeAuthCB_v3, snmpGet_v3, snmpGetbulk_v3, snmpGetnext_v3, and snmpSet_v3 End of changeAPIs.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.


AddVarbind Routine

This routine is used to create an initial protocol data unit (PDU), and subsequent calls will add varbinds to that PDU.

The value of this routine is that you will be able to create PDUs and add varbinds to those PDUs. The burden of storage allocation for each varbind and its values is removed from you, as is pointer maintenance on the varbinds. Remember that you need to deallocate any dynamic storage when you are done with it. The FreePdu routine (see page FreePdu Routine) is an easy way to do this. The AddVarbind sample code follows:

#include <qtomeapi.h>

int AddVarbind(snmppdu **pdu, char * oid, value v, unsigned
char pdu_type, unsigned char asn_type)
{

   varBind * t;                           /* Varbind pointer.       */
   int str_len,i;

   switch ( pdu_type ) {                  /* Check to make sure that*/
      case GET_PDU_TYPE:                  /* the PDU type is a known*/
      case SET_PDU_TYPE:                  /* value.  If the value is*/
      case GETBULK_PDU_TYPE:              /* not valid you may want */
      case GETNEXT_PDU_TYPE: break;       /* to set a return code   */    
      defaults: return(-2005);            /* value of your liking   */
                                          /* for example, -2005).   */
   }                                      


   if (pdu[0] == NULL)
       {                  /* Check if PDU is null (meaning new PDU).*/
          pdu[0] = ( snmppdu *) malloc(sizeof(snmppdu));
                          /* Allocate storage for the PDU.          */
          memset( (snmppdu *) pdu[0],0,sizeof(pdu[0]));
                          /* Initialize the PDU to zeros.           */
          pdu[0]->pdu_type = pdu_type;
                          /* Initialize the PDU type.               */
          pdu[0]->varbind = ( varBind * ) malloc(sizeof(varBind));
                          /* Allocate storage for the varbind.      */
          str_len = strlen(oid);
                          /* Set the length of the OID.             */

         if (str_len > API_MAX_OID_SIZE ) return(-2000);
                          /* If OID length is not valid return.     */
         pdu[0]->varbind->oid =

           (char *) malloc(API_MAX_OID_SIZE+1);
         strcpy(pdu[0]->varbind->oid,oid);  /* Copy the OID.   */
         pdu[0]->varbind->next = NULL;  /* Nullify next pointer*/
                                 /* This signifies the last varbind. */
         t = pdu[0]->varbind; /* Set temporary pointer to varbind.*/
         t->val.str_val =
           (char *) malloc(API_MAX_VALUE_SIZE+1); /*Allocate storage */
                                         /* for the value of the OID.*/
/*********************************************************************/
/* Note:  This sample code shows a malloc of the maximum value size  */
/* plus 1 for null termination.  It would be in your best interest   */
/* to allocate only the amount of the actual value, plus 1.  This    */
/* reduces the amount of space allocated on each PDU.                */
/*********************************************************************/
   }
   else
   {
      if ( pdu[0]->pdu_type != pdu_type ) return(-2001);
                           /* If this is not the initial call to      */
                           /* add a varbind, then check to make       */
                           /* sure the PDU type of this call          */
                           /* matches the original.                   */
      t = pdu[0]->varbind;
                           /* Store temporary pointer to this varbind.*/
      i = 0;               /* Initialize loop variable.               */

      while ( t->next != NULL ) /* Loop until you locate last varbind.*/
      {
         t = t->next;

         i++;

      }

      if ( i > 100 /* MAX_NUM... */ ) return(-2002);
                           /* Return if you exceed maximum varbinds.  */
      str_len = strlen(oid);   /* Set length of OID.                  */

      if (str_len > API_MAX_OID_SIZE ) return(-2000);
                             /* If OID length exceed maximum, return. */
      t->next = ( varBind * ) malloc(sizeof(varBind));
                             /* Allocate storage for this varbind.    */
      t = t->next;        /* Set new temporary varbind pointer.    */
      t->oid = (char *) malloc(API_MAX_OID_SIZE+1);
                               /* Allocate storage for the OID.       */
      strcpy(t->oid,oid);
                               /* Copy OID to storage.                */
      t->oid[str_len] = '\0';
                               /* Null terminate the OID.             */
      t->val.str_val = (char *) malloc(API_MAX_VALUE_SIZE+1);
                               /* Allocate storage to hold value.     */
      t->val_len = API_MAX_VALUE_SIZE+1;
/**********************************************************************/
/* Note:  This sample code shows a malloc of the maximum value size   */
/* plus 1 for null termination.  It would be in your best interest    */
/* to allocate only the amount of the actual value, plus 1.  This     */
/* reduces the amount of space allocated on each PDU.                 */
/**********************************************************************/
      t->next = NULL;
                               /* Nullify next varbind pointer        */
   }                           /* signifying the last varbind.        */

   if ( pdu_type == SET_PDU_TYPE )           /* For sets only         */
    {
      t->asn_type = asn_type;                /* Save ASN type         */

      switch (asn_type) {
         case API_ASN_OCTET_STRING:          /* All string types      */
         case API_ASN_OBJECT_IDENTIFIER:
         case API_ASN_IpAddress:
         case API_ASN_Opaque:
            str_len = strlen(v.str_val);        /* Store length       */
            strcpy(t->val.str_val,v.str_val);   /* Copy string        */
            t->val.str_val[str_len] = '\0';
                                                /* Null terminate     */
            t->val_len = str_len;               /* Save length        */
            break;
         case API_ASN_INTEGER:
         case API_ASN_Counter:
         case API_ASN_Gauge:
         case API_ASN_TimeTicks:
            *t->val.int_val = *v.int_val;       /* Save integer value */
            t->val_len = sizeof(int);           /* Save length of     */
            break;                              /* an integer.        */
         default: return(-2003);
      }
   }
   return(API_RC_OK);
}


FreePdu Routine

This routine is used to free all the dynamically allocated storage from AddVarbind.

The value of this routine is that you can free all the dynamically allocated (user domain) storage with one call. The FreePdu sample code follows:

#include <qtomeapi.h>

void FreePdu(snmppdu * pdu)   /* Pass in pointer to PDU.              */
{
   varBind * vb, *t;          /* Define pointers to varbinds.         */

   vb = pdu->varbind;      /* Set first varbind pointer.           */
   while (vb != NULL){        /* Loop as long as varbinds exist.      */
      t = vb;                 /* Save current varbind pointer.        */
      vb = vb->next;       /* Pointer to next varbind.             */
      free(t->oid);           /* Free storage allocated for OID.      */
      free(t->val.str_val);   /* Free storage allocated for value.    */
      free(t);       /* Free storage allocated for temporary varbind. */
   }
   free(pdu);                 /* Free storage allocated for PDU.      */
}


Start of changeMakeResponsePDUSpace Routine

This routine is used to create a response PDU and varbind spaces for the results of a call to the snmpGetbulk_v3 API.

#include <qtomeapi.h>

void MakeResponsePDUSpace(snmppdu ** pdu, int numVarbinds) {

    pdu[0] = (snmppdu *) malloc(sizeof(snmppdu));             
    /* Allocate storage for the PDU.          */              
    memset((snmppdu *) pdu[0], 0, sizeof(pdu[0]));

    /* Allocate storage for the intial varbind structure.*/            
    varBind *vb = malloc(sizeof(varBind));                    
    pdu[0]->varbind = vb;                                     
    memset(vb, 0, sizeof(varBind));

    /* Create additional varbind structures based on the */
    /* number requested by the caller of this procedure. */                          
    for(int i = 0; i < numVarbinds; i++) {                    
                                                              
        /* Allocate storage for an OID.                  */
        vb->oid = (char *) malloc(API_MAX_OID_SIZE + 1);      
        memset(vb>oid, 0, API_MAX_OID_SIZE+1);

        /* Allocate storage for a value.                 */              
        vb->val.str_val = malloc(API_MAX_VALUE_SIZE + 1);     
        memset(vb->val.str_val, 0, (API_MAX_VALUE_SIZE + 1)); 
        vb->val_len = API_MAX_VALUE_SIZE;

        /* Check whether additional varbind structures  */
        /* need to be allocated.                        */                     
        if (i < numVarbinds - 1) {

            /* Allocate storage for another varbind.    */                                
            vb->next = malloc(sizeof(varBind));               
            memset(vb->next, 0, sizeof(varBind));

            /* Add it to the chain of varbinds.         */             
            vb = vb->next;
                                  
        } else;
    }
}

End of change

snmpGet, snmpGet_v3, Start of changesnmpGetbulk_v3End of change Call Example

When you use the following example to call the snmpGet, snmpSet, snmpGetnext, Start of changesnmpGet_v3, snmpGetbulk_v3, snmpGetnext_v3, or snmpSet_v3End of change API, it is important to note the following:

The snmpGet, snmpGet_v3, and Start of change snmpGetbulk_v3 End of changesample code follows:

                                                       
#include <qtomeapi.h>

void main() {

typedef union
 {
   int  * int_val;
   char * str_val;
 } value;                                   /* Value typedef.         */

   snmppdu *pdu;                            /* PDU pointer.           */
   value   v;                               /* Value container.       */
   int     rc;                              /* Return code.           */
   char    community_name[120];           /* Community container.   */

   pdu = NULL;                              /* Nullify PDU pointer.   */
   rc = AddVarbind(&pdu,                    /* Add varbind with       */
                      "1.3.6.1.2.1.1.1.0",  /* OID, value, type of    */
                      v,                    /* PDU this is for, ASN   */
                      GET_PDU_TYPE,         /* type.  PDU pointer     */
                      0);                   /* is set to non-null.    */
   if ( rc < 0 ) {                          /* Check the return code.  */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   }

   rc = AddVarbind(&pdu,                    /* Add second varbind.    */
                      "1.3.6.1.2.1.1.1.1",  /* PDU pointer is now     */
                      v,                    /* non-null after 1st     */
                      GET_PDU_TYPE,         /* invocation of Add-     */
                      0);                   /* Varbind.               */
   if ( rc < 0 ) {                          /* Check the return code. */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   }
      strcpy(community_name,"public");      /* Set community name.    */

   rc = snmpGet(pdu,                        /* Invoke operation.      */
                "system_name_of_snmp_agent_system",  /* Hostname.     */
                10,                         /* Time-out value.        */
                community_name,         /* Pointer to community name. */
                6);                         /* Correct length of      */
                                            /* community name.        */

   /* Perform operations on the data in the response PDU.             */


   /* Free the PDU created for the snmpGet API call.                  */
   FreePdu(&pdu);
   /*******************************************************************/
   /* Perform a Get operation using SNMP version 3                    */
   /*******************************************************************/
   /* Run the following command on both the SNMP manager and agent systems.
      This will create an SNMP user that uses SNMPv3 authentication but
      does not do data encryption.
      The USRNAME and AUTPWD parameters are case sensitive and must be
      the same on both the manager and agent systems.  The KEYTYPE
      parameter must specify *NONLOCALIZED on the manager system:

      ADDUSRSNMP USRNAME('TESTV3USER')
                 AUTPCL(*HMACSHA) AUTPWD('TESTPASSWORD')
                 PVYPCL(*NONE)
                 KEYTYPE(*NONLOCALIZED)

     Ensure that the SNMP attributes on both the manager and agent
     systems allow SNMPv3 communications and have valid SNMP engine
     identifiers by running the following command:

     CHGSNMPA ALWSNMPV3(*YES) SNMPENGID(*SYSGEN)

     If SNMP is running, it will have to be ended and restarted after
     running the CHGSNMPA command in order to use SNMPv3.

   */

   snmp_auth_cb cb = NULL;
   snmppdu*        = v3pdu;
   int timeout     = 10;
   pdu = NULL;                              /* Nullify PDU pointer.   */
   rc = AddVarbind(&v3pdu,                  /* Add varbind with       */
                      "1.3.6.1.2.1.1.1.0",  /* OID, value, type of    */
                      v,                    /* PDU this is for, ASN   */
                      GET_PDU_TYPE,         /* type.  PDU pointer     */
                      0);                   /* is set to non-null.    */
   if ( rc < 0 ) {                          /* Check the return code. */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   }

   rc = AddVarbind(&v3pdu,                  /* Add second varbind.    */
                      "1.3.6.1.2.1.1.1.1",  /* PDU pointer is now     */
                      v,                    /* non-null after 1st     */
                      GET_PDU_TYPE,         /* invocation of Add-     */
                      0);                   /* Varbind.               */
   if ( rc < 0 ) {                          /* Check the return code. */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   }
   /* A call to the snmpDiscover_v3() API should be made with each SNMP
      agent that your application will communicate with.  Each SNMP
      agent must have its own control block.                          */
   rc = snmpDiscover_v3("system_name_of_snmp_agent_system",
                        timeout,
                        &cb);
   /* Check whether the SNMPv3 discovery operation was successful     */
   if (rc == 0) {
      /* Perform an SNMPv3 get operation.                             */
      rc = snmpGet_v3(v3pdu,
                      "system_name_of_snmp_agent_system",
                      timeout,
                      "TESTV3USER",
                      &cb);
   } else {

      printf("Error: %d\n",rc);              /* Print the return code.*/
      exit(1);

   }

   /* Free the PDU created for the snmpGet_v3 API call.           */
   FreePdu(&v3pdu);

Start of change
   /* Perform other snmpGet_v3(), snmpGetnext_v3(), snmpSet_v3()
      operations at this point, or in this case we will  perform 
      an snmpGetbulk_v3().                                            */
   snmppdu*  v3pdu_bulk;
   snmppdu_bulk*  pdu_bulk;
   snmppdu*       response_pdu;
   response_pdu = NULL;

   v3pdu_bulk = NULL;


   rc = AddVarbind(&v3pdu_bulk,             /* Add varbind with       */
                      "1.3.6.1.2.1.1.1",    /* OID, value, type of    */
                      v,                    /* PDU this is for, ASN   */
                      GETBULK_PDU_TYPE,     /* type.  PDU pointer     */
                      0);                   /* is set to non-null.    */
   if ( rc < 0 ) {                          /* Check the return code. */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   }

   rc = AddVarbind(&v3pdu_bulk,             /* Add second varbind.    */
                      "1.3.6.1.2.1.6.19",   /* PDU pointer is now     */
                      v,                    /* non-null after 1st     */
                      GETBULK_PDU_TYPE,     /* invocation of Add-     */
                      0);                   /* Varbind.               */
   if ( rc < 0 ) {                          /* Check the return code. */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   } 

   /* Set get bulk specific fields in the PDU.                        */
   pdu_bulk = (snmppdu_bulk *) (v3pdu_bulk));
   pdu_bulk->non_repeaters = 1;
   pdu_bulk->maximum_repetitions = 2;

   /* Create space for the response PDU and varbinds.                 */
   /* The number of response PDU varbinds is calculated using the     */
   /* formula T = ((V - N) * M) + N where T is the total number of    */
   /* varbinds to be returned, V is the number of varbinds provided   */
   /* by the pdu_ptr parameter, N is the number of non-repeater       */
   /* varbinds provided by the pdu_ptr parameter, and M is the        */
   /* maximum repetitions value specified by the pdu_ptr parameter.   */
   /* In this example T = ((2 - 1) * 2) + 1 which results in T = 3.   */
   MakeResponsePDUSpace(&response_pdu, 3);  
  
   /* Perform an SNMPv3 get bulk operation.                           */
   rc = snmpGetbulk_v3(v3pdu_bulk,
                      "system_name_of_snmp_agent_system",
                      timeout,
                      "TESTV3USER",
                      &cb,
                      &response_pdu);
   if ( rc < 0 ) {                          /* Check the return code. */
      printf("Error: %d\n",rc);             /* Print the return code. */
      exit(1);
   }

   /* Perform operations on the data in the response PDU.              */

   /* Free the PDUs created for the snmpGetbulk_v3 API call.           */
   FreePdu(&v3pdu_bulk);
   FreePdu(&response_pdu); 
End of change

   /* Free the memory allocated for the control block.  Once this has been
      performed, a call to the snmpDiscover_v3() API must be made again if
      SNMPv3 communication is to be reestablished with the SNMP agent.*/

   rc = snmpFreeAuthCB_v3(&cb);

}



[ Back to top | UNIX-Type APIs | APIs by category ]