找回密码
 加入
搜索
查看: 2927|回复: 5

[网络通信] 用已知MAC地址返回IP地址的方案探讨,高手进

[复制链接]
发表于 2016-4-15 22:51:30 | 显示全部楼层 |阅读模式
本帖最后由 txm888 于 2016-4-17 10:26 编辑

最近很苦恼的烦心事儿,在局域网内有一大批路由器需要管理,且路由器的wan接口是动态获取IP的,这些路由器是跨网段的,想登陆路由器管理,得去现场。

脑洞大开,想要是能用每个路由器的mac地址返回IP再登陆管理界面操作不是更方便吗?
在论坛搜索了2天,只有ip mac扫描工具,1-255尽然最快也要花3/4秒,如果跨网段速度慢得不惊人,
请问大师们,能否进行UDP广播包的方式,套出IP对应mac的IP地址?
如果有思路,可付费索取,期待,谢谢!

mac地址扫描的有很多,如纯au3 P版大侠杰作:http://www.autoitx.com/forum.php ... =mac%2B%C9%A8%C3%E8


如下代码可能是个办法,但是JAVA的办法,要是能翻译为AU3的就好了
Java远程获取MAC地址代码

java 
Java代码  
package com.thunisoft.shxt.support.macAddr;  
  
import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.DatagramSocket;  
import java.net.InetAddress;  
import java.net.SocketException;  
import java.net.SocketTimeoutException;  
  
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
  
/** 
 * 主机A向主机B发送“UDP-NetBIOS-NS”询问包,即向主机B的137端口,发Query包来询问主机B的NetBIOS Names信息。 
 * 其次,主机B接收到“UDP-NetBIOS-NS”询问包, 
 * 假设主机B正确安装了NetBIOS服务........... 而且137端口开放, 
 * 则主机B会向主机A发送一个“UDP-NetBIOS-NS”应答包,即发Answer包给主机A。 
 * 并利用UDP(NetBIOS Name Service)来快速获取远程主机MAC地址的方法 
 * @author lijt 
 */  
  
public class UdpGetClientMacAddr {  
      
    private static Log log = LogFactory.getLog(UdpGetClientMacAddr.class);  
      
    private String         remoteAddr;  
    private int            remotePort = 137;  
    private byte[]         buffer      = new byte[1024];  
    private DatagramSocket ds          = null;  
  
    public UdpGetClientMacAddr(String strAddr) throws Exception {  
        remoteAddr = strAddr;  
        ds = new DatagramSocket();  
    }  
  
