home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / VRAC / SNMPKT.ZIP / TESTMIB.C < prev    next >
C/C++ Source or Header  |  1992-08-04  |  18KB  |  644 lines

  1. /*++ BUILD Version: 0001    // Increment this if a change has global effects
  2.  
  3. Copyright (c) 1991  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     testmib.c
  8.  
  9. Abstract:
  10.  
  11.     Sample SNMP Extension Agent for Windows NT.
  12.  
  13.     These files (testdll.c, testmib.c, and testmib.h) provide an example of 
  14.     how to structure an Extension Agent DLL which works in conjunction with 
  15.     the SNMP Extendible Agent for Windows NT.
  16.  
  17.     Extensive comments have been included to describe its structure and
  18.     operation.  See also "Microsoft Windows/NT SNMP Programmer's Reference".
  19.  
  20. Created:
  21.  
  22.     13-Jun-1991
  23.  
  24. Revision History:
  25.  
  26. --*/
  27.  
  28.  
  29.  
  30.  
  31. // This Extension Agent implements the Internet toaster MIB.  It's 
  32. // definition follows here:
  33. //
  34. //
  35. //         TOASTER-MIB DEFINITIONS ::= BEGIN
  36. //
  37. //         IMPORTS
  38. //                 enterprises
  39. //                         FROM RFC1155-SMI
  40. //                 OBJECT-TYPE
  41. //                         FROM RFC-1212
  42. //                 DisplayString
  43. //                         FROM RFC-1213;
  44. //
  45. //         epilogue        OBJECT IDENTIFIER ::= { enterprises 12 }
  46. //         toaster         OBJECT IDENTIFIER ::= { epilogue 2 }
  47. //
  48. //         -- toaster MIB
  49. //
  50. //         toasterManufacturer OBJECT-TYPE
  51. //             SYNTAX  DisplayString
  52. //             ACCESS  read-only
  53. //             STATUS  mandatory
  54. //             DESCRIPTION
  55. //                     "The name of the toaster's manufacturer. For instance,
  56. //                      Sunbeam."
  57. //             ::= { toaster 1 }
  58. //
  59. //         toasterModelNumber OBJECT-TYPE
  60. //             SYNTAX  DisplayString
  61. //             ACCESS  read-only
  62. //             STATUS  mandatory
  63. //             DESCRIPTION
  64. //                     "The name of the toaster's model. For instance,
  65. //                      Radiant Automatic."
  66. //             ::= { toaster 2 }
  67. //
  68. //         toasterControl OBJECT-TYPE
  69. //             SYNTAX  INTEGER  {
  70. //                         up(1),
  71. //                         down(2)
  72. //                     }
  73. //             ACCESS  read-write
  74. //             STATUS  mandatory
  75. //             DESCRIPTION
  76. //                     "This variable controls the current state of the 
  77. //                      toaster. To begin toasting, set it to down(2). To 
  78. //                      abort toasting (perhaps in the event of an 
  79. //                      emergency), set it to up(2)."
  80. //             ::= { toaster 3 }
  81. //
  82. //         toasterDoneness OBJECT-TYPE
  83. //             SYNTAX  INTEGER (1..10)
  84. //             ACCESS  read-write
  85. //             STATUS  mandatory
  86. //             DESCRIPTION
  87. //                     "This variable controls how well done ensuing toast 
  88. //                      should be on a scale of 1 to 10. Toast made at 10 
  89. //                      is generally considered unfit for human consumption; 
  90. //                      toast made at 1 is lightly warmed."
  91. //             ::= { toaster 4 }
  92. //
  93. //         toasterToastType OBJECT-TYPE
  94. //             SYNTAX  INTEGER  {
  95. //                         white-bread(1),
  96. //                         wheat-bread(2),
  97. //                         wonder-bread(3),
  98. //                         frozen-waffle(4),
  99. //                         frozen-bagel(5),
  100. //                         hash-brown(6),
  101. //                         other(7)
  102. //                     }
  103. //             ACCESS  read-write
  104. //             STATUS  mandatory
  105. //             DESCRIPTION
  106. //                     "This variable informs the toaster of the type of 
  107. //                      material being toasted. The toaster uses this 
  108. //                      information combined with toasterToastDoneness to 
  109. //                      compute how long the material must be toasted for 
  110. //                      to achieve the desired doneness."
  111. //             ::= { toaster 5 }
  112. //
  113. //         END
  114.  
  115.  
  116. // Necessary includes.
  117.  
  118. #include <windows.h>
  119. #include <malloc.h>
  120.  
  121. #include <snmp.h>
  122.  
  123.  
  124. // Contains definitions for the table structure describing the MIB.  This
  125. // is used in conjunction with testmib.c where the MIB requests are resolved.
  126.  
  127. #include "testmib.h"
  128.  
  129.  
  130. // If an addition or deletion to the MIB is necessary, there are several
  131. // places in the code that must be checked and possibly changed.
  132. //
  133. // The last field in each MIB entry is used to point to the NEXT
  134. // leaf variable.  If an addition or deletetion is made, these pointers
  135. // may need to be updated to reflect the modification.
  136.  
  137.  
  138. // The prefix to all of these MIB variables is 1.3.6.1.4.1.12
  139.  
  140. UINT OID_Prefix[] = { 1, 3, 6, 1, 4, 1, 12 };
  141. AsnObjectIdentifier MIB_OidPrefix = { OID_SIZEOF(OID_Prefix), OID_Prefix };
  142.  
  143.  
  144.  
  145. //                         //
  146. // OID definitions for MIB //
  147. //                         //
  148.  
  149.  
  150. // Definition of the toaster group
  151.  
  152. UINT MIB_toaster[]  = { 2 };
  153.  
  154.  
  155. // Definition of leaf variables under the toaster group
  156. // All leaf variables have a zero appended to their OID to indicate
  157. // that it is the only instance of this variable and it exists.
  158.  
  159. UINT MIB_toasterManufacturer[]     = { 2, 1, 0 };
  160. UINT MIB_toasterModelNumber[]      = { 2, 2, 0 };
  161. UINT MIB_toasterControl[]          = { 2, 3, 0 };
  162. UINT MIB_toasterDoneness[]         = { 2, 4, 0 };
  163. UINT MIB_toasterToastType[]        = { 2, 5, 0 };
  164.  
  165.  
  166.  
  167. //                             //
  168. // Storage definitions for MIB //
  169. //                             //
  170.  
  171. char       MIB_toasterManStor[]     = "Microsoft Corporation";
  172. char       MIB_toasterModelStor[]   = 
  173.                "Example SNMP Extension Agent for Windows/NT (TOASTER-MIB).";
  174. AsnInteger MIB_toasterControlStor   = 1;
  175. AsnInteger MIB_toasterDonenessStor  = 2;
  176. AsnInteger MIB_toasterToastTypeStor = 3;
  177.  
  178.  
  179.  
  180. // MIB definiton
  181.  
  182. MIB_ENTRY Mib[] = {
  183.       { { OID_SIZEOF(MIB_toasterManufacturer), MIB_toasterManufacturer },
  184.         &MIB_toasterManStor, ASN_RFC1213_DISPSTRING,
  185.         MIB_ACCESS_READ, MIB_leaf_func, &Mib[1] },
  186.  
  187.       { { OID_SIZEOF(MIB_toasterModelNumber), MIB_toasterModelNumber },
  188.         &MIB_toasterModelStor, ASN_RFC1213_DISPSTRING,
  189.         MIB_ACCESS_READ, MIB_leaf_func, &Mib[2] },
  190.  
  191.       { { OID_SIZEOF(MIB_toasterControl), MIB_toasterControl },
  192.         &MIB_toasterControlStor, ASN_INTEGER,
  193.         MIB_ACCESS_READWRITE, MIB_control_func, &Mib[3] },
  194.  
  195.       { { OID_SIZEOF(MIB_toasterDoneness), MIB_toasterDoneness },
  196.         &MIB_toasterDonenessStor, ASN_INTEGER,
  197.         MIB_ACCESS_READWRITE, MIB_doneness_func, &Mib[4] },
  198.  
  199.       { { OID_SIZEOF(MIB_toasterToastType), MIB_toasterToastType },
  200.         &MIB_toasterToastTypeStor, ASN_INTEGER,
  201.         MIB_ACCESS_READWRITE, MIB_toasttype_func, NULL }
  202.       };
  203.  
  204. UINT MIB_num_variables = sizeof Mib / sizeof( MIB_ENTRY );
  205.  
  206.  
  207.  
  208. //
  209. // ResolveVarBind
  210. //    Resolves a single variable binding.  Modifies the variable on a GET
  211. //    or a GET-NEXT.
  212. //
  213. // Notes:
  214. //
  215. // Return Codes:
  216. //    Standard PDU error codes.
  217. //
  218. // Error Codes:
  219. //    None.
  220. //
  221. UINT ResolveVarBind(
  222.         IN OUT RFC1157VarBind *VarBind, // Variable Binding to resolve
  223.     IN UINT PduAction               // Action specified in PDU
  224.     )
  225.  
  226. {
  227. MIB_ENTRY            *MibPtr;
  228. AsnObjectIdentifier  TempOid;
  229. int                  CompResult;
  230. UINT                 I;
  231. UINT                 nResult;
  232.  
  233.  
  234.    // Search for var bind name in the MIB
  235.    I      = 0;
  236.    MibPtr = NULL;
  237.    while ( MibPtr == NULL && I < MIB_num_variables )
  238.       {
  239.       // Construct OID with complete prefix for comparison purposes
  240.       SNMP_oidcpy( &TempOid, &MIB_OidPrefix );
  241.       SNMP_oidappend( &TempOid, &Mib[I].Oid );
  242.  
  243.       // Check for OID in MIB - On a GET-NEXT the OID does not have to exactly
  244.       // match a variable in the MIB, it must only fall under the MIB root.
  245.       CompResult = SNMP_oidcmp( &VarBind->name, &TempOid );
  246.       if ( 0 > CompResult )
  247.      {
  248.      // Since there is not an exact match, the only valid action is GET-NEXT
  249.      if ( MIB_ACTION_GETNEXT != PduAction )
  250.         {
  251.         nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  252.         goto Exit;
  253.         }
  254.  
  255.      // Since the match was not exact, but var bind name is within MIB,
  256.      // we are at the NEXT MIB variable down from the one specified.
  257.      PduAction = MIB_ACTION_GET;
  258.      MibPtr = &Mib[I];
  259.  
  260.          // Replace var bind name with new name
  261.          SNMP_oidfree( &VarBind->name );
  262.          SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
  263.          SNMP_oidappend( &VarBind->name, &MibPtr->Oid );
  264.      }
  265.       else
  266.          {
  267.      // An exact match was found.
  268.          if ( 0 == CompResult )
  269.             {
  270.         MibPtr = &Mib[I];
  271.         }
  272.      }
  273.  
  274.       // Free OID memory before checking another variable
  275.       SNMP_oidfree( &TempOid );
  276.  
  277.       I++;
  278.       } // while
  279.  
  280.    // If OID not within scope of MIB, then no such name
  281.    if ( MibPtr == NULL )
  282.       {
  283.       nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
  284.       goto Exit;
  285.       }
  286.  
  287.    // Call function to process request.  Each MIB entry has a function pointer
  288.    // that knows how to process its MIB variable.
  289.    nResult = (*MibPtr->MibFunc)( PduAction, MibPtr, VarBind );
  290.  
  291.    // Free temp memory
  292.    SNMP_oidfree( &TempOid );
  293.  
  294. Exit:
  295.    return nResult;
  296. } // ResolveVarBind
  297.  
  298.  
  299.  
  300. //
  301. // MIB_leaf_func
  302. //    Performs generic actions on LEAF variables in the MIB.
  303. //
  304. // Notes:
  305. //
  306. // Return Codes:
  307. //    Standard PDU error codes.
  308. //
  309. // Error Codes:
  310. //    None.
  311. //
  312. UINT MIB_leaf_func(
  313.         IN UINT Action,
  314.     IN MIB_ENTRY *MibPtr,
  315.     IN RFC1157VarBind *VarBind
  316.     )
  317.  
  318. {
  319. UINT   ErrStat;
  320.  
  321.    switch ( Action )
  322.       {
  323.       case MIB_ACTION_GETNEXT:
  324.      // If there is no GET-NEXT pointer, this is the end of this MIB
  325.      if ( MibPtr->MibNext == NULL )
  326.         {
  327.         ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  328.         goto Exit;
  329.         }
  330.  
  331.          // Setup var bind name of NEXT MIB variable
  332.          SNMP_oidfree( &VarBind->name );
  333.          SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
  334.          SNMP_oidappend( &VarBind->name, &MibPtr->MibNext->Oid );
  335.  
  336.          // Call function to process request.  Each MIB entry has a function
  337.      // pointer that knows how to process its MIB variable.
  338.          ErrStat = (*MibPtr->MibNext->MibFunc)( MIB_ACTION_GET,
  339.                                             MibPtr->MibNext, VarBind );
  340.          break;
  341.  
  342.       case MIB_ACTION_GET:
  343.          // Make sure that this variable's ACCESS is GET'able
  344.      if ( MibPtr->Access != MIB_ACCESS_READ &&
  345.           MibPtr->Access != MIB_ACCESS_READWRITE )
  346.         {
  347.         ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  348.         goto Exit;
  349.         }
  350.  
  351.      // Setup varbind's return value
  352.      VarBind->value.asnType = MibPtr->Type;
  353.      switch ( VarBind->value.asnType )
  354.         {
  355.             case ASN_RFC1155_COUNTER:
  356.             case ASN_RFC1155_GAUGE:
  357.             case ASN_INTEGER:
  358.                VarBind->value.asnValue.number = *(AsnInteger *)(MibPtr->Storage);
  359.            break;
  360.  
  361.             case ASN_OCTETSTRING: // This entails ASN_RFC1213_DISPSTRING also
  362.            VarBind->value.asnValue.string.length =
  363.                                  strlen( (LPSTR)MibPtr->Storage );
  364.  
  365.            if ( NULL == 
  366.                     (VarBind->value.asnValue.string.stream =
  367.                     malloc(VarBind->value.asnValue.string.length *
  368.                            sizeof(char))) )
  369.               {
  370.               ErrStat = SNMP_ERRORSTATUS_GENERR;
  371.               goto Exit;
  372.               }
  373.  
  374.            memcpy( VarBind->value.asnValue.string.stream,
  375.                    (LPSTR)MibPtr->Storage,
  376.                    VarBind->value.asnValue.string.length );
  377.            VarBind->value.asnValue.string.dynamic = TRUE;
  378.  
  379.            break;
  380.  
  381.         default:
  382.            ErrStat = SNMP_ERRORSTATUS_GENERR;
  383.            goto Exit;
  384.         }
  385.  
  386.      break;
  387.  
  388.       case MIB_ACTION_SET:
  389.          // Make sure that this variable's ACCESS is SET'able
  390.      if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
  391.           MibPtr->Access != MIB_ACCESS_WRITE )
  392.         {
  393.         ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  394.             goto Exit;
  395.         }
  396.  
  397.          // Check for proper type before setting
  398.          if ( MibPtr->Type != VarBind->value.asnType )
  399.         {
  400.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  401.         goto Exit;
  402.         }
  403.  
  404.      // Save value in MIB
  405.      switch ( VarBind->value.asnType )
  406.         {
  407.             case ASN_RFC1155_COUNTER:
  408.             case ASN_RFC1155_GAUGE:
  409.             case ASN_INTEGER:
  410.                *(AsnInteger *)(MibPtr->Storage) = VarBind->value.asnValue.number;
  411.            break;
  412.  
  413.             case ASN_OCTETSTRING: // This entails ASN_RFC1213_DISPSTRING also
  414.                // The storage must be adequate to contain the new string
  415.                // including a NULL terminator.
  416.                memcpy( (LPSTR)MibPtr->Storage,
  417.                        VarBind->value.asnValue.string.stream,
  418.                        VarBind->value.asnValue.string.length );
  419.  
  420.            ((LPSTR)MibPtr->Storage)[VarBind->value.asnValue.string.length] =
  421.                                                                           '\0';
  422.            break;
  423.  
  424.         default:
  425.            ErrStat = SNMP_ERRORSTATUS_GENERR;
  426.            goto Exit;
  427.         }
  428.  
  429.          break;
  430.  
  431.       default:
  432.      ErrStat = SNMP_ERRORSTATUS_GENERR;
  433.      goto Exit;
  434.       } // switch
  435.  
  436.    // Signal no error occurred
  437.    ErrStat = SNMP_ERRORSTATUS_NOERROR;
  438.  
  439. Exit:
  440.    return ErrStat;
  441. } // MIB_leaf_func
  442.  
  443.  
  444.  
  445. //
  446. // MIB_control_func
  447. //    Performs specific actions on the toasterControl MIB variable
  448. //
  449. // Notes:
  450. //
  451. // Return Codes:
  452. //    Standard PDU error codes.
  453. //
  454. // Error Codes:
  455. //    None.
  456. //
  457. UINT MIB_control_func(
  458.         IN UINT Action,
  459.     IN MIB_ENTRY *MibPtr,
  460.     IN RFC1157VarBind *VarBind
  461.     )
  462.  
  463. {
  464. UINT   ErrStat;
  465.  
  466.    switch ( Action )
  467.       {
  468.       case MIB_ACTION_SET:
  469.          // Make sure that this variable's ACCESS is SET'able
  470.      if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
  471.           MibPtr->Access != MIB_ACCESS_WRITE )
  472.         {
  473.         ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  474.             goto Exit;
  475.         }
  476.  
  477.          // Check for proper type before setting
  478.          if ( MibPtr->Type != VarBind->value.asnType )
  479.         {
  480.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  481.         goto Exit;
  482.         }
  483.  
  484.          // Make sure the value is valid
  485.          if ( MIB_TOASTER_UP > VarBind->value.asnValue.number ||
  486.               MIB_TOASTER_DOWN < VarBind->value.asnValue.number )
  487.             {
  488.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  489.         goto Exit;
  490.             }
  491.  
  492.          // Let fall through purposefully for further processing by
  493.          // generic leaf function.
  494.  
  495.       case MIB_ACTION_GETNEXT:
  496.       case MIB_ACTION_GET:
  497.      // Call the more generic function to perform the action
  498.          ErrStat = MIB_leaf_func( Action, MibPtr, VarBind );
  499.          break;
  500.  
  501.       default:
  502.      ErrStat = SNMP_ERRORSTATUS_GENERR;
  503.      goto Exit;
  504.       } // switch
  505.  
  506. Exit:
  507.    return ErrStat;
  508. } // MIB_control_func
  509.  
  510.  
  511.  
  512. //
  513. // MIB_doneness_func
  514. //    Performs specific actions on the toasterDoneness MIB variable
  515. //
  516. // Notes:
  517. //
  518. // Return Codes:
  519. //    Standard PDU error codes.
  520. //
  521. // Error Codes:
  522. //    None.
  523. //
  524. UINT MIB_doneness_func(
  525.         IN UINT Action,
  526.     IN MIB_ENTRY *MibPtr,
  527.     IN RFC1157VarBind *VarBind
  528.     )
  529.  
  530. {
  531. UINT   ErrStat;
  532.  
  533.    switch ( Action )
  534.       {
  535.       case MIB_ACTION_SET:
  536.          // Make sure that this variable's ACCESS is SET'able
  537.      if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
  538.           MibPtr->Access != MIB_ACCESS_WRITE )
  539.         {
  540.         ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  541.             goto Exit;
  542.         }
  543.  
  544.          // Check for proper type before setting
  545.          if ( MibPtr->Type != VarBind->value.asnType )
  546.         {
  547.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  548.         goto Exit;
  549.         }
  550.  
  551.          // Make sure the value is valid
  552.          if ( MIB_TOASTER_LIGHTLYWARM > VarBind->value.asnValue.number ||
  553.               MIB_TOASTER_BURNT < VarBind->value.asnValue.number )
  554.             {
  555.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  556.         goto Exit;
  557.             }
  558.  
  559.          // Let fall through purposefully for further processing by
  560.          // generic leaf function.
  561.  
  562.       case MIB_ACTION_GETNEXT:
  563.       case MIB_ACTION_GET:
  564.      // Call the more generic function to perform the action
  565.          ErrStat = MIB_leaf_func( Action, MibPtr, VarBind );
  566.          break;
  567.  
  568.       default:
  569.      ErrStat = SNMP_ERRORSTATUS_GENERR;
  570.      goto Exit;
  571.       } // switch
  572.  
  573. Exit:
  574.    return ErrStat;
  575. } // MIB_doneness_func
  576.  
  577.  
  578.  
  579. //
  580. // MIB_toasttype_func
  581. //    Performs specific actions on the toasterToastType MIB variable
  582. //
  583. // Notes:
  584. //
  585. // Return Codes:
  586. //    Standard PDU error codes.
  587. //
  588. // Error Codes:
  589. //    None.
  590. //
  591. UINT MIB_toasttype_func(
  592.         IN UINT Action,
  593.     IN MIB_ENTRY *MibPtr,
  594.     IN RFC1157VarBind *VarBind
  595.     )
  596.  
  597. {
  598. UINT   ErrStat;
  599.  
  600.    switch ( Action )
  601.       {
  602.       case MIB_ACTION_SET:
  603.          // Make sure that this variable's ACCESS is SET'able
  604.      if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
  605.           MibPtr->Access != MIB_ACCESS_WRITE )
  606.         {
  607.         ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
  608.             goto Exit;
  609.         }
  610.  
  611.          // Check for proper type before setting
  612.          if ( MibPtr->Type != VarBind->value.asnType )
  613.         {
  614.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  615.         goto Exit;
  616.         }
  617.  
  618.          // Make sure the value is valid
  619.          if ( MIB_TOASTER_WHITEBREAD > VarBind->value.asnValue.number ||
  620.               MIB_TOASTER_OTHERBREAD < VarBind->value.asnValue.number )
  621.             {
  622.         ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  623.         goto Exit;
  624.             }
  625.  
  626.          // Let fall through purposefully for further processing by
  627.          // generic leaf function.
  628.  
  629.       case MIB_ACTION_GETNEXT:
  630.       case MIB_ACTION_GET:
  631.      // Call the more generic function to perform the action
  632.          ErrStat = MIB_leaf_func( Action, MibPtr, VarBind );
  633.          break;
  634.  
  635.       default:
  636.      ErrStat = SNMP_ERRORSTATUS_GENERR;
  637.      goto Exit;
  638.       } // switch
  639.  
  640. Exit:
  641.    return ErrStat;
  642. } // MIB_toasttype_func
  643.  
  644.