home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / lnsnmp.zip / LNVDATA.CPP next >
C/C++ Source or Header  |  1994-02-26  |  14KB  |  438 lines

  1. /*************************************************************************/
  2. /* Program Name: LNVDATA.CPP  Title: Support Module for SNMP LAN NetView */
  3. /* OS/2 Developer Magazine, Issue: March-April '94                       */
  4. /* Article Title: Network Management: Using SNMP for LAN NetView         */
  5. /* Author: Stacey Taylor   CompuServe ID: 73670,3235                     */
  6. /*                         Phone: (818) 878-7300 Fax: (818) 878-7313     */
  7. /* Description:                                                          */
  8. /*  This simple program demonstrates the programming techniques required */
  9. /* when retrieving data from an SNMP agent via the LAN NetView platform. */
  10. /* Output from this program (i.e. tracing/debugging data), is written to */
  11. /* a file called, SNMPDATA.                                              */
  12. /*                                                                       */
  13. /* Program Requirements:                                                 */
  14. /*   C/Set++                                                             */
  15. /*   LAN NetView, Manage Module with Development Toolkit                 */
  16. /*************************************************************************/
  17.  
  18.  
  19. //---------------------------------------------------------
  20. // System Include Files
  21. //---------------------------------------------------------
  22. #include <stdio.h> 
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <xom.h>        // from LAN NetView include directory
  27. #include <xmp.h>        // from LAN NetView include directory
  28. #include <xmp_snmp.h>   // from LAN NetView include directory
  29.  
  30.  
  31. // define a array to describe all the syntaxes.
  32. // This could be used for CMIP operations also.
  33.  
  34. typedef struct
  35. {
  36.    int   SyntaxID;
  37.    char *SyntaxDesc;
  38. } SNMP_SYNTAX;
  39.  
  40. static SNMP_SYNTAX SNMPSyntax[] = 
  41. {
  42.    { OM_S_BIT_STRING,               "OM_S_BIT_STRING" },
  43.    { OM_S_BOOLEAN,                  "OM_S_BOOLEAN" },
  44.    { OM_S_ENCODING_STRING,          "OM_S_ENCODING_STRING" },
  45.    { OM_S_ENUMERATION,              "OM_S_ENUMERATION" },
  46.    { OM_S_GENERAL_STRING,           "OM_S_GENERAL_STRING" },
  47.    { OM_S_GENERALISED_TIME_STRING,  "OM_S_GENERALIZED_TIME_STRING" },
  48.    { OM_S_GRAPHIC_STRING,           "OM_S_GRAPHIC_STRING" },
  49.    { OM_S_IA5_STRING,               "OM_S_IA5_STRING" },
  50.    { OM_S_INTEGER,                  "OM_S_INTEGER" },
  51.    { OM_S_NO_MORE_SYNTAXES,         "OM_S_NO_MORE_SYNTAXES" },
  52.    { OM_S_NULL,                     "OM_S_NULL" },
  53.    { OM_S_NUMERIC_STRING,           "OM_S_NUMERIC_STRING" },
  54.    { OM_S_OBJECT,                   "OM_S_OBJECT" },
  55.    { OM_S_OBJECT_DESCRIPTOR_STRING, "OM_S_OBJECT_DESCRIPTOR_STRING" },
  56.    { OM_S_OBJECT_IDENTIFIER_STRING, "OM_S_OBJECT_IDENTIFIER_STRING" },
  57.    { OM_S_OCTET_STRING,             "OM_S_OCTET_STRING" },
  58.    { OM_S_PRINTABLE_STRING,         "OM_S_PRINTABLE_STRING" },
  59.    { OM_S_TELETEX_STRING,           "OM_S_TELETEX_STRING" },
  60.    { OM_S_UTC_TIME_STRING,          "OM_S_UTC_TIME_STRING" },
  61.    { OM_S_VIDEOTEX_STRING,          "OM_S_VIDEOTEX_STRING" },
  62.    { OM_S_VISIBLE_STRING,           "OM_S_VISIBLE_STRING" }
  63. };
  64.  
  65.  
  66. // File handle to SNMPDATA.OUT file
  67.  
  68. static FILE *hOutput;  
  69.  
  70.  
  71.  
  72. // Prototype internal functions
  73.  
  74. static void RecurseSNMPStruct ( OM_workspace, OM_public_object, int );
  75. static void ExtractValue ( OM_workspace, OM_public_object, char * );
  76.  
  77.  
  78. //------------------------------------------------------------------------
  79. // Function: DecomposeSNMPStruct
  80. //
  81. // This routine will output the SNMP structure 
  82. // (in a more readable form) to a file called,
  83. // SNMPDATA.OUT.
  84. //------------------------------------------------------------------------
  85. void DecomposeSNMPStruct ( OM_workspace Workspace,
  86.                            OM_public_object SNMPStruct )
  87. {
  88.  
  89.  
  90.    // open the file in attach mode.
  91.  
  92.    hOutput = fopen ( "SNMPDATA", "a" );
  93.    if (hOutput == NULL)
  94.    {
  95.       return;
  96.    }
  97.  
  98.  
  99.    RecurseSNMPStruct ( Workspace, SNMPStruct, 0 );
  100.  
  101.    fprintf ( hOutput, "________________________________________________\n" );
  102.  
  103.    fclose ( hOutput );
  104.  
  105.    return;
  106. }
  107.  
  108. //-------------------------------------------------------------------------
  109. // Function: RecurseSNMPStruct
  110. //
  111. // Recursive routine to examine the SNMP Structure
  112. //-------------------------------------------------------------------------
  113. static void RecurseSNMPStruct ( OM_workspace Workspace, 
  114.                          OM_public_object SNMPStruct, 
  115.                          int Indent )
  116. {
  117.    OM_public_object CurrentClass;
  118.    OM_return_code   OMRet;
  119.    char *           TypeDesc;
  120.    int              i;
  121.    char             ValueDesc[128];
  122.  
  123.  
  124.    CurrentClass = SNMPStruct;
  125.  
  126.  
  127.    while ( SNMPStruct->type != OM_NO_MORE_TYPES )
  128.    {
  129.  
  130.       // indent the output
  131.  
  132.       fprintf ( hOutput, "%*.*s", Indent, Indent, "" );
  133.  
  134.  
  135.       // output the type description
  136.  
  137.       OMRet = at_type_to_label ( Workspace, &CurrentClass->value.string,
  138.                                  SNMPStruct->type, &TypeDesc );
  139.       if ( OMRet == OM_SUCCESS )
  140.       {
  141.          fprintf ( hOutput, "%s ", TypeDesc);
  142.          at_free ( TypeDesc );
  143.       }
  144.       else
  145.       {
  146.          fprintf ( hOutput, "Error in determining type!  ");
  147.       }
  148.    
  149.  
  150.       // output the syntax description.  Loop through the array
  151.       // of possible syntaxes, looking for a match.
  152.  
  153.       for ( i = 0; i < sizeof (SNMPSyntax) / sizeof (SNMPSyntax[0]); i++ )
  154.       {
  155.          if ( (SNMPStruct->syntax & OM_S_SYNTAX) == SNMPSyntax[i].SyntaxID )
  156.          {
  157.             fprintf ( hOutput, "%s ", SNMPSyntax[i].SyntaxDesc );
  158.             break;
  159.          }
  160.       }
  161.  
  162.  
  163.       // output the value
  164.       
  165.       ExtractValue ( Workspace, SNMPStruct, ValueDesc );
  166.       fprintf ( hOutput, "%s", ValueDesc );
  167.       fprintf ( hOutput, "\n");
  168.  
  169.  
  170.       // If this is a pointer to an object, then recurse
  171.       // using the object's pointer.
  172.  
  173.       if ( (SNMPStruct->syntax & OM_S_OBJECT)  == OM_S_OBJECT )
  174.       {
  175.          RecurseSNMPStruct ( Workspace, SNMPStruct->value.object.object,
  176.                              Indent + 4 );
  177.       }
  178.  
  179.  
  180.       // increment to the next object in the SNMP structure
  181.  
  182.       SNMPStruct++;
  183.  
  184.  
  185.    } // while loop
  186.  
  187. }
  188.  
  189. //-----------------------------------------------------------------------
  190. // Function: ExtractValue
  191. // 
  192. // This routine finds and formats the SNMP value
  193. //-----------------------------------------------------------------------
  194. static void ExtractValue ( OM_workspace Workspace,
  195.                            OM_public_object SNMPStruct,
  196.                            char *ValueDesc )
  197. {
  198.    OM_return_code   OMRet;
  199.    char            *OIDDesc;
  200.    char            *PackageName;
  201.    OM_uint32        TypeDesc;
  202.    int              i;   // loop variable
  203.  
  204.  
  205.    switch ( SNMPStruct->syntax & OM_S_SYNTAX )
  206.    {
  207.       case OM_S_BOOLEAN:
  208.          if ( SNMPStruct->value.boolean == 0)
  209.          {
  210.             strcpy ( ValueDesc, "True");
  211.          }
  212.          else
  213.          {
  214.             strcpy ( ValueDesc, "False");
  215.          }
  216.          break;
  217.  
  218.       case OM_S_INTEGER:
  219.       case OM_S_ENUMERATION:
  220.          sprintf ( ValueDesc, "%d", SNMPStruct->value.integer );
  221.          break;
  222.  
  223.       case OM_S_NULL:
  224.          strcpy ( ValueDesc, "Null" );
  225.          break;
  226.  
  227.       case OM_S_OBJECT:
  228.          sprintf ( ValueDesc, "%X", SNMPStruct->value.object.object );
  229.          break;
  230.          
  231.       case OM_S_BIT_STRING:
  232.       case OM_S_OBJECT_DESCRIPTOR_STRING:
  233.       case OM_S_ENCODING_STRING:
  234.          for ( i = 0; i < SNMPStruct->value.string.length; i++ )
  235.          {
  236.             sprintf ( &ValueDesc[i*2], "2.2%X", 
  237.                       ((char *)(SNMPStruct->value.string.elements))[i] );
  238.          }
  239.          break;
  240.  
  241.       case OM_S_GENERAL_STRING:
  242.       case OM_S_GENERALISED_TIME_STRING:
  243.       case OM_S_GRAPHIC_STRING:
  244.       case OM_S_IA5_STRING:
  245.       case OM_S_NUMERIC_STRING:
  246.       case OM_S_PRINTABLE_STRING:
  247.       case OM_S_TELETEX_STRING:
  248.       case OM_S_UTC_TIME_STRING:
  249.       case OM_S_VIDEOTEX_STRING:
  250.       case OM_S_VISIBLE_STRING:
  251.          memcpy ( ValueDesc, (char *)SNMPStruct->value.string.elements,
  252.                   SNMPStruct->value.string.length );
  253.          ValueDesc[SNMPStruct->value.string.length] = '\0';
  254.          break;
  255.  
  256.       case OM_S_OBJECT_IDENTIFIER_STRING:
  257.          OMRet = at_oid_to_label ( Workspace, &SNMPStruct->value.string,
  258.                                    &PackageName, &OIDDesc, &TypeDesc );
  259.          if ( OMRet == OM_SUCCESS )
  260.          {
  261.             sprintf ( ValueDesc, "%s", OIDDesc );
  262.             at_free ( PackageName );
  263.             at_free ( OIDDesc );
  264.          }
  265.          else
  266.          {
  267.             OMRet = at_oid_to_str ( SNMPStruct->value.string, &OIDDesc );
  268.             if ( OMRet == OM_SUCCESS )
  269.             {
  270.                strcpy ( ValueDesc, OIDDesc );
  271.                at_free ( OIDDesc );
  272.             }
  273.             else
  274.             {
  275.                strcpy ( ValueDesc, "Unknown OID" );
  276.             }
  277.          }
  278.          break;
  279.  
  280.       case OM_S_OCTET_STRING:
  281.       {
  282.          int i;
  283.  
  284.          // Special formatting for IP Addresses
  285.  
  286.          if (SNMPStruct->type == MP_IP_ADDRESS) 
  287.          {
  288.             sprintf (ValueDesc,"%i.%i.%i.%i", 
  289.                   (int)((char *)SNMPStruct->value.string.elements)[0],
  290.                   (int)((char *)SNMPStruct->value.string.elements)[1],
  291.                   (int)((char *)SNMPStruct->value.string.elements)[2],
  292.                   (int)((char *)SNMPStruct->value.string.elements)[3] );
  293.          }
  294.          else
  295.          {
  296.             int Ascii = 1;  // assume readable ascii
  297.  
  298.             // determine if the data is readable ascii.
  299.  
  300.             for (i = 0; i < SNMPStruct->value.string.length; i++)
  301.             {
  302.                if (!isprint(((char *)SNMPStruct->value.string.elements)[i]))
  303.                {
  304.                   Ascii = 0;     // not readable ascii
  305.                   break;
  306.                }
  307.             }
  308.       
  309.             if ( !Ascii )
  310.             {
  311.                for (i = 0; i < SNMPStruct->value.string.length; i++)
  312.                {
  313.                   sprintf (&ValueDesc[i*2],"%02X", 
  314.                            ((char *)SNMPStruct->value.string.elements)[i]);
  315.                }
  316.             }
  317.             else
  318.             {
  319.                memcpy(ValueDesc, (char *)SNMPStruct->value.string.elements,
  320.                         SNMPStruct->value.string.length );
  321.                ValueDesc[SNMPStruct->value.string.length] = '\0';
  322.             }
  323.          }
  324.  
  325.       }
  326.       break;
  327.  
  328.       default:
  329.          strcpy ( ValueDesc, "Unknown Syntax" );
  330.          break;
  331.          
  332.    } // switch 
  333.  
  334.    return;
  335. }
  336.  
  337.  
  338. //------------------------------------------------------------------------
  339. // Function: GetSNMPData
  340. //
  341. // This routine will search the SNMP structure looking for a 
  342. // match with the desired ID.  When found, the ID's data is
  343. // returned in Data parameter.
  344. //------------------------------------------------------------------------
  345. int GetSNMPData ( OM_workspace Workspace,
  346.                    OM_public_object SNMPStruct,
  347.                    char *ID, char *Data )
  348. {
  349.    int  Found  = 0;
  350.    OM_object_identifier OID;
  351.  
  352.  
  353.    Data[0] = '\0';
  354.  
  355.  
  356.  
  357.    while ( SNMPStruct->type != OM_NO_MORE_TYPES && Found == 0 )
  358.    {
  359.       switch ( SNMPStruct->type )
  360.       {
  361.  
  362.          // This can be though of as a 'Header' for SNMP data that
  363.          // will follow (recursive).
  364.          case MP_VAR_BIND_LIST:
  365.             Found = GetSNMPData ( Workspace, SNMPStruct->value.object.object,
  366.                                   ID, Data );
  367.             if ( Found == 1 )
  368.             {
  369.                return Found;
  370.             }
  371.             break;
  372.  
  373.  
  374.          // If MP_NAME, then this contains the ID of the value returned.
  375.          // If the IDs match, then the next element must be the value,
  376.          // which therefore must have the type MP_VALUE.  If this is
  377.          // true, then recurse to get the value.  We will then be looking
  378.          // for MP_SIMPLE elements.
  379.          case MP_NAME:
  380.             at_str_to_oid ( ID, &OID );
  381.             if ( at_oid_match ( &OID, &SNMPStruct->value.string ) == OM_TRUE )
  382.             {
  383.                SNMPStruct++;
  384.                if ( SNMPStruct->type == MP_VALUE )
  385.                {
  386.                   Found = GetSNMPData ( Workspace, 
  387.                                         SNMPStruct->value.object.object,
  388.                                         ID, Data );
  389.                   if ( Found == 1 )
  390.                   {
  391.                      at_free ( OID.elements );
  392.                      return Found;
  393.                   }
  394.                }
  395.             }
  396.             at_free ( OID.elements );
  397.             break;
  398.  
  399.  
  400.          // 'Header' that means data following is of simple or
  401.          // application type
  402.          case MP_APPLICATION_WIDE:
  403.          case MP_SIMPLE:
  404.             Found = GetSNMPData ( Workspace, SNMPStruct->value.object.object,
  405.                                   ID, Data );
  406.             if ( Found == 1 )
  407.             {
  408.                return Found;
  409.             }
  410.             break;
  411.  
  412.  
  413.          // This is the data !!
  414.          case MP_STRING:
  415.          case MP_COUNTER:
  416.             Found = 1;
  417.             break;
  418.  
  419.       } // type switch
  420.  
  421.       if ( Found == 0)
  422.       {
  423.          SNMPStruct++;
  424.       }
  425.  
  426.    } // while loop
  427.  
  428.  
  429.    if ( Found == 1 )
  430.    {
  431.       ExtractValue ( Workspace, SNMPStruct, Data );
  432.    }
  433.       
  434.  
  435.    return Found;
  436. }
  437.  
  438.