    //发送数据包  
    protected final DatagramPacket send(final byte[] bytes) throws IOException {  
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(remoteAddr), remotePort);  
        ds.send(dp);  
        return dp;  
    }  
    //接收数据包  
    protected final DatagramPacket receive() {  
        DatagramPacket dp = new DatagramPacket(buffer, buffer.length);  
        try {  
            ds.setSoTimeout(3000);  
            ds.receive(dp);   
        }catch(SocketTimeoutException  ex) {     
           log.info("接收数据超时...,不能获取客户端MAC地址");  
          //  throw new SocketTimeoutException("连接超时");  
        }  catch (SocketException e1) {  
            log.error("发生Sorcket异常..."+e1.getMessage());  
            e1.printStackTrace();  
        }catch (IOException e2) {  
            log.error("发生IO异常..."+e2.getMessage());  
        }  
        return dp;  
    }  
  
    // 询问包结构:  
    // Transaction ID 两字节(16位) 0x00 0x00  
    // Flags 两字节(16位) 0x00 0x10  
    // Questions 两字节(16位) 0x00 0x01  
    // AnswerRRs 两字节(16位) 0x00 0x00  
    // AuthorityRRs 两字节(16位) 0x00 0x00  
    // AdditionalRRs 两字节(16位) 0x00 0x00  
    // Name:array [1..34] 0x20 0x43 0x4B 0x41(30个) 0x00 ;  
    // Type:NBSTAT 两字节 0x00 0x21  
    // Class:INET 两字节(16位)0x00 0x01  
    protected byte[] getQueryCmd() throws Exception {  
        byte[] t_ns = new byte[50];  
        t_ns[0] = 0x00;  
        t_ns[1] = 0x00;  
        t_ns[2] = 0x00;  
        t_ns[3] = 0x10;  
        t_ns[4] = 0x00;  
        t_ns[5] = 0x01;  
        t_ns[6] = 0x00;  
        t_ns[7] = 0x00;  
        t_ns[8] = 0x00;  
        t_ns[9] = 0x00;  
        t_ns[10] = 0x00;  
        t_ns[11] = 0x00;  
        t_ns[12] = 0x20;  
        t_ns[13] = 0x43;  
        t_ns[14] = 0x4B;  
  
        for (int i = 15; i < 45; i++) {  
            t_ns[i] = 0x41;  
        }  
  
        t_ns[45] = 0x00;  
        t_ns[46] = 0x00;  
        t_ns[47] = 0x21;  
        t_ns[48] = 0x00;  
        t_ns[49] = 0x01;  
        return t_ns;  
    }  
  
    // 表1 “UDP-NetBIOS-NS”应答包的结构及主要字段一览表  
    // 序号 字段名 长度  
    // 1 Transaction ID 两字节(16位)  
    // 2 Flags 两字节(16位)  
    // 3 Questions 两字节(16位)  
    // 4 AnswerRRs 两字节(16位)  
    // 5 AuthorityRRs 两字节(16位)  
    // 6 AdditionalRRs 两字节(16位)  
    // 7 Name<Workstation/Redirector> 34字节(272位)  
    // 8 Type:NBSTAT 两字节(16位)  
    // 9 Class:INET 两字节(16位)  
    // 10 Time To Live 四字节(32位)  
    // 11 Length 两字节(16位)  
    // 12 Number of name 一个字节(8位)  
    // NetBIOS Name Info 18×Number Of Name字节  
    // Unit ID 6字节(48位  
  
    protected final String getMacAddr(byte[] brevdata) throws Exception {  
        // 获取计算机名  
     //   System.out.println(new String(brevdata, 57, 18));  
     //   System.out.println(new String(brevdata, 75, 18));  
     //   System.out.println(new String(brevdata, 93, 18));  
        int i = brevdata[56] * 18 + 56;  
        String sAddr = "";  
        StringBuffer sb = new StringBuffer(17);  
        // 先从第56字节位置,读出Number Of Names(NetBIOS名字的个数,其中每个NetBIOS Names Info部分占18个字节)  
        // 然后可计算出“Unit ID”字段的位置=56+Number Of Names×18,最后从该位置起连续读取6个字节,就是目的主机的MAC地址。  
        for (int j = 1; j < 7; j++) {  
            sAddr = Integer.toHexString(0xFF & brevdata[i + j]);  
            if (sAddr.length() < 2) {  
                sb.append(0);  
            }  
            sb.append(sAddr.toUpperCase());  
            if (j < 6) sb.append('-');  
        }  
        return sb.toString();  
    }  
  
    public final void close() {  
        try {  
            ds.close();  
        } catch (Exception ex) {  
            ex.printStackTrace();  
        }  
    }  
  
    /** 
     * 获取远程主机的mac地址 
     * @return 
     * @throws Exception 
     */  
    public final String getRemoteMacAddr() throws Exception {  
        byte[] bqcmd = getQueryCmd();  
        this.send(bqcmd);  
        DatagramPacket dp = receive();  
        String smac ="";  
        smac = getMacAddr(dp.getData());  
        this.close();  
        return smac;  
    }  
   public static void  main(String[] args) throws Exception  
   {  
       UdpGetClientMacAddr  add = new UdpGetClientMacAddr("172.16.26.52");  
       System.out.println(add.getRemoteMacAddr());  
   }  
  
}  
http://thinkblog.iteye.com/blog/1499877
 楼主| 发表于 2016-4-17 10:14:58 | 显示全部楼层
找到了下面这篇文章,但不知道如何弄:
http://bbs.csdn.net/topics/70071564
发表于 2016-4-18 09:15:59 | 显示全部楼层
插WAN口 要把路由器的远程管理开起来才可以管理的吧
 楼主| 发表于 2016-4-18 13:20:32 | 显示全部楼层
回复 3# lin6051


    发现也不是个办法,上级把wan口各IP隔立起来了,扫描不到
只有一个办法,拨号成功后,向某台电脑发个消息,但需要路由器支持
发表于 2016-4-18 13:41:00 | 显示全部楼层
[参考如下代码(转自官网)]

