求AU3调用API操作ARP实例!!
本帖最后由 FBWOLF 于 2009-5-29 18:09 编辑例:创建ARP列表项目
删除ARP列表项目
修改ARP列表项目
以下是DELPHI代码,供各位参考!
//那我就不客气了。
//代码在下面
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, WinSock;
const
MAXLEN_PHYSADDR = 8;
type
TMACArr6 = array of Byte;
TMAC_ADDR6 = record
case integer of
0: (bAddr: TMACArr6);
1: (DW: DWORD; WD: WORD);
end;
PMAC_ADDR6 = ^TMAC_ADDR6;
TMIB_IPNETROW = Record
dwIndex: DWORD;
dwPhysAddrLen: DWORD;
bPhysAddr: TMACArr6;
dwAddr: DWORD;
dwType: DWORD;
end;
PMIB_IPNETROW = ^TMIB_IPNETROW;
TMIB_IPNETTABLE = Record
dwNumEntries: DWORD;
table: array of TMIB_IPNETROW;
end;
PMIB_IPNETTABLE = ^TMIB_IPNETTABLE;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure GetARPTable();
public
{ Public declarations }
end;
var
Form1: TForm1;
function GetIpNetTable(pIpNetTable: PMIB_IPNETTABLE; var pdwSize: DWORD;
bOrder: Boolean): DWORD; stdcall;
external 'IPHLPAPI.DLL' name 'GetIpNetTable';
function SetIpNetEntry(pArpEntry: PMIB_IPNETROW): DWORD; stdcall;
external 'IPHLPAPI.DLL' name 'SetIpNetEntry';
implementation
{$R *.DFM}
//取得ARP表所有的行
procedure TForm1.GetARPTable();
var
buf: array of BYTE;
pIPNet: PMIB_IPNETTABLE;
dwSize: DWORD;
i: integer;
pmac: PMAC_ADDR6;
smac: string;
begin
pIPNet := @buf;
dwSize := 4096;
if GetIpNetTable(pIPNet, dwSize, True) = 0 then
for i := 0 to pIPNet.dwNumEntries-1 do // 循环,ARP表每条处理一次
with pIPNet.table do
begin
pmac := @bPhysAddr;
if (pmac.DW <> 0) and (pmac.WD <> 0) then // 忽略MAC全0的行
begin
// inet_ntoa(in_addr(dwAddr)); // 得到该行IP与MAC
smac := IntToHex(bPhysAddr,2)+
IntToHex(bPhysAddr,2)+
IntToHex(bPhysAddr,2)+
IntToHex(bPhysAddr,2)+
IntToHex(bPhysAddr,2)+
IntToHex(bPhysAddr,2);
Memo1.Lines.Add(inet_ntoa(in_addr(dwAddr)) + ' ' + smac);
end;
end;
end;
// 修改一个已存在的行
procedure ChangeIPNetRow(Adapter: DWORD; dwAddr: DWORD; bAddr: TMACArr6);
var
mibrow: TMIB_IPNETROW;
begin
mibrow.dwIndex := Adapter;
mibrow.dwPhysAddrLen := 6;
mibrow.bPhysAddr := bAddr;
mibrow.dwAddr := dwAddr;
mibrow.dwType := 2; // invalid
SetIpNetEntry(@mibrow);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
GetARPTable();
end;
end. 不会吧,真的没人会吗? 不是没人会,大概是没有技术含量,高手们迟迟不肯出招。
Func _inet_addr($sAddr)
Local $iAddr
$iAddr = DllCall("Ws2_32.dll", "long", "inet_addr", "str", $sAddr)
Return $iAddr
EndFunc ;==>_inet_addr()
Func _inet_ntoa($iAddr)
Local $sAddr
$sAddr = DllCall("Ws2_32.dll", "str", "inet_ntoa", "long", $iAddr)
Return $sAddr
EndFunc ;==>_inet_ntoa()
Func _FormatMac($sMac, $iString = True)
If $iString Then
$sMac = StringTrimLeft($sMac, 2)
Return StringTrimRight(StringRegExpReplace($sMac, ".{2}", "\0:"), 1)
Else
Return "0x" & StringReplace($sMac, ":", "")
EndIf
EndFunc ;==>_FormatMac()
Func _GetIpNetTable()
Local $iResult, $tBuffer, $pBuffer, $tIpTable
Local $aResult, $tNum, $tagIpTable, $iIndex
$iResult = DllCall("iphlpapi.dll", "dword", "GetIpNetTable", _
"ptr", 0, "int*", 0, "int", 1)
If $iResult = 0 Then Return SetError($iResult, 0, $aResult)
$tBuffer = DllStructCreate("ubyte[" & $iResult & "]")
$pBuffer = DllStructGetPtr($tBuffer)
$iResult = DllCall("iphlpapi.dll", "dword", "GetIpNetTable", _
"ptr", $pBuffer, "int*", $iResult, "int", 1)
$tNum = DllStructCreate("dword", $pBuffer)
$aResult = DllStructGetData($tNum, 1)
Redim $aResult[$aResult + 1]
For $i = 1 to $aResult
$tagIpTable &= ";dword;byte;dword"
Next
$tIpTable = DllStructCreate("dword" & $tagIpTable, $pBuffer)
For $i = 2 to $aResult * 3 Step 3
$iIndex += 1
$aResult[$iIndex] = DllStructGetData($tIpTable, $i, 1)
$aResult[$iIndex] = _FormatMac(DllStructGetData($tIpTable, $i + 1))
$aResult[$iIndex] = _inet_ntoa(DllStructGetData($tIpTable, $i + 2, 1))
$aResult[$iIndex] = DllStructGetData($tIpTable, $i + 2, 2)
Next
$tNum = 0
$tBuffer = 0
$tIpTable = 0
Return SetError($iResult, 0, $aResult)
EndFunc ;==>_GetIpNetTable()
Func _SetIpNetEntry($iAdptIndex, $sAddr, $sMac, $sType = "Static")
Local $iResult, $iAddr, $iMac, $tIpNetRow, $pIpNetRow, $iType
Switch $sType
Case "Dynamic"
$iType = 3
Case Else
$iType = 4
EndSwitch
$iAddr = _inet_addr($sAddr)
$iMac = _FormatMac($sMac, 0)
$tIpNetRow = DllStructCreate("dword;byte;dword")
$pIpNetRow = DllStructGetPtr($tIpNetRow)
DllStructSetData($tIpNetRow, 1, $iAdptIndex, 1)
DllStructSetData($tIpNetRow, 1, (StringLen($iMac) - 2) / 2, 2)
DllStructSetData($tIpNetRow, 2, $iMac)
DllStructSetData($tIpNetRow, 3, $iAddr, 1)
DllStructSetData($tIpNetRow, 3, $iType, 2)
$iResult = DllCall("iphlpapi.dll", "long", "SetIpNetEntry", "ptr", $pIpNetRow)
$tIpNetRow = 0
Return SetError($iResult, 0, $iResult = 0)
EndFunc ;==>_SetIpNetEntry()
Func _DeleteIpNetEntry($iAdptIndex, $sAddr)
Local $iResult, $iAddr, $tIpNetRow, $pIpNetRow
$iAddr = _inet_addr($sAddr)
$tIpNetRow = DllStructCreate("dword;byte;dword")
$pIpNetRow = DllStructGetPtr($tIpNetRow)
DllStructSetData($tIpNetRow, 1, $iAdptIndex, 1)
DllStructSetData($tIpNetRow, 3, $iAddr, 1)
$iResult = DllCall("iphlpapi.dll", "long", "DeleteIpNetEntry", "ptr", $pIpNetRow)
$tIpNetRow = 0
Return SetError($iResult, 0, $iResult = 0)
EndFunc ;==>_DeleteIpNetEntry()
3# pusofalse
pusofalse兄,谢谢!
其实。。。我一早就搬了凳子等你放出代码。。。呵呵
学习一下,终于可以放弃arp.exe了。 谢谢了!我先去试试了! 不好意思,我没调用成功
$iAdptIndex是什么呢?
对API操作实在是半窍不通啊! 问题:
1. $iAdptIndex 应该是网络适配器索引,也就是arp.exe中的if_addr。arp.exe中如果未指定if_addr,它是使用第一个可用接口。那么如何做到arp.exe这个效果?或者说未指定$iAdptIndex时如何直接获取?
2. _GetIpNetTable返回的PhysAddr,前6位是MAC地址,后2位是什么?如果没什么用的话,可否直接返回MAC地址? 不好意思,我没调用成功
$iAdptIndex是什么呢?
对API操作实在是半窍不通啊!
FBWOLF 发表于 2009-5-29 11:18 http://www.autoitx.com/images/common/back.gif
网络适配器索引,就是arp -a里显示的 Interface: 192.168.0.100 --- 0x10003 后面这个数字。 谢谢楼上兄弟! 找到了一段PB的获取网卡编号代码,给楼上兄弟参考了!兄弟研究好了!麻烦共享下,同谢!
FUNCTION Getdwindex() AS DWORD'DIM ifT AS MIB_IFTABLE
DIM lenIfT AS DWORD
DIM RValue AS LONG
DIM i AS LONG
LenIfT = LEN(ifT)
RValue = GetIfTable(ifT, LenIfT, 1)
FOR i = 0 TO ifT.dwNumEntries - 1
IF ifT.Table(i).dwType = 6 THEN
FUNCTION=(ifT.Table(i).dwIndex)
END IF
NEXT
END FUNCTION 额。。。不好意思,我也是菜鸟。。。
还要请pusofalse兄出手啊。 高人,这段代码是上面的DELPHI代码翻译过来的?造福人类啊,强烈建议放到汉化版里面去!
:face (11): 本帖最后由 sensel 于 2009-5-29 15:06 编辑
照葫芦画瓢。。。
弄了半天总算可以了。_GetIfTable()返回数组,第一个 = 6的元素,即为第一个可用接口的索引。
代码见下帖。有个问题,DllStructGetData($tIfTable, $i)返回值是空的,我不懂。。。 本帖最后由 sensel 于 2009-5-29 19:07 编辑
总算可用了,跟arp.exe说声88~~~
我又乱改pusofalse兄的代码了。。。pusofalse兄请勿见怪:face (29):
最终结果。。。不玩了
Opt("MustDeclareVars", 1)
Local Const $sIP = "192.168.0.22", $sMac = "00:20:21:22:CC:DD"
Local $aIfTable, $iIndex = 0
$aIfTable = _GetIfTable()
For $i = 1 To $aIfTable
If $aIfTable[$i] = 6 Then
_FlushIpNetTable($aIfTable[$i]) ; 清空ARP表
If $iIndex = 0 Then $iIndex = $aIfTable[$i] ; 获取第一个可用网络适配器索引号
EndIf
Next
If $iIndex <> 0 Then ; 绑定 MAC
_SetIpNetEntry($iIndex, $sIP, $sMac)
EndIf
Exit
;===============================================================================
; 说明: 获取 IP地址-物理地址 映射表
; 语法: _GetIpNetTable([$sIPAddr = ""])
; 参数: $sIPAddr - [可选] IP地址
; 需要: 无
; 返回: 成功 - 二维数组, 结构:
; $array - ARP项目总数
; $array - 网络适配器索引号
; $array - IP地址
; $array - 物理地址
; $array - ARP项目类型: 4 - 静态, 3 - 动态, 2 - 无效, 1 - 其他
; ...
; 至 - 第 n ARP项目信息
; 失败 - 空列表数组 = 0, 并设置 @error 到 1, @extended 到API操作返回值
; 备注: 出处: http://www.autoitx.com/forum.php?mod=viewthread&tid=7308 3#, 作者: pusofalse
;===============================================================================
Func _GetIpNetTable($sIPAddr = "")
Local $aResult, $sAddr, $sPhysAddr, $iPhysAddrLen, $iIndex = 0, $aIpNetTable = []
Local $tBuffer, $pBuffer, $tNum, $tagIpTable = "", $tIpTable, $iNumber
$aResult = DllCall("iphlpapi.dll", "dword", "GetIpNetTable", _
"ptr", 0, "int*", 0, "int", 1)
If $aResult = 0 Then Return SetError(1, $aResult, $aIpNetTable)
$tBuffer = DllStructCreate("ubyte[" & $aResult & "]")
$pBuffer = DllStructGetPtr($tBuffer)
$aResult = DllCall("iphlpapi.dll", "dword", "GetIpNetTable", _
"ptr", $pBuffer, "int*", $aResult, "int", 1)
$tNum = DllStructCreate("dword", $pBuffer)
$iNumber = DllStructGetData($tNum, 1)
For $i = 1 To $iNumber
$tagIpTable &= ";dword;byte;dword"
Next
$tIpTable = DllStructCreate("dword" & $tagIpTable, $pBuffer)
For $i = 2 To $iNumber * 3 Step 3
$sAddr = DllStructGetData($tIpTable, $i + 2, 1)
$sAddr = _inet_ntoa($sAddr)
$iPhysAddrLen = DllStructGetData($tIpTable, $i, 2)
$sPhysAddr = DllStructGetData($tIpTable, $i + 1)
$sPhysAddr = StringLeft($sPhysAddr, 2 + $iPhysAddrLen * 2)
$sPhysAddr = _FormatMac($sPhysAddr)
If $sIPAddr <> "" AND $sIPAddr <> $sAddr Then ContinueLoop
$iIndex += 1
ReDim $aIpNetTable[$iIndex + 1]
$aIpNetTable[$iIndex] = DllStructGetData($tIpTable, $i, 1)
$aIpNetTable[$iIndex] = $sAddr
$aIpNetTable[$iIndex] = $sPhysAddr
$aIpNetTable[$iIndex] = DllStructGetData($tIpTable, $i + 2, 2)
Next
$aIpNetTable = $iIndex
Return SetError($aResult, 0, $aIpNetTable)
EndFunc ;==>_GetIpNetTable
;===============================================================================
; 说明: 获取 MIB-II 接口表
; 语法: _GetIfTable()
; 参数: 无
; 需要: 无
; 返回: 成功 - 二维数组, 结构:
; $array - 接口总数
; $array - 第一接口索引号
; $array - 第一接口名称
; $array - 第一接口类型
; $array - 第一接口MTU字节数
; $array - 第一接口连接速度
; $array - 第一接口物理地址
; $array - 第一接口管理状态
; $array - 第一接口操作状态
; $array - 第一接口持续时间
; $array - 第一接口接收字节数
; $array - 第一接口接收单播数据包
; $array - 第一接口接收广播和组播数据包
; $array - 第一接口接收数据包丢弃数
; $array - 第一接口接收数据包错误数
; $array - 第一接口接收未知协议数据包
; $array - 第一接口发送字节数
; $array - 第一接口发送单播数据包
; $array - 第一接口发送广播和组播数据包
; $array - 第一接口发送数据包丢弃数
; $array - 第一接口发送数据包错误数
; $array - 第一接口传输队列长度
; $array - 第一接口描述
; ...
; 至 - 第 n 接口信息
; 失败 - 空列表数组 = 0, 并设置 @error 到 1, @extended 到API操作返回值
; 备注: 参考: http://www.autoitx.com/forum.php?mod=viewthread&tid=7308 3#
;===============================================================================
Func _GetIfTable()
Local $aResult, $sPhysAddr, $iPhysAddrLen, $sDescr, $iDescrLen, $iIndex = 0, $aIfTable = []
Local $tBuffer, $pBuffer, $tNum, $tagIfTable = "", $tIfTable
$aResult = DllCall("iphlpapi.dll", "dword", "GetIfTable", _
"ptr", 0, "int*", 0, "int", 1)
If $aResult = 0 Then Return SetError(1, $aResult, $aIfTable)
$tBuffer = DllStructCreate("ubyte[" & $aResult & "]")
$pBuffer = DllStructGetPtr($tBuffer)
$aResult = DllCall("iphlpapi.dll", "dword", "GetIfTable", _
"ptr", $pBuffer, "int*", $aResult, "int", 1)
$tNum = DllStructCreate("dword", $pBuffer)
$aIfTable = DllStructGetData($tNum, 1)
For $i = 1 To $aIfTable
$tagIfTable &= ";wchar;dword;byte;dword;byte"
Next
$tIfTable = DllStructCreate("dword" & $tagIfTable, $pBuffer)
ReDim $aIfTable[$aIfTable + 1]
For $i = 2 To $aIfTable * 5 Step 5
$iPhysAddrLen = DllStructGetData($tIfTable, $i + 1, 5)
$sPhysAddr = DllStructGetData($tIfTable, $i + 2)
$sPhysAddr = StringLeft($sPhysAddr, 2 + $iPhysAddrLen * 2)
$sPhysAddr = _FormatMac($sPhysAddr)
$iDescrLen = DllStructGetData($tIfTable, $i + 3, 16)
$sDescr = DllStructGetData($tIfTable, $i + 4)
$sDescr = StringLeft($sDescr, $iDescrLen * 2)
$sDescr = BinaryToString($sDescr)
$iIndex += 1
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 1, 1)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 1, 2)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 1, 3)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 1, 4)
$aIfTable[$iIndex] = $sPhysAddr
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 1)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 2)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 3)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 4)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 5)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 6)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 7)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 8)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 9)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 10)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 11)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 12)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 13)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 14)
$aIfTable[$iIndex] = DllStructGetData($tIfTable, $i + 3, 15)
$aIfTable[$iIndex] = $sDescr
Next
Return SetError($aResult, 0, $aIfTable)
EndFunc ;==>_GetIfTable
;===============================================================================
; 说明: 更改ARP表项目
; 语法: _SetIpNetEntry($iAdptIndex, $sAddr, $sMac[, $sType = "Static"])
; 参数: $iAdptIndex - 网络适配器索引号
; $sAddr - IP地址
; $sMac - 物理地址
; $sType - [可选] ARP项目类型, "Static" - 静态, "Dynamic" - 动态
; 需要: 无
; 返回: 成功 - 1
; 失败 - 0, 并设置 @error 到 API操作返回值
; 备注: 出处: http://www.autoitx.com/forum.php?mod=viewthread&tid=7308 3#, 作者: pusofalse
;===============================================================================
Func _SetIpNetEntry($iAdptIndex, $sAddr, $sMac, $sType = "Static")
Local $aResult, $iAddr, $iMac, $tIpNetRow, $pIpNetRow, $iType
If $sType = "Dynamic" Then
$iType = 3
Else
$iType = 4
EndIf
$iAddr = _inet_addr($sAddr)
$iMac = _FormatMac($sMac, 0)
$tIpNetRow = DllStructCreate("dword;byte;dword")
$pIpNetRow = DllStructGetPtr($tIpNetRow)
DllStructSetData($tIpNetRow, 1, $iAdptIndex, 1)
DllStructSetData($tIpNetRow, 1, (StringLen($iMac) - 2) / 2, 2)
DllStructSetData($tIpNetRow, 2, $iMac)
DllStructSetData($tIpNetRow, 3, $iAddr, 1)
DllStructSetData($tIpNetRow, 3, $iType, 2)
$aResult = DllCall("iphlpapi.dll", "long", "SetIpNetEntry", "ptr", $pIpNetRow)
Return SetError($aResult, 0, $aResult = 0)
EndFunc ;==>_SetIpNetEntry
;===============================================================================
; 说明: 删除ARP表项目
; 语法: _DeleteIpNetEntry($iAdptIndex, $sAddr)
; 参数: $iAdptIndex - 网络适配器索引号
; $sAddr - IP地址
; 需要: 无
; 返回: 成功 - 1
; 失败 - 0, 并设置 @error 到 API操作返回值
; 备注: 出处: http://www.autoitx.com/forum.php?mod=viewthread&tid=7308 3#, 作者: pusofalse
;===============================================================================
Func _DeleteIpNetEntry($iAdptIndex, $sAddr)
Local $aResult, $iAddr, $tIpNetRow, $pIpNetRow
$iAddr = _inet_addr($sAddr)
$tIpNetRow = DllStructCreate("dword;byte;dword")
$pIpNetRow = DllStructGetPtr($tIpNetRow)
DllStructSetData($tIpNetRow, 1, $iAdptIndex, 1)
DllStructSetData($tIpNetRow, 3, $iAddr, 1)
$aResult = DllCall("iphlpapi.dll", "long", "DeleteIpNetEntry", "ptr", $pIpNetRow)
Return SetError($aResult, 0, $aResult = 0)
EndFunc ;==>_DeleteIpNetEntry
;===============================================================================
; 说明: 清空指定网络适配器ARP表项目
; 语法: _FlushIpNetTable($iAdptIndex)
; 参数: $iAdptIndex - 网络适配器索引号
; 需要: 无
; 返回: 成功 - 1
; 失败 - 0, 并设置 @error 到 API操作返回值
; 备注: 出处: http://www.autoitx.com/forum.php?mod=viewthread&tid=7308 3#, 作者: pusofalse
;===============================================================================
Func _FlushIpNetTable($iAdptIndex)
Local $aResult
$aResult = DllCall("iphlpapi.dll", "long", "FlushIpNetTable", "long", $iAdptIndex)
Return SetError($aResult, 0, $aResult = 0)
EndFunc ;==>_FlushIpNetTable
Func _inet_addr($sAddr)
Local $iAddr = DllCall("ws2_32.dll", "long", "inet_addr", "str", $sAddr)
Return $iAddr
EndFunc ;==>_inet_addr
Func _inet_ntoa($iAddr)
Local $sAddr = DllCall("ws2_32.dll", "str", "inet_ntoa", "long", $iAddr)
Return $sAddr
EndFunc ;==>_inet_ntoa
Func _FormatMac($sMac, $iString = True)
If $iString Then
$sMac = StringTrimLeft($sMac, 2)
Return StringTrimRight(StringRegExpReplace($sMac, ".{2}", "\0:"), 1)
Else
Return "0x" & StringReplace($sMac, ":", "")
EndIf
EndFunc ;==>_FormatMac 天哪,_GetIpNetTable()需要这么多代码啊?
页:
[1]
2