IdSNMP.pas 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.3 10/26/2004 11:08:04 PM JPMugaas
  18. Updated refs.
  19. Rev 1.2 2004.02.03 5:44:22 PM czhower
  20. Name changes
  21. Rev 1.1 1/21/2004 4:03:36 PM JPMugaas
  22. InitComponent
  23. Rev 1.0 11/13/2002 08:01:02 AM JPMugaas
  24. }
  25. unit IdSNMP;
  26. {
  27. -2001.02.13 - Kudzu - Misc "Indy" Changes.
  28. -Contributions also by: Hernan Sanchez ([email protected])
  29. -Original Author: Lukas Gebauer
  30. The Synapse SNMP component was converted for use in INDY.
  31. | The Original Code is Synapse Delphi Library. |
  32. |==============================================================================|
  33. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  34. | Portions created by Lukas Gebauer are Copyright (c)2000. |
  35. | All Rights Reserved. |
  36. |==============================================================================|
  37. | Contributor(s): |
  38. | Hernan Sanchez ([email protected]) Original author |
  39. | Colin Wilson ([email protected]) Fixed some bugs & added support |
  40. | for Value types |
  41. | Remy Lebeau ([email protected]) Added support for Unicode and |
  42. | Generics |
  43. |==============================================================================|
  44. | History: see HISTORY.HTM from distribution package |
  45. | (Found at URL: http://www.ararat.cz/synapse/) |
  46. |==============================================================================|
  47. }
  48. interface
  49. {$i IdCompilerDefines.inc}
  50. uses
  51. Classes,
  52. {$IFDEF HAS_UNIT_Generics_Collections}
  53. System.Generics.Collections,
  54. {$ENDIF}
  55. IdASN1Util,
  56. IdGlobal,
  57. IdUDPBase,
  58. IdUDPClient,
  59. IdSocketHandle;
  60. const
  61. //PDU type
  62. PDUGetRequest = $a0;
  63. PDUGetNextRequest = $a1;
  64. PDUGetResponse = $a2;
  65. PDUSetRequest = $a3;
  66. PDUTrap = $a4;
  67. //errors
  68. ENoError = 0;
  69. ETooBig = 1;
  70. ENoSuchName = 2;
  71. EBadValue = 3;
  72. EReadOnly = 4;
  73. EGenErr = 5;
  74. type
  75. TIdSNMP = class;
  76. // TODO: create TIdMIBValueList for non-Generics compilers...
  77. {$IFDEF HAS_GENERICS_TList}
  78. TIdMIBValue = record
  79. OID: String;
  80. Value: String;
  81. ValueType: Integer;
  82. constructor Create(const AOID, AValue: String; const AValueType: Integer);
  83. end;
  84. TIdMIBValueList = TList<TIdMIBValue>;
  85. {$ENDIF}
  86. TSNMPInfo = class(TObject)
  87. private
  88. {$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} fOwner : TIdSNMP;
  89. fCommunity: string;
  90. function GetValue (idx : Integer) : string;
  91. function GetValueCount: Integer;
  92. function GetValueType (idx : Integer) : Integer;
  93. function GetValueOID(idx: Integer): string;
  94. procedure SetCommunity(const Value: string);
  95. protected
  96. Buffer: string;
  97. {$IFNDEF HAS_GENERICS_TList}
  98. procedure SyncMIB;
  99. {$ENDIF}
  100. public
  101. Host : string;
  102. Port : TIdPort;
  103. Enterprise: string;
  104. GenTrap: integer;
  105. SpecTrap: integer;
  106. Version : integer;
  107. PDUType : integer;
  108. TimeTicks : integer;
  109. ID : integer;
  110. ErrorStatus : integer;
  111. ErrorIndex : integer;
  112. {$IFDEF HAS_GENERICS_TList}
  113. MIBValues : TIdMIBValueList;
  114. {$ELSE}
  115. MIBOID : TStrings;
  116. MIBValue : TStrings;
  117. {$ENDIF}
  118. constructor Create (AOwner : TIdSNMP);
  119. destructor Destroy; override;
  120. function EncodeTrap: Boolean;
  121. function DecodeTrap: Boolean;
  122. procedure DecodeBuf(Buffer: string);
  123. function EncodeBuf: string;
  124. procedure Clear;
  125. procedure MIBAdd(MIB, Value: string; ValueType: Integer = ASN1_OCTSTR);
  126. procedure MIBDelete(Index: integer);
  127. function MIBGet(MIB: string): string;
  128. property Owner : TIdSNMP read fOwner;
  129. property Community : string read fCommunity write SetCommunity;
  130. property ValueCount : Integer read GetValueCount;
  131. property Value [idx : Integer] : string read GetValue;
  132. property ValueOID [idx : Integer] : string read GetValueOID;
  133. property ValueType [idx : Integer] : Integer read GetValueType;
  134. end;
  135. TIdSNMP = class(TIdUDPClient)
  136. protected
  137. fCommunity: string;
  138. fTrapPort: TIdPort;
  139. fTrapRecvBinding: TIdSocketHandle;
  140. procedure SetCommunity(const Value: string);
  141. procedure SetTrapPort(const AValue: TIdPort);
  142. procedure InitComponent; override;
  143. function GetBinding: TIdSocketHandle; override;
  144. procedure CloseBinding; override;
  145. public
  146. Query : TSNMPInfo;
  147. Reply : TSNMPInfo;
  148. Trap : TSNMPInfo;
  149. {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
  150. constructor Create(AOwner: TComponent); reintroduce; overload;
  151. {$ENDIF}
  152. destructor Destroy; override;
  153. function SendQuery : Boolean;
  154. function QuickSend(const Mib, DestCommunity, DestHost: string; var Value: string):Boolean;
  155. function QuickSendTrap(const DestHost, Enterprise, DestCommunity: string;
  156. DestPort: TIdPort; Generic, Specific: integer;
  157. {$IFDEF HAS_GENERICS_TList}
  158. MIBValues: TIdMIBValueList
  159. {$ELSE}
  160. MIBName, MIBValue: TStrings
  161. {$ENDIF}
  162. ): Boolean;
  163. function QuickReceiveTrap(var SrcHost, Enterprise, SrcCommunity: string;
  164. var SrcPort: TIdPort; var Generic, Specific, Seconds: integer;
  165. {$IFDEF HAS_GENERICS_TList}
  166. MIBValues: TIdMIBValueList
  167. {$ELSE}
  168. MIBName, MIBValue: TStrings
  169. {$ENDIF}
  170. ): Boolean;
  171. function SendTrap: Boolean;
  172. function ReceiveTrap: Boolean;
  173. published
  174. property Port default 161;
  175. property TrapPort : TIdPort read fTrapPort write SetTrapPort default 162;
  176. property Community : string read fCommunity write SetCommunity;
  177. end;
  178. implementation
  179. uses
  180. IdStack, IdStackConsts, SysUtils;
  181. //Hernan Sanchez
  182. function IPToID(Host: string): string;
  183. var
  184. s, t: string;
  185. i, x: integer;
  186. begin
  187. Result := ''; {Do not Localize}
  188. for x := 1 to 3 do
  189. begin
  190. t := ''; {Do not Localize}
  191. s := Copy(Host, IndyPos('.', Host), Length(Host)); {Do not Localize}
  192. t := Copy(Host, 1, (Length(Host) - Length(s)));
  193. Delete(Host, 1, (Length(Host) - Length(s) + 1));
  194. i := IndyStrToInt(t, 0);
  195. Result := Result + Chr(i);
  196. end;
  197. i := IndyStrToInt(Host, 0);
  198. Result := Result + Chr(i);
  199. end;
  200. function MibIntToASNObject(const OID: String; const Value: Integer; const ObjType: Integer = ASN1_INT): String;
  201. {$IFDEF USE_INLINE}inline;{$ENDIF}
  202. begin
  203. Result := ASNObject(MibToID(OID), ASN1_OBJID) + ASNObject(ASNEncInt(Value), ObjType);
  204. end;
  205. function MibUIntToASNObject(const OID: String; const Value, ObjType: Integer): String;
  206. {$IFDEF USE_INLINE}inline;{$ENDIF}
  207. begin
  208. Result := ASNObject(MibToID(OID), ASN1_OBJID) + ASNObject(ASNEncUInt(Value), ObjType);
  209. end;
  210. function MibObjIDToASNObject(const ObjID, Value: String): String;
  211. {$IFDEF USE_INLINE}inline;{$ENDIF}
  212. begin
  213. Result := ASNObject(MibToID(ObjID), ASN1_OBJID) + ASNObject(MibToID(Value), ASN1_OBJID);
  214. end;
  215. function MibIPAddrToASNObject(const OID, Value: String): String;
  216. {$IFDEF USE_INLINE}inline;{$ENDIF}
  217. begin
  218. Result := ASNObject(MibToID(OID), ASN1_OBJID) + ASNObject(IPToID(Value), ASN1_IPADDR);
  219. end;
  220. function MibNullToASNObject(const OID: String): String;
  221. {$IFDEF USE_INLINE}inline;{$ENDIF}
  222. begin
  223. Result := ASNObject(MibToID(OID), ASN1_OBJID) + ASNObject('', ASN1_NULL); {Do not Localize}
  224. end;
  225. function MibStrToASNObject(const OID, Value: String; const ObjType: Integer = ASN1_OCTSTR): String;
  226. {$IFDEF USE_INLINE}inline;{$ENDIF}
  227. begin
  228. Result := ASNObject(MibToID(OID), ASN1_OBJID) + ASNObject(Value, ObjType);
  229. end;
  230. {========================== SNMP INFO OBJECT ==================================}
  231. {$IFDEF HAS_GENERICS_TList}
  232. constructor TIdMIBValue.Create(const AOID, AValue: String; const AValueType: Integer);
  233. begin
  234. OID := AOID;
  235. Value := AValue;
  236. ValueType := AValueType;
  237. end;
  238. {$ENDIF}
  239. { TSNMPInfo }
  240. (*----------------------------------------------------------------------------*
  241. | constructor TSNMPInfo.Create () |
  242. | |
  243. | Constructor for TSNMPInfo |
  244. | |
  245. | Parameters: |
  246. | AOwner : TIdSNMP The owning IdSNMP Component |
  247. | |
  248. *----------------------------------------------------------------------------*)
  249. constructor TSNMPInfo.Create(AOwner : TIdSNMP);
  250. begin
  251. inherited Create;
  252. fOwner := AOwner;
  253. {$IFDEF HAS_GENERICS_TList}
  254. MIBValues := TIdMIBValueList.Create;
  255. {$ELSE}
  256. MIBOID := TStringList.Create;
  257. MIBValue := TStringList.Create;
  258. {$ENDIF}
  259. if fOwner <> nil then begin
  260. fCommunity := fOwner.Community;
  261. Port := fOwner.Port;
  262. end;
  263. end;
  264. (*----------------------------------------------------------------------------*
  265. | destructor TSNMPInfo.Destroy |
  266. | |
  267. | Destructor for TSNMPInfo |
  268. *----------------------------------------------------------------------------*)
  269. destructor TSNMPInfo.Destroy;
  270. begin
  271. {$IFDEF HAS_GENERICS_TList}
  272. FreeAndNil(MIBValues);
  273. {$ELSE}
  274. FreeAndNil(MIBValue);
  275. FreeAndNil(MIBOID);
  276. {$ENDIF}
  277. inherited Destroy;
  278. end;
  279. {$IFNDEF HAS_GENERICS_TList}
  280. (*----------------------------------------------------------------------------*
  281. | procedure TSNMPInfo.SyncMIB |
  282. | |
  283. | Ensure that there are as many 'values' as 'oids' |
  284. *----------------------------------------------------------------------------*)
  285. procedure TSNMPInfo.SyncMIB;
  286. var
  287. n,x: integer;
  288. begin
  289. x := MIBValue.Count;
  290. for n := x to MIBOID.Count-1 do begin
  291. MIBValue.Add('');
  292. end;
  293. end;
  294. {$ENDIF}
  295. (*----------------------------------------------------------------------------*
  296. | procedure TSNMPInfo.DecodeBuf |
  297. | |
  298. | Decode an ASN buffer into version, community, MIB OID/Value pairs, etc. |
  299. | |
  300. | Parameters: |
  301. | Buffer:string The ASN buffer to decode |
  302. *----------------------------------------------------------------------------*)
  303. procedure TSNMPInfo.DecodeBuf(Buffer: string);
  304. var
  305. Pos: integer;
  306. endpos,vt: integer;
  307. sm,sv: string;
  308. begin
  309. Pos := 2;
  310. Endpos := ASNDecLen(Pos, Buffer);
  311. Version := IndyStrToInt(ASNItem(Pos,Buffer,vt),0);
  312. Community := ASNItem(Pos,buffer,vt);
  313. PDUType := IndyStrToInt(ASNItem(Pos,Buffer,vt),0);
  314. ID := IndyStrToInt(ASNItem(Pos,Buffer,vt),0);
  315. ErrorStatus := IndyStrToInt(ASNItem(Pos,Buffer,vt),0);
  316. ErrorIndex := IndyStrToInt(ASNItem(Pos,Buffer,vt),0);
  317. ASNItem(Pos, Buffer, vt);
  318. while Pos < Endpos do // Decode MIB/Value pairs
  319. begin
  320. ASNItem(Pos, Buffer, vt);
  321. Sm := ASNItem(Pos, Buffer, vt);
  322. Sv := ASNItem(Pos, Buffer, vt);
  323. MIBAdd(sm, sv, vt);
  324. end;
  325. end;
  326. (*----------------------------------------------------------------------------*
  327. | function TSNMPInfo.EncodeBuf |
  328. | |
  329. | Encode the details into an ASN string |
  330. | |
  331. | The function returns the encoded ASN string |
  332. *----------------------------------------------------------------------------*)
  333. function TSNMPInfo.EncodeBuf: string;
  334. var
  335. data,s: string;
  336. n: integer;
  337. objType: Integer;
  338. begin
  339. data := ''; {Do not Localize}
  340. {$IFNDEF HAS_GENERICS_TList}
  341. SyncMIB;
  342. {$ENDIF}
  343. for n := 0 to {$IFDEF HAS_GENERICS_TList}MIBValues{$ELSE}MIBOID{$ENDIF}.Count-1 do
  344. begin
  345. objType := GetValueType(n);
  346. case objType of
  347. ASN1_INT:
  348. s := MibIntToASNObject(GetValueOID(n), IndyStrToInt(GetValue(n), 0));
  349. ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
  350. s := MibUIntToASNObject(GetValueOID(n), IndyStrToInt(GetValue(n), 0), objType);
  351. ASN1_OBJID:
  352. s := MibObjIDToASNObject(GetValueOID(n), GetValue(n));
  353. ASN1_IPADDR:
  354. s := MibIPAddrToASNObject(GetValueOID(n), GetValue(n));
  355. ASN1_NULL:
  356. s := MibNullToASNObject(GetValueOID(n));
  357. else
  358. s := MibStrToASNObject(GetValueOID(n), GetValue(n), objType);
  359. end;
  360. data := data + ASNObject(s, ASN1_SEQ);
  361. end;
  362. data := ASNObject(ASNEncInt(ID), ASN1_INT)
  363. + ASNObject(ASNEncInt(ErrorStatus), ASN1_INT)
  364. + ASNObject(ASNEncInt(ErrorIndex), ASN1_INT)
  365. + ASNObject(data, ASN1_SEQ);
  366. data := ASNObject(ASNEncInt(Version), ASN1_INT)
  367. + ASNObject(Community, ASN1_OCTSTR)
  368. + ASNObject(data, PDUType);
  369. data := ASNObject(data, ASN1_SEQ);
  370. Result := data;
  371. end;
  372. (*----------------------------------------------------------------------------*
  373. | procedure TSNMPInfo.Clear |
  374. | |
  375. | Clear the header info and MIBOID/Value lists. |
  376. *----------------------------------------------------------------------------*)
  377. procedure TSNMPInfo.Clear;
  378. var
  379. // under ARC, convert a weak reference to a strong reference before working with it
  380. LOwner: TIdSNMP;
  381. begin
  382. LOwner := fOwner;
  383. Version := 0;
  384. if LOwner <> nil then begin
  385. fCommunity := LOwner.Community;
  386. if Self = LOwner.Trap then begin
  387. Port := LOwner.TrapPort
  388. end else begin
  389. Port := LOwner.Port;
  390. end;
  391. Host := LOwner.Host;
  392. end else begin
  393. fCommunity := '';
  394. Port := 0;
  395. Host := '';
  396. end;
  397. PDUType := 0;
  398. ID := 0;
  399. ErrorStatus := 0;
  400. ErrorIndex := 0;
  401. {$IFDEF HAS_GENERICS_TList}
  402. MIBValues.Clear;
  403. {$ELSE}
  404. MIBOID.Clear;
  405. MIBValue.Clear;
  406. {$ENDIF}
  407. end;
  408. (*----------------------------------------------------------------------------*
  409. | procedure TSNMPInfo.MIBAdd |
  410. | |
  411. | Add a MIBOID/Value pair |
  412. | |
  413. | Parameters: |
  414. | MIB : string The MIBOID to add |
  415. | Value : string The Value |
  416. | valueType : Integer The Value's type. Optional - defaults to | {Do not Localize}
  417. | ASN1_OCTSTR |
  418. *----------------------------------------------------------------------------*)
  419. procedure TSNMPInfo.MIBAdd(MIB, Value: string; ValueType: Integer);
  420. {$IFNDEF HAS_GENERICS_TList}
  421. var
  422. x: integer;
  423. {$ENDIF}
  424. begin
  425. {$IFDEF HAS_GENERICS_TList}
  426. MIBValues.Add(TIdMIBValue.Create(MIB, Value, ValueType));
  427. {$ELSE}
  428. SyncMIB;
  429. MIBOID.Add(MIB);
  430. x := MIBOID.Count;
  431. if MIBValue.Count > x then
  432. begin
  433. MIBValue[x-1] := Value;
  434. MIBValue.Objects[x-1] := TObject(ValueType);
  435. end else
  436. begin
  437. MIBValue.AddObject(Value, TObject(ValueType));
  438. end;
  439. {$ENDIF}
  440. end;
  441. (*----------------------------------------------------------------------------*
  442. | procedure TSNMPInfo.MIBDelete |
  443. | |
  444. | Delete a MIBOID/Value pair |
  445. | |
  446. | Parameters: |
  447. | Index:integer The index of the pair to delete |
  448. *----------------------------------------------------------------------------*)
  449. procedure TSNMPInfo.MIBDelete(Index: integer);
  450. begin
  451. {$IFDEF HAS_GENERICS_TList}
  452. MIBValues.Delete(Index);
  453. {$ELSE}
  454. SyncMIB;
  455. MIBOID.Delete(Index);
  456. if (MIBValue.Count-1) >= Index then begin
  457. MIBValue.Delete(Index);
  458. end;
  459. {$ENDIF}
  460. end;
  461. (*----------------------------------------------------------------------------*
  462. | function TSNMPInfo.MIBGet |
  463. | |
  464. | Get a string representation of the value of the specified MIBOID |
  465. | |
  466. | Parameters: |
  467. | MIB:string The MIBOID to query |
  468. | |
  469. | The function returns the string representation of the value. |
  470. *----------------------------------------------------------------------------*)
  471. function TSNMPInfo.MIBGet(MIB: string): string;
  472. var
  473. x: integer;
  474. begin
  475. {$IFDEF HAS_GENERICS_TList}
  476. Result := ''; {Do not Localize}
  477. for x := 0 to MIBValues.Count-1 do begin
  478. if TextIsSame(MIBValues[x].OID, MIB) then begin
  479. Result := MIBValues[x].Value;
  480. Exit;
  481. end;
  482. end;
  483. {$ELSE}
  484. SyncMIB;
  485. x := MIBOID.IndexOf(MIB);
  486. if x < 0 then begin
  487. Result := ''; {Do not Localize}
  488. end else begin
  489. Result := MIBValue[x];
  490. end;
  491. {$ENDIF}
  492. end;
  493. {======================= TRAPS =====================================}
  494. (*----------------------------------------------------------------------------*
  495. | procedure TSNMPInfo.EncodeTrap |
  496. | |
  497. | Encode the trap details into an ASN string - the 'Buffer' member |
  498. | |
  499. | The function returns 1 for historical reasons! |
  500. *----------------------------------------------------------------------------*)
  501. function TSNMPInfo.EncodeTrap: Boolean;
  502. var
  503. s: string;
  504. n: integer;
  505. objType: Integer;
  506. begin
  507. Buffer := ''; {Do not Localize}
  508. for n := 0 to {$IFDEF HAS_GENERICS_TList}MIBValues{$ELSE}MIBOID{$ENDIF}.Count-1 do
  509. begin
  510. objType := GetValueType(n);
  511. case objType of
  512. ASN1_INT:
  513. s := MibIntToASNObject(GetValueOID(n), IndyStrToInt(GetValue(n), 0));
  514. ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
  515. s := MibUIntToASNObject(GetValueOID(n), IndyStrToInt(GetValue(n), 0), objType);
  516. ASN1_OBJID:
  517. s := MibObjIDToASNObject(GetValueOID(n), GetValue(n));
  518. ASN1_IPADDR:
  519. s := MibIPAddrToASNObject(GetValueOID(n), GetValue(n));
  520. ASN1_NULL:
  521. s := MibNullToASNObject(GetValueOID(n));
  522. else
  523. s := MibStrToASNObject(GetValueOID(n), GetValue(n), objType);
  524. end;
  525. Buffer := Buffer + ASNObject(s, ASN1_SEQ);
  526. end;
  527. Buffer := ASNObject(MibToID(Enterprise), ASN1_OBJID)
  528. + ASNObject(IPToID(Host), ASN1_IPADDR)
  529. + ASNObject(ASNEncInt(GenTrap), ASN1_INT)
  530. + ASNObject(ASNEncInt(SpecTrap), ASN1_INT)
  531. + ASNObject(ASNEncInt(TimeTicks), ASN1_TIMETICKS)
  532. + ASNObject(Buffer, ASN1_SEQ);
  533. Buffer := ASNObject(ASNEncInt(Version), ASN1_INT)
  534. + ASNObject(Community, ASN1_OCTSTR)
  535. + ASNObject(Buffer, PDUType);
  536. Buffer := ASNObject(Buffer, ASN1_SEQ);
  537. Result := True;
  538. end;
  539. (*----------------------------------------------------------------------------*
  540. | procedure TSNMPInfo.DecodeTrap |
  541. | |
  542. | Decode the 'Buffer' trap string to fil in our member variables. | {Do not Localize}
  543. | |
  544. | The function returns 1. |
  545. *----------------------------------------------------------------------------*)
  546. function TSNMPInfo.DecodeTrap: Boolean;
  547. var
  548. Pos, EndPos, vt: integer;
  549. Sm, Sv: string;
  550. begin
  551. Pos := 2;
  552. EndPos := ASNDecLen(Pos, Buffer);
  553. Version := IndyStrToInt(ASNItem(Pos, Buffer, vt), 0);
  554. Community := ASNItem(Pos, Buffer, vt);
  555. PDUType := IndyStrToInt(ASNItem(Pos, Buffer, vt), PDUTRAP);
  556. Enterprise := ASNItem(Pos, Buffer, vt);
  557. Host := ASNItem(Pos, Buffer, vt);
  558. GenTrap := IndyStrToInt(ASNItem(Pos, Buffer, vt), 0);
  559. Spectrap := IndyStrToInt(ASNItem(Pos, Buffer, vt), 0);
  560. TimeTicks := IndyStrToInt(ASNItem(Pos, Buffer, vt), 0);
  561. ASNItem(Pos, Buffer, vt);
  562. while Pos < EndPos do
  563. begin
  564. ASNItem(Pos, Buffer, vt);
  565. Sm := ASNItem(Pos, Buffer, vt);
  566. Sv := ASNItem(Pos, Buffer, vt);
  567. MIBAdd(Sm, Sv, vt);
  568. end;
  569. Result := True;
  570. end;
  571. (*----------------------------------------------------------------------------*
  572. | TSNMPInfo.SetCommunity |
  573. | |
  574. | Set the community. |
  575. | |
  576. | Parameters: |
  577. | const Value: string The new community value |
  578. *----------------------------------------------------------------------------*)
  579. procedure TSNMPInfo.SetCommunity(const Value: string);
  580. begin
  581. if fCommunity <> Value then
  582. begin
  583. Clear;
  584. fCommunity := Value;
  585. end;
  586. end;
  587. { TIdSNMP }
  588. {============================== IdSNMP OBJECT ================================}
  589. (*----------------------------------------------------------------------------*
  590. | constructor TIdSNMP.Create |
  591. | |
  592. | Contructor for TIdSNMP component |
  593. | |
  594. | Parameters: |
  595. | aOwner : TComponent |
  596. *----------------------------------------------------------------------------*)
  597. {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
  598. constructor TIdSNMP.Create(AOwner: TComponent);
  599. begin
  600. inherited Create(AOwner);
  601. end;
  602. {$ENDIF}
  603. procedure TIdSNMP.InitComponent;
  604. begin
  605. inherited InitComponent;
  606. Port := 161;
  607. fTrapPort := 162;
  608. fCommunity := 'public'; {Do not Localize}
  609. Query := TSNMPInfo.Create(Self);
  610. Reply := TSNMPInfo.Create(Self);
  611. Trap := TSNMPInfo.Create(Self);
  612. Query.Clear;
  613. Reply.Clear;
  614. Trap.Clear;
  615. FReceiveTimeout := 5000;
  616. end;
  617. (*----------------------------------------------------------------------------*
  618. | destructor TIdSNMP.Destroy |
  619. | |
  620. | Destructor for TIdSNMP component |
  621. *----------------------------------------------------------------------------*)
  622. destructor TIdSNMP.Destroy;
  623. begin
  624. FreeAndNil(Reply);
  625. FreeAndNil(Query);
  626. FreeAndNil(Trap);
  627. inherited Destroy;
  628. end;
  629. (*----------------------------------------------------------------------------*
  630. | function TIdSNMP.GetBinding |
  631. | |
  632. | Prepare socket handles for use. |
  633. *----------------------------------------------------------------------------*)
  634. function TIdSNMP.GetBinding: TIdSocketHandle;
  635. begin
  636. Result := inherited GetBinding;
  637. if fTrapRecvBinding = nil then begin
  638. fTrapRecvBinding := TIdSocketHandle.Create(nil);
  639. end;
  640. if (not fTrapRecvBinding.HandleAllocated) and (fTrapPort <> 0) then begin
  641. fTrapRecvBinding.IPVersion := Result.IPVersion;
  642. fTrapRecvBinding.AllocateSocket(Id_SOCK_DGRAM);
  643. fTrapRecvBinding.IP := Result.IP;
  644. fTrapRecvBinding.Port := fTrapPort;
  645. fTrapRecvBinding.Bind;
  646. end;
  647. end;
  648. (*----------------------------------------------------------------------------*
  649. | procedure TIdSNMP.CloseBinding |
  650. | |
  651. | Clean up socket handles. |
  652. *----------------------------------------------------------------------------*)
  653. procedure TIdSNMP.CloseBinding;
  654. begin
  655. FreeAndNil(fTrapRecvBinding);
  656. inherited CloseBinding;
  657. end;
  658. (*----------------------------------------------------------------------------*
  659. | function TIdSNMP.SendQuery |
  660. | |
  661. | Send an SNMP query and receive a reply. |
  662. | |
  663. | nb. Before calling this, ensure that the following members are set: |
  664. | |
  665. | Community The SNMP community being queried - eg. 'public' | {Do not Localize}
  666. | Host The IP address being queried. 127.0.0.1 for the |
  667. | local machine. |
  668. | |
  669. | The call Query.Clear, then set: |
  670. | |
  671. | Query.PDUType PDUGetRequest to get a single set of MIBOID |
  672. | value(s) or PDUGetNextRequest to start walking |
  673. | the MIB |
  674. | |
  675. | Next call Query.Clear, call MIBAdd to add the MIBOID(s) you require. |
  676. | |
  677. | The function returns True if a response was received. IF a response was |
  678. | received, it will be decoded into Reply.Value |
  679. *----------------------------------------------------------------------------*)
  680. function TIdSNMP.SendQuery: Boolean;
  681. var
  682. LEncoding: IIdTextEncoding;
  683. begin
  684. Reply.Clear;
  685. Query.Buffer := Query.EncodeBuf;
  686. LEncoding := IndyTextEncoding_8Bit;
  687. Send(Query.Host, Query.Port, Query.Buffer, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
  688. try
  689. Reply.Buffer := ReceiveString(Reply.Host, Reply.Port, FReceiveTimeout, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
  690. except
  691. on e : EIdSocketError do
  692. begin
  693. if e.LastError = 10054 then begin
  694. Reply.Buffer := ''; {Do not Localize}
  695. end else begin
  696. raise;
  697. end;
  698. end;
  699. end;
  700. if Reply.Buffer <> '' then begin
  701. Reply.DecodeBuf(Reply.Buffer); {Do not Localize}
  702. end;
  703. Result := (Reply.Buffer <> '') and (Reply.ErrorStatus = 0); {Do not Localize}
  704. end;
  705. (*----------------------------------------------------------------------------*
  706. | TIdSNMP.QuickSend |
  707. | |
  708. | Query a single MIBOID value. |
  709. | |
  710. | Parameters: |
  711. | Mib : string The MIBOID to query |
  712. | Community : string The SNMP comunity |
  713. | Host : string The SNMP host |
  714. | var value : string String representation of the returned value. |
  715. | |
  716. | The function returns true if a value was returned for the MIB OID |
  717. *----------------------------------------------------------------------------*)
  718. function TIdSNMP.QuickSend (const Mib, DestCommunity, DestHost: string; var Value: string): Boolean;
  719. begin
  720. Community := DestCommunity;
  721. Host := DestHost;
  722. Query.Clear;
  723. Query.PDUType := PDUGetRequest;
  724. Query.MIBAdd(MIB, ''); {Do not Localize}
  725. Result := SendQuery;
  726. if Result then begin
  727. Value := Reply.MIBGet(MIB);
  728. end;
  729. end;
  730. (*----------------------------------------------------------------------------*
  731. | TIdSNMP.SendTrap |
  732. | |
  733. | Send an SNMP trap. |
  734. | |
  735. | The function returns 1 |
  736. *----------------------------------------------------------------------------*)
  737. function TIdSNMP.SendTrap: Boolean;
  738. var
  739. LEncoding: IIdTextEncoding;
  740. begin
  741. Trap.PDUType := PDUTrap;
  742. Trap.EncodeTrap;
  743. LEncoding := IndyTextEncoding_8Bit;
  744. Send(Trap.Host, Trap.Port, Trap.Buffer, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
  745. Result := True;
  746. end;
  747. function TIdSNMP.ReceiveTrap: Boolean;
  748. var
  749. i, LMSec: Integer;
  750. LBuffer : TIdBytes;
  751. LIPVersion: TIdIPVersion;
  752. begin
  753. Result := False;
  754. Trap.Clear;
  755. Trap.PDUType := PDUTrap;
  756. LMSec := ReceiveTimeOut;
  757. if (LMSec = IdTimeoutDefault) or (LMSec = 0) then begin
  758. LMSec := IdTimeoutInfinite;
  759. end;
  760. GetBinding; // make sure fTrapBinding is allocated
  761. SetLength(LBuffer, BufferSize);
  762. if not fTrapRecvBinding.Readable(LMSec) then begin
  763. Trap.Host := ''; {Do not Localize}
  764. Trap.Port := 0;
  765. Exit;
  766. end;
  767. i := fTrapRecvBinding.RecvFrom(LBuffer, Trap.Host, Trap.Port, LIPVersion);
  768. Trap.Buffer := BytesToString(LBuffer, 0, i, IndyTextEncoding_8Bit);
  769. if Trap.Buffer <> '' then begin {Do not Localize}
  770. Trap.DecodeTrap;
  771. Result := True;
  772. end;
  773. end;
  774. function TIdSNMP.QuickSendTrap(const DestHost, Enterprise, DestCommunity: string;
  775. DestPort: TIdPort; Generic, Specific: integer;
  776. {$IFDEF HAS_GENERICS_TList}
  777. MIBValues: TIdMIBValueList
  778. {$ELSE}
  779. MIBName, MIBValue: TStrings
  780. {$ENDIF}
  781. ): Boolean;
  782. var
  783. i: integer;
  784. begin
  785. Trap.Clear;
  786. Trap.Host := DestHost;
  787. Trap.Port := DestPort;
  788. Trap.Community := DestCommunity;
  789. Trap.Enterprise := Enterprise;
  790. Trap.GenTrap := Generic;
  791. Trap.SpecTrap := Specific;
  792. for i := 0 to {$IFDEF HAS_GENERICS_TList}MIBValues{$ELSE}MIBName{$ENDIF}.Count-1 do begin
  793. Trap.MIBAdd(
  794. {$IFDEF HAS_GENERICS_TList}
  795. MIBValues[i].OID, MIBValues[i].Value, MIBValues[i].ValueType
  796. {$ELSE}
  797. MIBName[i], MIBValue[i], PtrInt(MIBValue.Objects[i])
  798. {$ENDIF}
  799. );
  800. end;
  801. Result := SendTrap;
  802. end;
  803. function TIdSNMP.QuickReceiveTrap(var SrcHost, Enterprise, SrcCommunity: string;
  804. var SrcPort: TIdPort; var Generic, Specific, Seconds: integer;
  805. {$IFDEF HAS_GENERICS_TList}
  806. MIBValues: TIdMIBValueList
  807. {$ELSE}
  808. MIBName, MIBValue: TStrings
  809. {$ENDIF}
  810. ): Boolean;
  811. var
  812. i: integer;
  813. begin
  814. Result := ReceiveTrap;
  815. if Result then
  816. begin
  817. SrcHost := Trap.Host;
  818. SrcPort := Trap.Port;
  819. Enterprise := Trap.Enterprise;
  820. SrcCommunity := Trap.Community;
  821. Generic := Trap.GenTrap;
  822. Specific := Trap.SpecTrap;
  823. Seconds := Trap.TimeTicks;
  824. {$IFDEF HAS_GENERICS_TList}
  825. MIBValues.Clear;
  826. {$ELSE}
  827. MIBName.Clear;
  828. MIBValue.Clear;
  829. {$ENDIF}
  830. for i := 0 to Trap.{$IFDEF HAS_GENERICS_TList}MIBValues{$ELSE}MIBOID{$ENDIF}.Count-1 do
  831. begin
  832. {$IFDEF HAS_GENERICS_TList}
  833. MIBValues.Add(TIdMIBValue.Create(Trap.ValueOID[i], Trap.Value[i], Trap.ValueType[i]));
  834. {$ELSE}
  835. MIBName.Add(Trap.ValueOID[i]);
  836. MIBValue.AddObject(Trap.Value[i], TObject(Trap.ValueType[i]));
  837. {$ENDIF}
  838. end;
  839. end;
  840. end;
  841. (*----------------------------------------------------------------------------*
  842. | TSNMPInfo.GetValue |
  843. | |
  844. | Return string representation of value 'idx' |
  845. | |
  846. | Parameters: |
  847. | idx : Integer The value to get |
  848. | |
  849. | The function returns the string representation of the value. |
  850. *----------------------------------------------------------------------------*)
  851. function TSNMPInfo.GetValue (idx : Integer) : string;
  852. begin
  853. {$IFDEF HAS_GENERICS_TList}
  854. Result := MIBValues[idx].Value;
  855. {$ELSE}
  856. Result := MIBValue[idx];
  857. {$ENDIF}
  858. end;
  859. (*----------------------------------------------------------------------------*
  860. | TSNMPInfo.GetValueCount |
  861. | |
  862. | Get the number of values. |
  863. | |
  864. | The function returns the number of values. |
  865. *----------------------------------------------------------------------------*)
  866. function TSNMPInfo.GetValueCount: Integer;
  867. begin
  868. {$IFDEF HAS_GENERICS_TList}
  869. Result := MIBValues.Count;
  870. {$ELSE}
  871. Result := MIBValue.Count;
  872. {$ENDIF}
  873. end;
  874. (*----------------------------------------------------------------------------*
  875. | TSNMPInfo.GetValueType |
  876. | |
  877. | Return the 'type' of value 'idx' |
  878. | |
  879. | Parameters: |
  880. | idx : Integer The value type to get |
  881. | |
  882. | The function returns the value type. |
  883. *----------------------------------------------------------------------------*)
  884. function TSNMPInfo.GetValueType (idx : Integer): Integer;
  885. begin
  886. {$IFDEF HAS_GENERICS_TList}
  887. Result := MIBValues[idx].ValueType;
  888. {$ELSE}
  889. Result := Integer(MIBValue.Objects[idx]);
  890. {$ENDIF}
  891. if Result = 0 then begin
  892. Result := ASN1_OCTSTR;
  893. end;
  894. end;
  895. (*----------------------------------------------------------------------------*
  896. | TSNMPInfo.GetValueOID |
  897. | |
  898. | Get the MIB OID for value 'idx' |
  899. | |
  900. | Parameters: |
  901. | idx: Integer The MIB OID to gey |
  902. | |
  903. | The function returns the specified MIB OID |
  904. *----------------------------------------------------------------------------*)
  905. function TSNMPInfo.GetValueOID(idx: Integer): string;
  906. begin
  907. {$IFDEF HAS_GENERICS_TList}
  908. Result := MIBValues[idx].OID;
  909. {$ELSE}
  910. Result := MIBOID[idx];
  911. {$ENDIF}
  912. end;
  913. (*----------------------------------------------------------------------------*
  914. | TIdSNMP.SetCommunity |
  915. | |
  916. | Setter for the Community property. |
  917. | |
  918. | Parameters: |
  919. | const Value: string The new community value |
  920. *----------------------------------------------------------------------------*)
  921. procedure TIdSNMP.SetCommunity(const Value: string);
  922. begin
  923. if fCommunity <> Value then
  924. begin
  925. fCommunity := Value;
  926. Query.Community := Value;
  927. Reply.Community := Value;
  928. Trap.Community := Value
  929. end
  930. end;
  931. (*----------------------------------------------------------------------------*
  932. | TIdSNMP.SetTrapPort |
  933. | |
  934. | Setter for the TrapPort property. |
  935. | |
  936. | Parameters: |
  937. | const Value: TIdPort The new port value |
  938. *----------------------------------------------------------------------------*)
  939. procedure TIdSNMP.SetTrapPort(const AValue: TIdPort);
  940. begin
  941. if fTrapPort <> AValue then begin
  942. if Assigned(fTrapRecvBinding) then begin
  943. fTrapRecvBinding.CloseSocket;
  944. end;
  945. fTrapPort := AValue;
  946. end;
  947. end;
  948. end.