#include <Date.au3>

;===============================================================================
;
; Description:      Get DHCP Client Attributes by IP Address, MAC or Name
; Parameter(s):     $sDHCP - IP Address of DHCP Server
;                   $ClientID - Client IP, MAC or Name (String or Native Format)
;                     Integer - native format for IP Address/Mask
;                     Binary  - native format for MAC Address (6 bytes)
;                   $iIDType - type of ClientID information:
;                     0 - Auto-define by value
;                     1 - Client IP address
;                     2 - Client Hardware (MAC) address
;                     3 - Client Name
;                   $iFlags - Config Flags:
;                     0x1- Output Format (0-Text, 1-Native)
; Requirement(s):   Testing
; Return Value(s):  On Success - The array of parameters with indexes
;                     0 - Client IP address
;                     1 - Client IP subnet mask
;                     2 - Client MAC address
;                     3 - Client Name
;                     4 - Client Comment
;                     5 - Client Lease Expires Time
;                   On Failure - Null, @error set to
;                     1 - Client not found on DHCP server
;                     2 - Invalid ClientID parameter
;                     3 - Operating System not supported
;                     4 - Any Runtime Error, API Error Code set to @extended
; Author(s):         amel27 (Alexander Melnichuk)
; Note(s):           Client Name is case sensitive
;
;===============================================================================

