|
|
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.