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