Func _DHCP_GetClientInfo($sDHCP, $ClientID, $iIDType=0, $iFlags=0)
    ; Create DHCP_SEARCH_INFO Structure
    Local $tSearchInfo= DllStructCreate("int SearchType;int DataLength;ptr DataPtr")
    Local $iSearchInfoPtr = DllStructGetPtr($tSearchInfo), $aSubnets[2]=[1,0], $iType=0
    Local $tBinaryData = DllStructCreate("dword SubnetIPAddress;ubyte HardwareID;ubyte MACAddress[6]")
    ; Check Client ID Parameter and Define SearchInfo Type
    If IsInt($ClientID) Then
        If $iIDType=0 Or $iIDType=1 Then $iType = 1
    ElseIf IsBinary($ClientID) Then
        If BinaryLen($ClientID)=6 And ($iIDType=0 Or $iIDType=2) Then $iType = 2
    ElseIf IsString($ClientID) Then
        If StringRegExp($ClientID, "^(\d+\.){3}\d+$") Then
            ; Get IP DWord type from String
            Local $aOctets = StringSplit($ClientID, "."), $iClientIP = 0
            For $i=1 To 4
                If BitAND($aOctets[$i], 0xFFFFFF00) Then Return SetError(2) ; ERR: Invalid Client IP Address
                $iClientIP = BitOR(BitRotate($iClientIP, 8, "D"), $aOctets[$i])
            Next
            $ClientID = $iClientIP
            If $iIDType=0 Or $iIDType=1 Then $iType = 1
        ElseIf StringRegExp($ClientID,"^(0[xX])?[[:xdigit:]]{2}((:|-)?[[:xdigit:]]{2}){5}$") Then
            $ClientID = Binary("0x"& StringRegExpReplace($ClientID,"(0[xX]|:|-)",""))
            If $iIDType=0 Or $iIDType=2 Then $iType = 2
        Else
            If $iIDType=0 Or $iIDType=3 Then $iType = 3
        EndIf
    EndIf
    If $iType =0 Then Return SetError(2)
    ; Route the filling of DHCP_SEARCH_INFO structure
    Switch $iType
        Case 1
            ; Filling DHCP_SEARCH_INFO for search by client IP address
            Local $tSearchInfo_IP = DllStructCreate("int SearchType;dword ClientIPAddress", $iSearchInfoPtr)
            DllStructSetData($tSearchInfo_IP, "SearchType", 0)
            DllStructSetData($tSearchInfo_IP, "ClientIPAddress", $ClientID)
        Case 2
            ; Filling DHCP_SEARCH_INFO for search by client MAC address
            DllStructSetData($tSearchInfo, "SearchType", 1)
            DllStructSetData($tSearchInfo, "DataLength", 11)
            DllStructSetData($tSearchInfo, "DataPtr", DllStructGetPtr($tBinaryData))
            ; Filling DHCP_BINARY_DATA
            DllStructSetData($tBinaryData, "HardwareID", 0x01)
            DllStructSetData($tBinaryData, "MACAddress", $ClientID)
            ; Get Array of DHCP Subnets
            $aSubnets = _DHCP_EnumSubnets($sDHCP, 1)
            If @error=1 Then Return SetError(1)
            If @error=2 Then Return SetError(4, @extended)
        Case 3
            ; Filling DHCP_SEARCH_INFO for search by client Name
            Local $tSearchInfo_Name = DllStructCreate("int SearchType;ptr ClientNamePtr", $iSearchInfoPtr)
            Local $tClientNameString= DllStructCreate("wchar ClientName["& StringLen($ClientID)+1 &"]")
            DllStructSetData($tSearchInfo_Name, "SearchType", 2)
            DllStructSetData($tSearchInfo_Name, "ClientNamePtr", DllStructGetPtr($tClientNameString))
            DllStructSetData($tClientNameString, "ClientName", $ClientID)
    EndSwitch
    ; Call  DhcpGetClientInfo API function
    Local $tClientInfo_Ptr = DllStructCreate("ptr"), $aRet, $aRes[6]
    For $i=1 To $aSubnets[0]
        DllStructSetData($tBinaryData, "SubnetIPAddress", $aSubnets[$i])
        $aRet = DllCall("Dhcpsapi.dll", "int", "DhcpGetClientInfo", _
            "wstr", $sDHCP, _
            "ptr", $iSearchInfoPtr, _
            "ptr", DllStructGetPtr($tClientInfo_Ptr) )
        If @error Then Return SetError(3, @error) ; ERR: Invalid DLL or Function Name
        If $aRet[0]<>20013 Then ExitLoop
    Next
    If $aRet[0]=20013 Then Return SetError(1, $aRet[0]) ; ERR: Client not found
    If $aRet[0] Then Return SetError(4, $aRet[0]) ; ERR: Any runtime errors
    ; DHCP_CLIENT_INFO structure
    Local $tClientInfo = DllStructCreate("dword ClientIpAddress;dword SubnetMask;int BinaryLen;ptr BinaryPtr;" & _
        "ptr ClientNamePtr;ptr ClientCommentPtr;ubyte ClientLeaseExpires[8];dword OwnerHostIPAddress;" & _
        "ptr OwnerHostNetBiosNamePtr;ptr OwnerHostNamePtr", DllStructGetData($tClientInfo_Ptr,1))
    Local $tClientBinary = DllStructCreate("ubyte BinaryData[6]", DllStructGetData($tClientInfo, "BinaryPtr"))
    ; Get IP Address
    $aRes[0] = DllStructGetData($tClientInfo, "ClientIpAddress")
    If BitAND($iFlags,1)=0 Then $aRes[0] = BitRotate(BitAND($aRes[0],0xFF000000), 8,"D") &"."& _
        BitRotate(BitAND($aRes[0],0x00FF0000),16,"D") &"."& _
        BitRotate(BitAND($aRes[0],0x0000FF00),-8,"W") &"."& BitAND($aRes[0],0x000000FF)
    ; Get IP Mask
    $aRes[1] = DllStructGetData($tClientInfo, "SubnetMask")
    If BitAND($iFlags,1)=0 Then $aRes[1]=BitRotate(BitAND($aRes[1],0xFF000000), 8,"D") &"."& _
        BitRotate(BitAND($aRes[1],0x00FF0000),16,"D") &"."& _
        BitRotate(BitAND($aRes[1],0x0000FF00),-8,"W") &"."& BitAND($aRes[1],0x000000FF)
    ; Get MAC Address
    $aRes[2] = DllStructGetData($tClientBinary, "BinaryData")
    If BitAND($iFlags,1)=0 Then $aRes[2] = String($aRes[2])
    ; Get Client Name
    Local $tClientNameString = DllStructCreate("wchar ClientName[255]", DllStructGetData($tClientInfo, "ClientNamePtr"))
    $aRes[3] = DllStructGetData($tClientNameString, "ClientName")
    ; Get Client Comment
    Local $tClientNameString = DllStructCreate("wchar ClientComment[255]", DllStructGetData($tClientInfo, "ClientCommentPtr"))
    $aRes[4] = DllStructGetData($tClientNameString, "ClientComment")
    ; Get Client Lease Expire Time
    $aRes[5] = DllStructGetData($tClientInfo, "ClientLeaseExpires")
    If BitAND($iFlags,1)=0 Then
        $aRes[5] = _Date_Time_FileTimeToLocalFileTime(DllStructGetPtr($tClientInfo, "ClientLeaseExpires"))
        $aRes[5] = _Date_Time_FileTimeToStr($aRes[5])
    EndIf
    ; Freeing a memory
    DllCall("Dhcpsapi.dll", "none", "DhcpRpcFreeMemory", "ptr", DllStructGetData($tClientInfo_Ptr,1))
    Return $aRes
