source: trunk/Packages/synapse/source/lib/snmpsend.pas

Last change on this file was 2, checked in by chronos, 12 years ago
  • Přidáno: Základní kostra projektu.
  • Přidáno: Knihovna synapse.
File size: 40.3 KB
Line 
1{==============================================================================|
2| Project : Ararat Synapse | 004.000.000 |
3|==============================================================================|
4| Content: SNMP client |
5|==============================================================================|
6| Copyright (c)1999-2011, Lukas Gebauer |
7| All rights reserved. |
8| |
9| Redistribution and use in source and binary forms, with or without |
10| modification, are permitted provided that the following conditions are met: |
11| |
12| Redistributions of source code must retain the above copyright notice, this |
13| list of conditions and the following disclaimer. |
14| |
15| Redistributions in binary form must reproduce the above copyright notice, |
16| this list of conditions and the following disclaimer in the documentation |
17| and/or other materials provided with the distribution. |
18| |
19| Neither the name of Lukas Gebauer nor the names of its contributors may |
20| be used to endorse or promote products derived from this software without |
21| specific prior written permission. |
22| |
23| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
24| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
27| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
29| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
30| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
33| DAMAGE. |
34|==============================================================================|
35| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
36| Portions created by Lukas Gebauer are Copyright (c)2000-2011. |
37| All Rights Reserved. |
38|==============================================================================|
39| Contributor(s): |
40| Jean-Fabien Connault (cycocrew@worldnet.fr) |
41|==============================================================================|
42| History: see HISTORY.HTM from distribution package |
43| (Found at URL: http://www.ararat.cz/synapse/) |
44|==============================================================================}
45
46{:@abstract(SNMP client)
47Supports SNMPv1 include traps, SNMPv2c and SNMPv3 include authorization
48and privacy encryption.
49
50Used RFC: RFC-1157, RFC-1901, RFC-3412, RFC-3414, RFC-3416, RFC-3826
51
52Supported Authorization hashes: MD5, SHA1
53Supported Privacy encryptions: DES, 3DES, AES
54}
55
56{$IFDEF FPC}
57 {$MODE DELPHI}
58{$ENDIF}
59{$Q-}
60{$H+}
61
62{$IFDEF UNICODE}
63 {$WARN IMPLICIT_STRING_CAST OFF}
64 {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
65{$ENDIF}
66
67unit snmpsend;
68
69interface
70
71uses
72 Classes, SysUtils,
73 blcksock, synautil, asn1util, synaip, synacode, synacrypt;
74
75const
76 cSnmpProtocol = '161';
77 cSnmpTrapProtocol = '162';
78
79 SNMP_V1 = 0;
80 SNMP_V2C = 1;
81 SNMP_V3 = 3;
82
83 //PDU type
84 PDUGetRequest = $A0;
85 PDUGetNextRequest = $A1;
86 PDUGetResponse = $A2;
87 PDUSetRequest = $A3;
88 PDUTrap = $A4; //Obsolete
89 //for SNMPv2
90 PDUGetBulkRequest = $A5;
91 PDUInformRequest = $A6;
92 PDUTrapV2 = $A7;
93 PDUReport = $A8;
94
95 //errors
96 ENoError = 0;
97 ETooBig = 1;
98 ENoSuchName = 2;
99 EBadValue = 3;
100 EReadOnly = 4;
101 EGenErr = 5;
102 //errors SNMPv2
103 ENoAccess = 6;
104 EWrongType = 7;
105 EWrongLength = 8;
106 EWrongEncoding = 9;
107 EWrongValue = 10;
108 ENoCreation = 11;
109 EInconsistentValue = 12;
110 EResourceUnavailable = 13;
111 ECommitFailed = 14;
112 EUndoFailed = 15;
113 EAuthorizationError = 16;
114 ENotWritable = 17;
115 EInconsistentName = 18;
116
117type
118
119 {:@abstract(Possible values for SNMPv3 flags.)
120 This flags specify level of authorization and encryption.}
121 TV3Flags = (
122 NoAuthNoPriv,
123 AuthNoPriv,
124 AuthPriv);
125
126 {:@abstract(Type of SNMPv3 authorization)}
127 TV3Auth = (
128 AuthMD5,
129 AuthSHA1);
130
131 {:@abstract(Type of SNMPv3 privacy)}
132 TV3Priv = (
133 PrivDES,
134 Priv3DES,
135 PrivAES);
136
137 {:@abstract(Data object with one record of MIB OID and corresponding values.)}
138 TSNMPMib = class(TObject)
139 protected
140 FOID: AnsiString;
141 FValue: AnsiString;
142 FValueType: Integer;
143 published
144 {:OID number in string format.}
145 property OID: AnsiString read FOID write FOID;
146
147 {:Value of OID object in string format.}
148 property Value: AnsiString read FValue write FValue;
149
150 {:Define type of Value. Supported values are defined in @link(asn1util).
151 For queries use ASN1_NULL, becouse you don't know type in response!}
152 property ValueType: Integer read FValueType write FValueType;
153 end;
154
155 {:@abstract(It holding all information for SNMPv3 agent synchronization)
156 Used internally.}
157 TV3Sync = record
158 EngineID: AnsiString;
159 EngineBoots: integer;
160 EngineTime: integer;
161 EngineStamp: Cardinal;
162 end;
163
164 {:@abstract(Data object abstracts SNMP data packet)}
165 TSNMPRec = class(TObject)
166 protected
167 FVersion: Integer;
168 FPDUType: Integer;
169 FID: Integer;
170 FErrorStatus: Integer;
171 FErrorIndex: Integer;
172 FCommunity: AnsiString;
173 FSNMPMibList: TList;
174 FMaxSize: Integer;
175 FFlags: TV3Flags;
176 FFlagReportable: Boolean;
177 FContextEngineID: AnsiString;
178 FContextName: AnsiString;
179 FAuthMode: TV3Auth;
180 FAuthEngineID: AnsiString;
181 FAuthEngineBoots: integer;
182 FAuthEngineTime: integer;
183 FAuthEngineTimeStamp: cardinal;
184 FUserName: AnsiString;
185 FPassword: AnsiString;
186 FAuthKey: AnsiString;
187 FPrivMode: TV3Priv;
188 FPrivPassword: AnsiString;
189 FPrivKey: AnsiString;
190 FPrivSalt: AnsiString;
191 FPrivSaltCounter: integer;
192 FOldTrapEnterprise: AnsiString;
193 FOldTrapHost: AnsiString;
194 FOldTrapGen: Integer;
195 FOldTrapSpec: Integer;
196 FOldTrapTimeTicks: Integer;
197 function Pass2Key(const Value: AnsiString): AnsiString;
198 function EncryptPDU(const value: AnsiString): AnsiString;
199 function DecryptPDU(const value: AnsiString): AnsiString;
200 public
201 constructor Create;
202 destructor Destroy; override;
203
204 {:Decode SNMP packet in buffer to object properties.}
205 function DecodeBuf(Buffer: AnsiString): Boolean;
206
207 {:Encode obeject properties to SNMP packet.}
208 function EncodeBuf: AnsiString;
209
210 {:Clears all object properties to default values.}
211 procedure Clear;
212
213 {:Add entry to @link(SNMPMibList). For queries use value as empty string,
214 and ValueType as ASN1_NULL.}
215 procedure MIBAdd(const MIB, Value: AnsiString; ValueType: Integer);
216
217 {:Delete entry from @link(SNMPMibList).}
218 procedure MIBDelete(Index: Integer);
219
220 {:Search @link(SNMPMibList) list for MIB and return correspond value.}
221 function MIBGet(const MIB: AnsiString): AnsiString;
222
223 {:return number of entries in MIB array.}
224 function MIBCount: integer;
225
226 {:Return MIB information from given row of MIB array.}
227 function MIBByIndex(Index: Integer): TSNMPMib;
228
229 {:List of @link(TSNMPMib) objects.}
230 property SNMPMibList: TList read FSNMPMibList;
231 published
232 {:Version of SNMP packet. Default value is 0 (SNMP ver. 1). You can use
233 value 1 for SNMPv2c or value 3 for SNMPv3.}
234 property Version: Integer read FVersion write FVersion;
235
236 {:Community string for autorize access to SNMP server. (Case sensitive!)
237 Community string is not used in SNMPv3! Use @link(Username) and
238 @link(password) instead!}
239 property Community: AnsiString read FCommunity write FCommunity;
240
241 {:Define type of SNMP operation.}
242 property PDUType: Integer read FPDUType write FPDUType;
243
244 {:Contains ID number. Not need to use.}
245 property ID: Integer read FID write FID;
246
247 {:When packet is reply, contains error code. Supported values are defined by
248 E* constants.}
249 property ErrorStatus: Integer read FErrorStatus write FErrorStatus;
250
251 {:Point to error position in reply packet. Not usefull for users. It only
252 good for debugging!}
253 property ErrorIndex: Integer read FErrorIndex write FErrorIndex;
254
255 {:special value for GetBulkRequest of SNMPv2 and v3.}
256 property NonRepeaters: Integer read FErrorStatus write FErrorStatus;
257
258 {:special value for GetBulkRequest of SNMPv2 and v3.}
259 property MaxRepetitions: Integer read FErrorIndex write FErrorIndex;
260
261 {:Maximum message size in bytes for SNMPv3. For sending is default 1472 bytes.}
262 property MaxSize: Integer read FMaxSize write FMaxSize;
263
264 {:Specify if message is authorised or encrypted. Used only in SNMPv3.}
265 property Flags: TV3Flags read FFlags write FFlags;
266
267 {:For SNMPv3.... If is @true, SNMP agent must send reply (at least with some
268 error).}
269 property FlagReportable: Boolean read FFlagReportable write FFlagReportable;
270
271 {:For SNMPv3. If not specified, is used value from @link(AuthEngineID)}
272 property ContextEngineID: AnsiString read FContextEngineID write FContextEngineID;
273
274 {:For SNMPv3.}
275 property ContextName: AnsiString read FContextName write FContextName;
276
277 {:For SNMPv3. Specify Authorization mode. (specify used hash for
278 authorization)}
279 property AuthMode: TV3Auth read FAuthMode write FAuthMode;
280
281 {:For SNMPv3. Specify Privacy mode.}
282 property PrivMode: TV3Priv read FPrivMode write FPrivMode;
283
284 {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
285 property AuthEngineID: AnsiString read FAuthEngineID write FAuthEngineID;
286
287 {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
288 property AuthEngineBoots: Integer read FAuthEngineBoots write FAuthEngineBoots;
289
290 {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
291 property AuthEngineTime: Integer read FAuthEngineTime write FAuthEngineTime;
292
293 {:value used by SNMPv3 authorisation for synchronization with SNMP agent.}
294 property AuthEngineTimeStamp: Cardinal read FAuthEngineTimeStamp Write FAuthEngineTimeStamp;
295
296 {:SNMPv3 authorization username}
297 property UserName: AnsiString read FUserName write FUserName;
298
299 {:SNMPv3 authorization password}
300 property Password: AnsiString read FPassword write FPassword;
301
302 {:For SNMPv3. Computed Athorization key from @link(password).}
303 property AuthKey: AnsiString read FAuthKey write FAuthKey;
304
305 {:SNMPv3 privacy password}
306 property PrivPassword: AnsiString read FPrivPassword write FPrivPassword;
307
308 {:For SNMPv3. Computed Privacy key from @link(PrivPassword).}
309 property PrivKey: AnsiString read FPrivKey write FPrivKey;
310
311 {:MIB value to identify the object that sent the TRAPv1.}
312 property OldTrapEnterprise: AnsiString read FOldTrapEnterprise write FOldTrapEnterprise;
313
314 {:Address of TRAPv1 sender (IP address).}
315 property OldTrapHost: AnsiString read FOldTrapHost write FOldTrapHost;
316
317 {:Generic TRAPv1 identification.}
318 property OldTrapGen: Integer read FOldTrapGen write FOldTrapGen;
319
320 {:Specific TRAPv1 identification.}
321 property OldTrapSpec: Integer read FOldTrapSpec write FOldTrapSpec;
322
323 {:Number of 1/100th of seconds since last reboot or power up. (for TRAPv1)}
324 property OldTrapTimeTicks: Integer read FOldTrapTimeTicks write FOldTrapTimeTicks;
325 end;
326
327 {:@abstract(Implementation of SNMP protocol.)
328
329 Note: Are you missing properties for specify server address and port? Look to
330 parent @link(TSynaClient) too!}
331 TSNMPSend = class(TSynaClient)
332 protected
333 FSock: TUDPBlockSocket;
334 FBuffer: AnsiString;
335 FHostIP: AnsiString;
336 FQuery: TSNMPRec;
337 FReply: TSNMPRec;
338 function InternalSendSnmp(const Value: TSNMPRec): Boolean;
339 function InternalRecvSnmp(const Value: TSNMPRec): Boolean;
340 function InternalSendRequest(const QValue, RValue: TSNMPRec): Boolean;
341 function GetV3EngineID: AnsiString;
342 function GetV3Sync: TV3Sync;
343 public
344 constructor Create;
345 destructor Destroy; override;
346
347 {:Connects to a Host and send there query. If in timeout SNMP server send
348 back query, result is @true. If is used SNMPv3, then it synchronize self
349 with SNMPv3 agent first. (It is needed for SNMPv3 auhorization!)}
350 function SendRequest: Boolean;
351
352 {:Send SNMP packet only, but not waits for reply. Good for sending traps.}
353 function SendTrap: Boolean;
354
355 {:Receive SNMP packet only. Good for receiving traps.}
356 function RecvTrap: Boolean;
357
358 {:Mapped to @link(SendRequest) internally. This function is only for
359 backward compatibility.}
360 function DoIt: Boolean;
361 published
362 {:contains raw binary form of SNMP packet. Good for debugging.}
363 property Buffer: AnsiString read FBuffer write FBuffer;
364
365 {:After SNMP operation hold IP address of remote side.}
366 property HostIP: AnsiString read FHostIP;
367
368 {:Data object contains SNMP query.}
369 property Query: TSNMPRec read FQuery;
370
371 {:Data object contains SNMP reply.}
372 property Reply: TSNMPRec read FReply;
373
374 {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
375 property Sock: TUDPBlockSocket read FSock;
376 end;
377
378{:A very useful function and example of its use would be found in the TSNMPSend
379 object. It implements basic GET method of the SNMP protocol. The MIB value is
380 located in the "OID" variable, and is sent to the requested "SNMPHost" with
381 the proper "Community" access identifier. Upon a successful retrieval, "Value"
382 will contain the information requested. If the SNMP operation is successful,
383 the result returns @true.}
384function SNMPGet(const OID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
385
386{:This is useful function and example of use TSNMPSend object. It implements
387 the basic SET method of the SNMP protocol. If the SNMP operation is successful,
388 the result is @true. "Value" is value of MIB Oid for "SNMPHost" with "Community"
389 access identifier. You must specify "ValueType" too.}
390function SNMPSet(const OID, Community, SNMPHost, Value: AnsiString; ValueType: Integer): Boolean;
391
392{:A very useful function and example of its use would be found in the TSNMPSend
393 object. It implements basic GETNEXT method of the SNMP protocol. The MIB value
394 is located in the "OID" variable, and is sent to the requested "SNMPHost" with
395 the proper "Community" access identifier. Upon a successful retrieval, "Value"
396 will contain the information requested. If the SNMP operation is successful,
397 the result returns @true.}
398function SNMPGetNext(var OID: AnsiString; const Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
399
400{:A very useful function and example of its use would be found in the TSNMPSend
401 object. It implements basic read of SNMP MIB tables. As BaseOID you must
402 specify basic MIB OID of requested table (base IOD is OID without row and
403 column specificator!)
404 Table is readed into stringlist, where each string is comma delimited string.
405
406 Warning: this function is not have best performance. For better performance
407 you must write your own function. best performace you can get by knowledge
408 of structuture of table and by more then one MIB on one query. }
409function SNMPGetTable(const BaseOID, Community, SNMPHost: AnsiString; const Value: TStrings): Boolean;
410
411{:A very useful function and example of its use would be found in the TSNMPSend
412 object. It implements basic read of SNMP MIB table element. As BaseOID you must
413 specify basic MIB OID of requested table (base IOD is OID without row and
414 column specificator!)
415 As next you must specify identificator of row and column for specify of needed
416 field of table.}
417function SNMPGetTableElement(const BaseOID, RowID, ColID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
418
419{:A very useful function and example of its use would be found in the TSNMPSend
420 object. It implements a TRAPv1 to send with all data in the parameters.}
421function SendTrap(const Dest, Source, Enterprise, Community: AnsiString;
422 Generic, Specific, Seconds: Integer; const MIBName, MIBValue: AnsiString;
423 MIBtype: Integer): Integer;
424
425{:A very useful function and example of its use would be found in the TSNMPSend
426 object. It receives a TRAPv1 and returns all the data that comes with it.}
427function RecvTrap(var Dest, Source, Enterprise, Community: AnsiString;
428 var Generic, Specific, Seconds: Integer; const MIBName,
429 MIBValue: TStringList): Integer;
430
431implementation
432
433{==============================================================================}
434
435constructor TSNMPRec.Create;
436begin
437 inherited Create;
438 FSNMPMibList := TList.Create;
439 Clear;
440 FAuthMode := AuthMD5;
441 FPassword := '';
442 FPrivMode := PrivDES;
443 FPrivPassword := '';
444 FID := 1;
445 FMaxSize := 1472;
446end;
447
448destructor TSNMPRec.Destroy;
449var
450 i: Integer;
451begin
452 for i := 0 to FSNMPMibList.Count - 1 do
453 TSNMPMib(FSNMPMibList[i]).Free;
454 FSNMPMibList.Clear;
455 FSNMPMibList.Free;
456 inherited Destroy;
457end;
458
459function TSNMPRec.Pass2Key(const Value: AnsiString): AnsiString;
460var
461 key: AnsiString;
462begin
463 case FAuthMode of
464 AuthMD5:
465 begin
466 key := MD5LongHash(Value, 1048576);
467 Result := MD5(key + FAuthEngineID + key);
468 end;
469 AuthSHA1:
470 begin
471 key := SHA1LongHash(Value, 1048576);
472 Result := SHA1(key + FAuthEngineID + key);
473 end;
474 else
475 Result := '';
476 end;
477end;
478
479function TSNMPRec.DecryptPDU(const value: AnsiString): AnsiString;
480var
481 des: TSynaDes;
482 des3: TSyna3Des;
483 aes: TSynaAes;
484 s: string;
485begin
486 FPrivKey := '';
487 if FFlags <> AuthPriv then
488 Result := value
489 else
490 begin
491 case FPrivMode of
492 Priv3DES:
493 begin
494 FPrivKey := Pass2Key(FPrivPassword);
495 FPrivKey := FPrivKey + Pass2Key(FPrivKey);
496 des3 := TSyna3Des.Create(PadString(FPrivKey, 24, #0));
497 try
498 s := PadString(FPrivKey, 32, #0);
499 delete(s, 1, 24);
500 des3.SetIV(xorstring(s, FPrivSalt));
501 s := des3.DecryptCBC(value);
502 Result := s;
503 finally
504 des3.free;
505 end;
506 end;
507 PrivAES:
508 begin
509 FPrivKey := Pass2Key(FPrivPassword);
510 aes := TSynaAes.Create(PadString(FPrivKey, 16, #0));
511 try
512 s := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FAuthEngineTime) + FPrivSalt;
513 aes.SetIV(s);
514 s := aes.DecryptCFBblock(value);
515 Result := s;
516 finally
517 aes.free;
518 end;
519 end;
520 else //PrivDES as default
521 begin
522 FPrivKey := Pass2Key(FPrivPassword);
523 des := TSynaDes.Create(PadString(FPrivKey, 8, #0));
524 try
525 s := PadString(FPrivKey, 16, #0);
526 delete(s, 1, 8);
527 des.SetIV(xorstring(s, FPrivSalt));
528 s := des.DecryptCBC(value);
529 Result := s;
530 finally
531 des.free;
532 end;
533 end;
534 end;
535 end;
536end;
537
538function TSNMPRec.DecodeBuf(Buffer: AnsiString): Boolean;
539var
540 Pos: Integer;
541 EndPos: Integer;
542 sm, sv: AnsiString;
543 Svt: Integer;
544 s: AnsiString;
545 Spos: integer;
546 x: Byte;
547begin
548 Clear;
549 Result := False;
550 if Length(Buffer) < 2 then
551 Exit;
552 if (Ord(Buffer[1]) and $20) = 0 then
553 Exit;
554 Pos := 2;
555 EndPos := ASNDecLen(Pos, Buffer);
556 if Length(Buffer) < (EndPos + 2) then
557 Exit;
558 Self.FVersion := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
559
560 if FVersion = 3 then
561 begin
562 ASNItem(Pos, Buffer, Svt); //header data seq
563 ASNItem(Pos, Buffer, Svt); //ID
564 FMaxSize := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
565 s := ASNItem(Pos, Buffer, Svt);
566 x := 0;
567 if s <> '' then
568 x := Ord(s[1]);
569 FFlagReportable := (x and 4) > 0;
570 x := x and 3;
571 case x of
572 1:
573 FFlags := AuthNoPriv;
574 3:
575 FFlags := AuthPriv;
576 else
577 FFlags := NoAuthNoPriv;
578 end;
579
580 x := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
581 s := ASNItem(Pos, Buffer, Svt); //SecurityParameters
582 //if SecurityModel is USM, then try to decode SecurityParameters
583 if (x = 3) and (s <> '') then
584 begin
585 spos := 1;
586 ASNItem(SPos, s, Svt);
587 FAuthEngineID := ASNItem(SPos, s, Svt);
588 FAuthEngineBoots := StrToIntDef(ASNItem(SPos, s, Svt), 0);
589 FAuthEngineTime := StrToIntDef(ASNItem(SPos, s, Svt), 0);
590 FAuthEngineTimeStamp := GetTick;
591 FUserName := ASNItem(SPos, s, Svt);
592 FAuthKey := ASNItem(SPos, s, Svt);
593 FPrivSalt := ASNItem(SPos, s, Svt);
594 end;
595 //scopedPDU
596 if FFlags = AuthPriv then
597 begin
598 x := Pos;
599 s := ASNItem(Pos, Buffer, Svt);
600 if Svt <> ASN1_OCTSTR then
601 exit;
602 s := DecryptPDU(s);
603 //replace encoded content by decoded version and continue
604 Buffer := copy(Buffer, 1, x - 1);
605 Buffer := Buffer + s;
606 Pos := x;
607 if length(Buffer) < EndPos then
608 EndPos := length(buffer);
609 end;
610 ASNItem(Pos, Buffer, Svt); //skip sequence mark
611 FContextEngineID := ASNItem(Pos, Buffer, Svt);
612 FContextName := ASNItem(Pos, Buffer, Svt);
613 end
614 else
615 begin
616 //old packet
617 Self.FCommunity := ASNItem(Pos, Buffer, Svt);
618 end;
619
620 ASNItem(Pos, Buffer, Svt);
621 Self.FPDUType := Svt;
622 if Self.FPDUType = PDUTrap then
623 begin
624 FOldTrapEnterprise := ASNItem(Pos, Buffer, Svt);
625 FOldTrapHost := ASNItem(Pos, Buffer, Svt);
626 FOldTrapGen := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
627 FOldTrapSpec := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
628 FOldTrapTimeTicks := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
629 end
630 else
631 begin
632 Self.FID := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
633 Self.FErrorStatus := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
634 Self.FErrorIndex := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
635 end;
636 ASNItem(Pos, Buffer, Svt);
637 while Pos < EndPos do
638 begin
639 ASNItem(Pos, Buffer, Svt);
640 Sm := ASNItem(Pos, Buffer, Svt);
641 Sv := ASNItem(Pos, Buffer, Svt);
642 if sm <> '' then
643 Self.MIBAdd(sm, sv, Svt);
644 end;
645 Result := True;
646end;
647
648function TSNMPRec.EncryptPDU(const value: AnsiString): AnsiString;
649var
650 des: TSynaDes;
651 des3: TSyna3Des;
652 aes: TSynaAes;
653 s: string;
654 x: integer;
655begin
656 FPrivKey := '';
657 if FFlags <> AuthPriv then
658 Result := Value
659 else
660 begin
661 case FPrivMode of
662 Priv3DES:
663 begin
664 FPrivKey := Pass2Key(FPrivPassword);
665 FPrivKey := FPrivKey + Pass2Key(FPrivKey);
666 des3 := TSyna3Des.Create(PadString(FPrivKey, 24, #0));
667 try
668 s := PadString(FPrivKey, 32, #0);
669 delete(s, 1, 24);
670 FPrivSalt := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FPrivSaltCounter);
671 inc(FPrivSaltCounter);
672 s := xorstring(s, FPrivSalt);
673 des3.SetIV(s);
674 x := length(value) mod 8;
675 x := 8 - x;
676 if x = 8 then
677 x := 0;
678 s := des3.EncryptCBC(value + Stringofchar(#0, x));
679 Result := ASNObject(s, ASN1_OCTSTR);
680 finally
681 des3.free;
682 end;
683 end;
684 PrivAES:
685 begin
686 FPrivKey := Pass2Key(FPrivPassword);
687 aes := TSynaAes.Create(PadString(FPrivKey, 16, #0));
688 try
689 FPrivSalt := CodeLongInt(0) + CodeLongInt(FPrivSaltCounter);
690 inc(FPrivSaltCounter);
691 s := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FAuthEngineTime) + FPrivSalt;
692 aes.SetIV(s);
693 s := aes.EncryptCFBblock(value);
694 Result := ASNObject(s, ASN1_OCTSTR);
695 finally
696 aes.free;
697 end;
698 end;
699 else //PrivDES as default
700 begin
701 FPrivKey := Pass2Key(FPrivPassword);
702 des := TSynaDes.Create(PadString(FPrivKey, 8, #0));
703 try
704 s := PadString(FPrivKey, 16, #0);
705 delete(s, 1, 8);
706 FPrivSalt := CodeLongInt(FAuthEngineBoots) + CodeLongInt(FPrivSaltCounter);
707 inc(FPrivSaltCounter);
708 s := xorstring(s, FPrivSalt);
709 des.SetIV(s);
710 x := length(value) mod 8;
711 x := 8 - x;
712 if x = 8 then
713 x := 0;
714 s := des.EncryptCBC(value + Stringofchar(#0, x));
715 Result := ASNObject(s, ASN1_OCTSTR);
716 finally
717 des.free;
718 end;
719 end;
720 end;
721 end;
722end;
723
724function TSNMPRec.EncodeBuf: AnsiString;
725var
726 s: AnsiString;
727 SNMPMib: TSNMPMib;
728 n: Integer;
729 pdu, head, auth, authbeg: AnsiString;
730 x: Byte;
731begin
732 pdu := '';
733 for n := 0 to FSNMPMibList.Count - 1 do
734 begin
735 SNMPMib := TSNMPMib(FSNMPMibList[n]);
736 case SNMPMib.ValueType of
737 ASN1_INT:
738 s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
739 ASNObject(ASNEncInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType);
740 ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
741 s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
742 ASNObject(ASNEncUInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType);
743 ASN1_OBJID:
744 s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
745 ASNObject(MibToID(SNMPMib.Value), SNMPMib.ValueType);
746 ASN1_IPADDR:
747 s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
748 ASNObject(IPToID(SNMPMib.Value), SNMPMib.ValueType);
749 ASN1_NULL:
750 s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
751 ASNObject('', ASN1_NULL);
752 else
753 s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
754 ASNObject(SNMPMib.Value, SNMPMib.ValueType);
755 end;
756 pdu := pdu + ASNObject(s, ASN1_SEQ);
757 end;
758 pdu := ASNObject(pdu, ASN1_SEQ);
759
760 if Self.FPDUType = PDUTrap then
761 pdu := ASNObject(MibToID(FOldTrapEnterprise), ASN1_OBJID) +
762 ASNObject(IPToID(FOldTrapHost), ASN1_IPADDR) +
763 ASNObject(ASNEncInt(FOldTrapGen), ASN1_INT) +
764 ASNObject(ASNEncInt(FOldTrapSpec), ASN1_INT) +
765 ASNObject(ASNEncUInt(FOldTrapTimeTicks), ASN1_TIMETICKS) +
766 pdu
767 else
768 pdu := ASNObject(ASNEncInt(Self.FID), ASN1_INT) +
769 ASNObject(ASNEncInt(Self.FErrorStatus), ASN1_INT) +
770 ASNObject(ASNEncInt(Self.FErrorIndex), ASN1_INT) +
771 pdu;
772 pdu := ASNObject(pdu, Self.FPDUType);
773
774 if FVersion = 3 then
775 begin
776 if FContextEngineID = '' then
777 FContextEngineID := FAuthEngineID;
778 //complete PDUv3...
779 pdu := ASNObject(FContextEngineID, ASN1_OCTSTR)
780 + ASNObject(FContextName, ASN1_OCTSTR)
781 + pdu;
782 pdu := ASNObject(pdu, ASN1_SEQ);
783 //encrypt PDU if Priv mode is enabled
784 pdu := EncryptPDU(pdu);
785
786 //prepare flags
787 case FFlags of
788 AuthNoPriv:
789 x := 1;
790 AuthPriv:
791 x := 3;
792 else
793 x := 0;
794 end;
795 if FFlagReportable then
796 x := x or 4;
797 head := ASNObject(ASNEncInt(Self.FVersion), ASN1_INT);
798 s := ASNObject(ASNEncInt(FID), ASN1_INT)
799 + ASNObject(ASNEncInt(FMaxSize), ASN1_INT)
800 + ASNObject(AnsiChar(x), ASN1_OCTSTR)
801 //encode security model USM
802 + ASNObject(ASNEncInt(3), ASN1_INT);
803 head := head + ASNObject(s, ASN1_SEQ);
804
805 //compute engine time difference
806 if FAuthEngineTimeStamp = 0 then //out of sync
807 x := 0
808 else
809 x := TickDelta(FAuthEngineTimeStamp, GetTick) div 1000;
810
811 authbeg := ASNObject(FAuthEngineID, ASN1_OCTSTR)
812 + ASNObject(ASNEncInt(FAuthEngineBoots), ASN1_INT)
813 + ASNObject(ASNEncInt(FAuthEngineTime + x), ASN1_INT)
814 + ASNObject(FUserName, ASN1_OCTSTR);
815
816
817 case FFlags of
818 AuthNoPriv,
819 AuthPriv:
820 begin
821 s := authbeg + ASNObject(StringOfChar(#0, 12), ASN1_OCTSTR)
822 + ASNObject(FPrivSalt, ASN1_OCTSTR);
823 s := ASNObject(s, ASN1_SEQ);
824 s := head + ASNObject(s, ASN1_OCTSTR);
825 s := ASNObject(s + pdu, ASN1_SEQ);
826 //in s is entire packet without auth info...
827 case FAuthMode of
828 AuthMD5:
829 begin
830 s := HMAC_MD5(s, Pass2Key(FPassword) + StringOfChar(#0, 48));
831 //strip to HMAC-MD5-96
832 delete(s, 13, 4);
833 end;
834 AuthSHA1:
835 begin
836 s := HMAC_SHA1(s, Pass2Key(FPassword) + StringOfChar(#0, 44));
837 //strip to HMAC-SHA-96
838 delete(s, 13, 8);
839 end;
840 else
841 s := '';
842 end;
843 FAuthKey := s;
844 end;
845 end;
846
847 auth := authbeg + ASNObject(FAuthKey, ASN1_OCTSTR)
848 + ASNObject(FPrivSalt, ASN1_OCTSTR);
849 auth := ASNObject(auth, ASN1_SEQ);
850
851 head := head + ASNObject(auth, ASN1_OCTSTR);
852 Result := ASNObject(head + pdu, ASN1_SEQ);
853 end
854 else
855 begin
856 head := ASNObject(ASNEncInt(Self.FVersion), ASN1_INT) +
857 ASNObject(Self.FCommunity, ASN1_OCTSTR);
858 Result := ASNObject(head + pdu, ASN1_SEQ);
859 end;
860 inc(self.FID);
861end;
862
863procedure TSNMPRec.Clear;
864var
865 i: Integer;
866begin
867 FVersion := SNMP_V1;
868 FCommunity := 'public';
869 FUserName := '';
870 FPDUType := 0;
871 FErrorStatus := 0;
872 FErrorIndex := 0;
873 for i := 0 to FSNMPMibList.Count - 1 do
874 TSNMPMib(FSNMPMibList[i]).Free;
875 FSNMPMibList.Clear;
876 FOldTrapEnterprise := '';
877 FOldTrapHost := '';
878 FOldTrapGen := 0;
879 FOldTrapSpec := 0;
880 FOldTrapTimeTicks := 0;
881 FFlags := NoAuthNoPriv;
882 FFlagReportable := false;
883 FContextEngineID := '';
884 FContextName := '';
885 FAuthEngineID := '';
886 FAuthEngineBoots := 0;
887 FAuthEngineTime := 0;
888 FAuthEngineTimeStamp := 0;
889 FAuthKey := '';
890 FPrivKey := '';
891 FPrivSalt := '';
892 FPrivSaltCounter := random(maxint);
893end;
894
895procedure TSNMPRec.MIBAdd(const MIB, Value: AnsiString; ValueType: Integer);
896var
897 SNMPMib: TSNMPMib;
898begin
899 SNMPMib := TSNMPMib.Create;
900 SNMPMib.OID := MIB;
901 SNMPMib.Value := Value;
902 SNMPMib.ValueType := ValueType;
903 FSNMPMibList.Add(SNMPMib);
904end;
905
906procedure TSNMPRec.MIBDelete(Index: Integer);
907begin
908 if (Index >= 0) and (Index < MIBCount) then
909 begin
910 TSNMPMib(FSNMPMibList[Index]).Free;
911 FSNMPMibList.Delete(Index);
912 end;
913end;
914
915function TSNMPRec.MIBCount: integer;
916begin
917 Result := FSNMPMibList.Count;
918end;
919
920function TSNMPRec.MIBByIndex(Index: Integer): TSNMPMib;
921begin
922 Result := nil;
923 if (Index >= 0) and (Index < MIBCount) then
924 Result := TSNMPMib(FSNMPMibList[Index]);
925end;
926
927function TSNMPRec.MIBGet(const MIB: AnsiString): AnsiString;
928var
929 i: Integer;
930begin
931 Result := '';
932 for i := 0 to MIBCount - 1 do
933 begin
934 if ((TSNMPMib(FSNMPMibList[i])).OID = MIB) then
935 begin
936 Result := (TSNMPMib(FSNMPMibList[i])).Value;
937 Break;
938 end;
939 end;
940end;
941
942{==============================================================================}
943
944constructor TSNMPSend.Create;
945begin
946 inherited Create;
947 FQuery := TSNMPRec.Create;
948 FReply := TSNMPRec.Create;
949 FQuery.Clear;
950 FReply.Clear;
951 FSock := TUDPBlockSocket.Create;
952 FSock.Owner := self;
953 FTimeout := 5000;
954 FTargetPort := cSnmpProtocol;
955 FHostIP := '';
956end;
957
958destructor TSNMPSend.Destroy;
959begin
960 FSock.Free;
961 FReply.Free;
962 FQuery.Free;
963 inherited Destroy;
964end;
965
966function TSNMPSend.InternalSendSnmp(const Value: TSNMPRec): Boolean;
967begin
968 FBuffer := Value.EncodeBuf;
969 FSock.SendString(FBuffer);
970 Result := FSock.LastError = 0;
971end;
972
973function TSNMPSend.InternalRecvSnmp(const Value: TSNMPRec): Boolean;
974begin
975 Result := False;
976 FReply.Clear;
977 FHostIP := cAnyHost;
978 FBuffer := FSock.RecvPacket(FTimeout);
979 if FSock.LastError = 0 then
980 begin
981 FHostIP := FSock.GetRemoteSinIP;
982 Result := Value.DecodeBuf(FBuffer);
983 end;
984end;
985
986function TSNMPSend.InternalSendRequest(const QValue, RValue: TSNMPRec): Boolean;
987begin
988 Result := False;
989 RValue.AuthMode := QValue.AuthMode;
990 RValue.Password := QValue.Password;
991 RValue.PrivMode := QValue.PrivMode;
992 RValue.PrivPassword := QValue.PrivPassword;
993 FSock.Bind(FIPInterface, cAnyPort);
994 FSock.Connect(FTargetHost, FTargetPort);
995 if InternalSendSnmp(QValue) then
996 Result := InternalRecvSnmp(RValue);
997end;
998
999function TSNMPSend.SendRequest: Boolean;
1000var
1001 sync: TV3Sync;
1002begin
1003 Result := False;
1004 if FQuery.FVersion = 3 then
1005 begin
1006 sync := GetV3Sync;
1007 FQuery.AuthEngineBoots := Sync.EngineBoots;
1008 FQuery.AuthEngineTime := Sync.EngineTime;
1009 FQuery.AuthEngineTimeStamp := Sync.EngineStamp;
1010 FQuery.AuthEngineID := Sync.EngineID;
1011 end;
1012 Result := InternalSendRequest(FQuery, FReply);
1013end;
1014
1015function TSNMPSend.SendTrap: Boolean;
1016begin
1017 FSock.Bind(FIPInterface, cAnyPort);
1018 FSock.Connect(FTargetHost, FTargetPort);
1019 Result := InternalSendSnmp(FQuery);
1020end;
1021
1022function TSNMPSend.RecvTrap: Boolean;
1023begin
1024 FSock.Bind(FIPInterface, FTargetPort);
1025 Result := InternalRecvSnmp(FReply);
1026end;
1027
1028function TSNMPSend.DoIt: Boolean;
1029begin
1030 Result := SendRequest;
1031end;
1032
1033function TSNMPSend.GetV3EngineID: AnsiString;
1034var
1035 DisQuery: TSNMPRec;
1036begin
1037 Result := '';
1038 DisQuery := TSNMPRec.Create;
1039 try
1040 DisQuery.Version := 3;
1041 DisQuery.UserName := '';
1042 DisQuery.FlagReportable := True;
1043 DisQuery.PDUType := PDUGetRequest;
1044 if InternalSendRequest(DisQuery, FReply) then
1045 Result := FReply.FAuthEngineID;
1046 finally
1047 DisQuery.Free;
1048 end;
1049end;
1050
1051function TSNMPSend.GetV3Sync: TV3Sync;
1052var
1053 SyncQuery: TSNMPRec;
1054begin
1055 Result.EngineID := GetV3EngineID;
1056 Result.EngineBoots := FReply.AuthEngineBoots;
1057 Result.EngineTime := FReply.AuthEngineTime;
1058 Result.EngineStamp := FReply.AuthEngineTimeStamp;
1059 if Result.EngineTime = 0 then
1060 begin
1061 //still not have sync...
1062 SyncQuery := TSNMPRec.Create;
1063 try
1064 SyncQuery.Version := 3;
1065 SyncQuery.UserName := FQuery.UserName;
1066 SyncQuery.Password := FQuery.Password;
1067 SyncQuery.FlagReportable := True;
1068 SyncQuery.Flags := FQuery.Flags;
1069 SyncQuery.AuthMode := FQuery.AuthMode;
1070 SyncQuery.PrivMode := FQuery.PrivMode;
1071 SyncQuery.PrivPassword := FQuery.PrivPassword;
1072 SyncQuery.PDUType := PDUGetRequest;
1073 SyncQuery.AuthEngineID := FReply.FAuthEngineID;
1074 if InternalSendRequest(SyncQuery, FReply) then
1075 begin
1076 Result.EngineBoots := FReply.AuthEngineBoots;
1077 Result.EngineTime := FReply.AuthEngineTime;
1078 Result.EngineStamp := FReply.AuthEngineTimeStamp;
1079 end;
1080 finally
1081 SyncQuery.Free;
1082 end;
1083 end;
1084end;
1085
1086{==============================================================================}
1087
1088function SNMPGet(const OID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
1089var
1090 SNMPSend: TSNMPSend;
1091begin
1092 SNMPSend := TSNMPSend.Create;
1093 try
1094 SNMPSend.Query.Clear;
1095 SNMPSend.Query.Community := Community;
1096 SNMPSend.Query.PDUType := PDUGetRequest;
1097 SNMPSend.Query.MIBAdd(OID, '', ASN1_NULL);
1098 SNMPSend.TargetHost := SNMPHost;
1099 Result := SNMPSend.SendRequest;
1100 Value := '';
1101 if Result then
1102 Value := SNMPSend.Reply.MIBGet(OID);
1103 finally
1104 SNMPSend.Free;
1105 end;
1106end;
1107
1108function SNMPSet(const OID, Community, SNMPHost, Value: AnsiString; ValueType: Integer): Boolean;
1109var
1110 SNMPSend: TSNMPSend;
1111begin
1112 SNMPSend := TSNMPSend.Create;
1113 try
1114 SNMPSend.Query.Clear;
1115 SNMPSend.Query.Community := Community;
1116 SNMPSend.Query.PDUType := PDUSetRequest;
1117 SNMPSend.Query.MIBAdd(OID, Value, ValueType);
1118 SNMPSend.TargetHost := SNMPHost;
1119 Result := SNMPSend.Sendrequest = True;
1120 finally
1121 SNMPSend.Free;
1122 end;
1123end;
1124
1125function InternalGetNext(const SNMPSend: TSNMPSend; var OID: AnsiString;
1126 const Community: AnsiString; var Value: AnsiString): Boolean;
1127begin
1128 SNMPSend.Query.Clear;
1129 SNMPSend.Query.ID := SNMPSend.Query.ID + 1;
1130 SNMPSend.Query.Community := Community;
1131 SNMPSend.Query.PDUType := PDUGetNextRequest;
1132 SNMPSend.Query.MIBAdd(OID, '', ASN1_NULL);
1133 Result := SNMPSend.Sendrequest;
1134 Value := '';
1135 if Result then
1136 if SNMPSend.Reply.SNMPMibList.Count > 0 then
1137 begin
1138 OID := TSNMPMib(SNMPSend.Reply.SNMPMibList[0]).OID;
1139 Value := TSNMPMib(SNMPSend.Reply.SNMPMibList[0]).Value;
1140 end;
1141end;
1142
1143function SNMPGetNext(var OID: AnsiString; const Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
1144var
1145 SNMPSend: TSNMPSend;
1146begin
1147 SNMPSend := TSNMPSend.Create;
1148 try
1149 SNMPSend.TargetHost := SNMPHost;
1150 Result := InternalGetNext(SNMPSend, OID, Community, Value);
1151 finally
1152 SNMPSend.Free;
1153 end;
1154end;
1155
1156function SNMPGetTable(const BaseOID, Community, SNMPHost: AnsiString; const Value: TStrings): Boolean;
1157var
1158 OID: AnsiString;
1159 s: AnsiString;
1160 col,row: String;
1161 x: integer;
1162 SNMPSend: TSNMPSend;
1163 RowList: TStringList;
1164begin
1165 Value.Clear;
1166 SNMPSend := TSNMPSend.Create;
1167 RowList := TStringList.Create;
1168 try
1169 SNMPSend.TargetHost := SNMPHost;
1170 OID := BaseOID;
1171 repeat
1172 Result := InternalGetNext(SNMPSend, OID, Community, s);
1173 if Pos(BaseOID, OID) <> 1 then
1174 break;
1175 row := separateright(oid, baseoid + '.');
1176 col := fetch(row, '.');
1177
1178 if IsBinaryString(s) then
1179 s := StrToHex(s);
1180 x := RowList.indexOf(Row);
1181 if x < 0 then
1182 begin
1183 x := RowList.add(Row);
1184 Value.Add('');
1185 end;
1186 if (Value[x] <> '') then
1187 Value[x] := Value[x] + ',';
1188 Value[x] := Value[x] + AnsiQuotedStr(s, '"');
1189 until not result;
1190 finally
1191 SNMPSend.Free;
1192 RowList.Free;
1193 end;
1194end;
1195
1196function SNMPGetTableElement(const BaseOID, RowID, ColID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
1197var
1198 s: AnsiString;
1199begin
1200 s := BaseOID + '.' + ColID + '.' + RowID;
1201 Result := SnmpGet(s, Community, SNMPHost, Value);
1202end;
1203
1204function SendTrap(const Dest, Source, Enterprise, Community: AnsiString;
1205 Generic, Specific, Seconds: Integer; const MIBName, MIBValue: AnsiString;
1206 MIBtype: Integer): Integer;
1207var
1208 SNMPSend: TSNMPSend;
1209begin
1210 SNMPSend := TSNMPSend.Create;
1211 try
1212 SNMPSend.TargetHost := Dest;
1213 SNMPSend.TargetPort := cSnmpTrapProtocol;
1214 SNMPSend.Query.Community := Community;
1215 SNMPSend.Query.Version := SNMP_V1;
1216 SNMPSend.Query.PDUType := PDUTrap;
1217 SNMPSend.Query.OldTrapHost := Source;
1218 SNMPSend.Query.OldTrapEnterprise := Enterprise;
1219 SNMPSend.Query.OldTrapGen := Generic;
1220 SNMPSend.Query.OldTrapSpec := Specific;
1221 SNMPSend.Query.OldTrapTimeTicks := Seconds;
1222 SNMPSend.Query.MIBAdd(MIBName, MIBValue, MIBType);
1223 Result := Ord(SNMPSend.SendTrap);
1224 finally
1225 SNMPSend.Free;
1226 end;
1227end;
1228
1229function RecvTrap(var Dest, Source, Enterprise, Community: AnsiString;
1230 var Generic, Specific, Seconds: Integer;
1231 const MIBName, MIBValue: TStringList): Integer;
1232var
1233 SNMPSend: TSNMPSend;
1234 i: Integer;
1235begin
1236 SNMPSend := TSNMPSend.Create;
1237 try
1238 Result := 0;
1239 SNMPSend.TargetPort := cSnmpTrapProtocol;
1240 if SNMPSend.RecvTrap then
1241 begin
1242 Result := 1;
1243 Dest := SNMPSend.HostIP;
1244 Community := SNMPSend.Reply.Community;
1245 Source := SNMPSend.Reply.OldTrapHost;
1246 Enterprise := SNMPSend.Reply.OldTrapEnterprise;
1247 Generic := SNMPSend.Reply.OldTrapGen;
1248 Specific := SNMPSend.Reply.OldTrapSpec;
1249 Seconds := SNMPSend.Reply.OldTrapTimeTicks;
1250 MIBName.Clear;
1251 MIBValue.Clear;
1252 for i := 0 to SNMPSend.Reply.SNMPMibList.Count - 1 do
1253 begin
1254 MIBName.Add(TSNMPMib(SNMPSend.Reply.SNMPMibList[i]).OID);
1255 MIBValue.Add(TSNMPMib(SNMPSend.Reply.SNMPMibList[i]).Value);
1256 end;
1257 end;
1258 finally
1259 SNMPSend.Free;
1260 end;
1261end;
1262
1263
1264end.
1265
1266
Note: See TracBrowser for help on using the repository browser.