home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / snmp / testdll / testmib.c < prev    next >
C/C++ Source or Header  |  1996-08-09  |  18KB  |  635 lines

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