EndFunc ;==> _DHCP_GetClientInfo


;===============================================================================
;
; Description:      Get List of DHCP Scopes
; Parameter(s):     $sDHCP - IP Address of DHCP Server
;                   $iFlags - Config Flags:
;                     0x1- Output Format (0-Text, 1-Native)
; Requirement(s):   Testing
; Return Value(s):  On Success - The array subnet of IP Addresses
;                     element with index 0 is count of scopes
;                   On Failure - @error set to
;                     1 - Scopes not defined, returned empty array
;                     2 - Any Runtime Error, invalid array,
;                         API Error Code set to @extended
; Author(s):         amel27 (Alexander Melnichuk)
; Note(s):
;
;===============================================================================
Func _DHCP_EnumSubnets($sDHCP, $iFlags=0)
    Local $tEnumSubnetsParms = DllStructCreate("hwnd ResumeHandle;ptr EnumInfoPtr;int ElementsRead;int ElementsTotal")
    Local $aSubnets[1]=[0], $tIPArray, $tAddress, $aRet
    Do
        $aRet = DllCall("Dhcpsapi.dll", "int", "DhcpEnumSubnets", _
            "wstr", $sDHCP, _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "ResumeHandle"), _
            "int", 100, _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "EnumInfoPtr") , _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "ElementsRead"), _
            "ptr" , DllStructGetPtr($tEnumSubnetsParms, "ElementsTotal") )
        If $aRet[0] Then Return SetError(2, $aRet[0]) ; ERR: Any runtime errors
        If DllStructGetData($tEnumSubnetsParms,"EnumInfoPtr")=0 Then Return SetError(1, 0, $aSubnets) ; ERR: Not Found
        $tIPArray = DllStructCreate("int NumElements;ptr Elements", DllStructGetData($tEnumSubnetsParms,"EnumInfoPtr"))
        ReDim $aSubnets[$aSubnets[0] + DllStructGetData($tIPArray,"NumElements") +1]
        For $i=$aSubnets[0]+1 To UBound($aSubnets)-1
            $tAddress = DllStructCreate("dword SubNetAddess", DllStructGetData($tIPArray,2) + ($i-$aSubnets[0]-1)*4)
            $aSubnets[$i]=DllStructGetData($tAddress, "SubNetAddess")
            If BitAND($iFlags,1)=0 Then $aSubnets[$i] = BitRotate(BitAND($aSubnets[$i],0xFF000000), 8,"D") _
                &"."& BitRotate(BitAND($aSubnets[$i],0x00FF0000),16,"D") _
                &"."& BitRotate(BitAND($aSubnets[$i],0x0000FF00),-8,"W") _
                &"."& BitAND($aSubnets[$i],0x000000FF)
        Next
        $aSubnets[0] += DllStructGetData($tIPArray,"NumElements")
    Until DllStructGetData($tEnumSubnetsParms,"ElementsRead") = DllStructGetData($tEnumSubnetsParms,"ElementsTotal")
    ; Freeing a memory
    DllCall("Dhcpsapi.dll", "none", "DhcpRpcFreeMemory", "ptr", DllStructGetData($tEnumSubnetsParms,"EnumInfoPtr"))
    Return $aSubnets
EndFunc ; => _DHCP_EnumSubnets

 
 楼主| 发表于 2016-4-19 10:47:01 | 显示全部楼层
回复 5# 虫子樱桃


    老大,没明白上面代码是操作什么的,能解释下或示范下吗?TKS
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-28 05:11 , Processed in 0.084339 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表