📄 snmpsend.pas
字号:
the basic SET method of the SNMP protocol. If the SNMP operation is successful,
the result is @true. "Value" is value of MIB Oid for "SNMPHost" with "Community"
access identifier. You must specify "ValueType" too.}
function SNMPSet(const OID, Community, SNMPHost, Value: AnsiString; ValueType: Integer): Boolean;
{:A very useful function and example of its use would be found in the TSNMPSend
object. It implements basic GETNEXT method of the SNMP protocol. The MIB value
is located in the "OID" variable, and is sent to the requested "SNMPHost" with
the proper "Community" access identifier. Upon a successful retrieval, "Value"
will contain the information requested. If the SNMP operation is successful,
the result returns @true.}
function SNMPGetNext(var OID: AnsiString; const Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
{:A very useful function and example of its use would be found in the TSNMPSend
object. It implements basic read of SNMP MIB tables. As BaseOID you must
specify basic MIB OID of requested table (base IOD is OID without row and
column specificator!)
Table is readed into stringlist, where each string is comma delimited string.
Warning: this function is not have best performance. For better performance
you must write your own function. best performace you can get by knowledge
of structuture of table and by more then one MIB on one query. }
function SNMPGetTable(const BaseOID, Community, SNMPHost: AnsiString; const Value: TStrings): Boolean;
{:A very useful function and example of its use would be found in the TSNMPSend
object. It implements basic read of SNMP MIB table element. As BaseOID you must
specify basic MIB OID of requested table (base IOD is OID without row and
column specificator!)
As next you must specify identificator of row and column for specify of needed
field of table.}
function SNMPGetTableElement(const BaseOID, RowID, ColID, Community, SNMPHost: AnsiString; var Value: AnsiString): Boolean;
{:A very useful function and example of its use would be found in the TSNMPSend
object. It implements a TRAPv1 to send with all data in the parameters.}
function SendTrap(const Dest, Source, Enterprise, Community: AnsiString;
Generic, Specific, Seconds: Integer; const MIBName, MIBValue: AnsiString;
MIBtype: Integer): Integer;
{:A very useful function and example of its use would be found in the TSNMPSend
object. It receives a TRAPv1 and returns all the data that comes with it.}
function RecvTrap(var Dest, Source, Enterprise, Community: AnsiString;
var Generic, Specific, Seconds: Integer; const MIBName,
MIBValue: TStringList): Integer;
implementation
{==============================================================================}
constructor TSNMPRec.Create;
begin
inherited Create;
FSNMPMibList := TList.Create;
Clear;
FID := 1;
FMaxSize := 1472;
end;
destructor TSNMPRec.Destroy;
var
i: Integer;
begin
for i := 0 to FSNMPMibList.Count - 1 do
TSNMPMib(FSNMPMibList[i]).Free;
FSNMPMibList.Clear;
FSNMPMibList.Free;
inherited Destroy;
end;
function TSNMPRec.Pass2Key(const Value: AnsiString): AnsiString;
var
key: AnsiString;
begin
case FAuthMode of
AuthMD5:
begin
key := MD5LongHash(Value, 1048576);
Result := MD5(key + FAuthEngineID + key);
end;
AuthSHA1:
begin
key := SHA1LongHash(Value, 1048576);
Result := SHA1(key + FAuthEngineID + key);
end;
else
Result := '';
end;
end;
function TSNMPRec.DecodeBuf(const Buffer: AnsiString): Boolean;
var
Pos: Integer;
EndPos: Integer;
sm, sv: AnsiString;
Svt: Integer;
s: AnsiString;
Spos: integer;
x: Byte;
begin
Clear;
Result := False;
if Length(Buffer) < 2 then
Exit;
if (Ord(Buffer[1]) and $20) = 0 then
Exit;
Pos := 2;
EndPos := ASNDecLen(Pos, Buffer);
if Length(Buffer) < (EndPos + 2) then
Exit;
Self.FVersion := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
if FVersion = 3 then
begin
ASNItem(Pos, Buffer, Svt); //header data seq
ASNItem(Pos, Buffer, Svt); //ID
FMaxSize := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
s := ASNItem(Pos, Buffer, Svt);
x := 0;
if s <> '' then
x := Ord(s[1]);
FFlagReportable := (x and 4) > 0;
x := x and 3;
case x of
1:
FFlags := AuthNoPriv;
3:
FFlags := AuthPriv;
else
FFlags := NoAuthNoPriv;
end;
x := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
s := ASNItem(Pos, Buffer, Svt); //SecurityParameters
//if SecurityModel is USM, then try to decode SecurityParameters
if (x = 3) and (s <> '') then
begin
spos := 1;
ASNItem(SPos, s, Svt);
FAuthEngineID := ASNItem(SPos, s, Svt);
FAuthEngineBoots := StrToIntDef(ASNItem(SPos, s, Svt), 0);
FAuthEngineTime := StrToIntDef(ASNItem(SPos, s, Svt), 0);
FAuthEngineTimeStamp := GetTick;
FUserName := ASNItem(SPos, s, Svt);
FAuthKey := ASNItem(SPos, s, Svt);
FPrivKey := ASNItem(SPos, s, Svt);
end;
//scopedPDU
s := ASNItem(Pos, Buffer, Svt);
if Svt = ASN1_OCTSTR then
begin
//decrypt!
end;
FContextEngineID := ASNItem(Pos, Buffer, Svt);
FContextName := ASNItem(Pos, Buffer, Svt);
end
else
begin
//old packet
Self.FCommunity := ASNItem(Pos, Buffer, Svt);
end;
ASNItem(Pos, Buffer, Svt);
Self.FPDUType := Svt;
if Self.FPDUType = PDUTrap then
begin
FOldTrapEnterprise := ASNItem(Pos, Buffer, Svt);
FOldTrapHost := ASNItem(Pos, Buffer, Svt);
FOldTrapGen := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
FOldTrapSpec := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
FOldTrapTimeTicks := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
end
else
begin
Self.FID := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
Self.FErrorStatus := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
Self.FErrorIndex := StrToIntDef(ASNItem(Pos, Buffer, Svt), 0);
end;
ASNItem(Pos, Buffer, Svt);
while Pos < EndPos do
begin
ASNItem(Pos, Buffer, Svt);
Sm := ASNItem(Pos, Buffer, Svt);
Sv := ASNItem(Pos, Buffer, Svt);
Self.MIBAdd(sm, sv, Svt);
end;
Result := True;
end;
function TSNMPRec.EncodeBuf: AnsiString;
var
s: AnsiString;
SNMPMib: TSNMPMib;
n: Integer;
pdu, head, auth, authbeg: AnsiString;
x: Byte;
begin
pdu := '';
for n := 0 to FSNMPMibList.Count - 1 do
begin
SNMPMib := TSNMPMib(FSNMPMibList[n]);
case SNMPMib.ValueType of
ASN1_INT:
s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
ASNObject(ASNEncInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType);
ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
ASNObject(ASNEncUInt(StrToIntDef(SNMPMib.Value, 0)), SNMPMib.ValueType);
ASN1_OBJID:
s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
ASNObject(MibToID(SNMPMib.Value), SNMPMib.ValueType);
ASN1_IPADDR:
s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
ASNObject(IPToID(SNMPMib.Value), SNMPMib.ValueType);
ASN1_NULL:
s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
ASNObject('', ASN1_NULL);
else
s := ASNObject(MibToID(SNMPMib.OID), ASN1_OBJID) +
ASNObject(SNMPMib.Value, SNMPMib.ValueType);
end;
pdu := pdu + ASNObject(s, ASN1_SEQ);
end;
pdu := ASNObject(pdu, ASN1_SEQ);
if Self.FPDUType = PDUTrap then
pdu := ASNObject(MibToID(FOldTrapEnterprise), ASN1_OBJID) +
ASNObject(IPToID(FOldTrapHost), ASN1_IPADDR) +
ASNObject(ASNEncInt(FOldTrapGen), ASN1_INT) +
ASNObject(ASNEncInt(FOldTrapSpec), ASN1_INT) +
ASNObject(ASNEncUInt(FOldTrapTimeTicks), ASN1_TIMETICKS) +
pdu
else
pdu := ASNObject(ASNEncInt(Self.FID), ASN1_INT) +
ASNObject(ASNEncInt(Self.FErrorStatus), ASN1_INT) +
ASNObject(ASNEncInt(Self.FErrorIndex), ASN1_INT) +
pdu;
pdu := ASNObject(pdu, Self.FPDUType);
if FVersion = 3 then
begin
if FContextEngineID = '' then
FContextEngineID := FAuthEngineID;
//complete PDUv3...
pdu := ASNObject(FContextEngineID, ASN1_OCTSTR)
+ ASNObject(FContextName, ASN1_OCTSTR)
+ pdu;
//maybe encrypt pdu... in future
pdu := ASNObject(pdu, ASN1_SEQ);
//prepare flags
case FFlags of
AuthNoPriv:
x := 1;
AuthPriv:
x := 3;
else
x := 0;
end;
if FFlagReportable then
x := x or 4;
head := ASNObject(ASNEncInt(Self.FVersion), ASN1_INT);
s := ASNObject(ASNEncInt(FID), ASN1_INT)
+ ASNObject(ASNEncInt(FMaxSize), ASN1_INT)
+ ASNObject(AnsiChar(x), ASN1_OCTSTR)
//encode security model USM
+ ASNObject(ASNEncInt(3), ASN1_INT);
head := head + ASNObject(s, ASN1_SEQ);
//compute engine time difference
x := TickDelta(FAuthEngineTimeStamp, GetTick) div 1000;
authbeg := ASNObject(FAuthEngineID, ASN1_OCTSTR)
+ ASNObject(ASNEncInt(FAuthEngineBoots), ASN1_INT)
+ ASNObject(ASNEncInt(FAuthEngineTime + x), ASN1_INT)
+ ASNObject(FUserName, ASN1_OCTSTR);
case FFlags of
AuthNoPriv,
AuthPriv:
begin
s := authbeg + ASNObject(StringOfChar(#0, 12), ASN1_OCTSTR)
+ ASNObject(FPrivKey, ASN1_OCTSTR);
s := ASNObject(s, ASN1_SEQ);
s := head + ASNObject(s, ASN1_OCTSTR);
s := ASNObject(s + pdu, ASN1_SEQ);
//in s is entire packet without auth info...
case FAuthMode of
AuthMD5:
begin
s := HMAC_MD5(s, Pass2Key(FPassword) + StringOfChar(#0, 48));
//strip to HMAC-MD5-96
delete(s, 13, 4);
end;
AuthSHA1:
begin
s := HMAC_SHA1(s, Pass2Key(FPassword) + StringOfChar(#0, 44));
//strip to HMAC-SHA-96
delete(s, 13, 8);
end;
else
s := '';
end;
FAuthKey := s;
end;
end;
auth := authbeg + ASNObject(FAuthKey, ASN1_OCTSTR)
+ ASNObject(FPrivKey, ASN1_OCTSTR);
auth := ASNObject(auth, ASN1_SEQ);
head := head + ASNObject(auth, ASN1_OCTSTR);
Result := ASNObject(head + pdu, ASN1_SEQ);
end
else
begin
head := ASNObject(ASNEncInt(Self.FVersion), ASN1_INT) +
ASNObject(Self.FCommunity, ASN1_OCTSTR);
Result := ASNObject(head + pdu, ASN1_SEQ);
end;
end;
procedure TSNMPRec.Clear;
var
i: Integer;
begin
FVersion := SNMP_V1;
FCommunity := 'public';
FUserName := '';
FPassword := '';
FPDUType := 0;
FErrorStatus := 0;
FErrorIndex := 0;
for i := 0 to FSNMPMibList.Count - 1 do
TSNMPMib(FSNMPMibList[i]).Free;
FSNMPMibList.Clear;
FOldTrapEnterprise := '';
FOldTrapHost := '';
FOldTrapGen := 0;
FOldTrapSpec := 0;
FOldTrapTimeTicks := 0;
FFlags := NoAuthNoPriv;
FFlagReportable := false;
FContextEngineID := '';
FContextName := '';
FAuthMode := AuthMD5;
FAuthEngineID := '';
FAuthEngineBoots := 0;
FAuthEngineTime := 0;
FAuthEngineTimeStamp := 0;
FAuthKey := '';
FPrivKey := '';
end;
procedure TSNMPRec.MIBAdd(const MIB, Value: AnsiString; ValueType: Integer);
var
SNMPMib: TSNMPMib;
begin
SNMPMib := TSNMPMib.Create;
SNMPMib.OID := MIB;
SNMPMib.Value := Value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -