【问题标题】:How can I get the arp table from a windows machine using python?如何使用 python 从 Windows 机器获取 arp 表?
【发布时间】:2020-01-22 10:14:32
【问题描述】:

我想使用 Python 从 Windows 系统中获取 arp 表。 我看到库python_arptable 只与linux 兼容,我不想使用arp -a 命令。 是否有任何 python 库可以让我提取它?或者也许使用 ctypes?

【问题讨论】:

标签: python-3.x ctypes arp


【解决方案1】:

为什么不使用arp -a?如果不出意外,您可以使用os.popen 捕获并解析:

>>> import os
>>> with os.popen('arp -a') as f:
...  data = f.read()
...
>>> import re
>>> for line in re.findall('([-.0-9]+)\s+([-0-9a-f]{17})\s+(\w+)',data):
...  print(line)
...
('192.168.1.1', 'cc-40-d0-19-73-e8', 'dynamic')
('192.168.1.2', 'e0-89-7e-15-f3-c0', 'dynamic')
('192.168.1.4', 'd0-d2-b0-12-c0-d1', 'dynamic')
('192.168.1.7', '00-11-d9-66-13-9d', 'dynamic')
('224.0.0.22', '01-00-5e-00-00-16', 'static')
('224.0.0.251', '01-00-5e-00-00-fb', 'static')
('224.0.0.252', '01-00-5e-00-00-fc', 'static')
('224.0.2.60', '01-00-5e-00-02-3c', 'static')
('239.255.255.250', '01-00-5e-7f-ff-fa', 'static')
('255.255.255.255', 'ff-ff-ff-ff-ff-ff', 'static')

否则,这是一个不太直接的 ctypes 解决方案(Python 3.6+):

from ctypes import *
from ctypes import wintypes as w
import struct

MAXLEN_PHYSADDR = 8

TYPE = {1:'other',2:'invalid',3:'dynamic',4:'static'}

class MIB_IPNETROW(Structure):
    _fields_ = (('dwIndex',w.DWORD),
                ('dwPhysAddrLen',w.DWORD),
                ('bPhysAddr',w.BYTE * MAXLEN_PHYSADDR),
                ('dwAddr',w.DWORD),
                ('dwType',w.DWORD))
    def __repr__(self):
        ip = struct.pack('<L',self.dwAddr)
        ip = f'{ip[0]}.{ip[1]}.{ip[2]}.{ip[3]}'
        mac = bytes(self.bPhysAddr)[:self.dwPhysAddrLen]
        mac = '-'.join(f'{b:02x}' for b in mac)
        return f"MIB_IPNETROW({self.dwIndex},{mac},{ip},{TYPE[self.dwType]})"

# ctypes doesn't do variable size-d structures well.
# This helper generates an IPNETTABLE class with a table
# array equal to "n".
def TABLE(n):
    class _MIB_IPNETTABLE(Structure):
        _fields_ = (('dwNumEntries',w.DWORD),
                    ('table',MIB_IPNETROW * n))
    return _MIB_IPNETTABLE

MIB_IPNETTABLE = TABLE(0) # general version to use with pointers.

dll = WinDLL('iphlpapi')
dll.GetIpNetTable.argtypes = POINTER(MIB_IPNETTABLE),w.PULONG,w.BOOL
dll.GetIpNetTable.restype = w.ULONG

# Query with a buffer size of zero to get actual size
size = w.DWORD(0)
dll.GetIpNetTable(None,byref(size),True)

# Generate buffer of correct size and pointer type.
buf = cast(create_string_buffer(b'',size=size.value),POINTER(MIB_IPNETTABLE))

# Get the table and cast to the specific table size
dll.GetIpNetTable(buf,byref(size),True)
buf = cast(buf,POINTER(TABLE(buf.contents.dwNumEntries)))

# Display the table entries (leverages __repr__ defined above)
for t in buf.contents.table:
    if t.dwType != 2 and t.dwPhysAddrLen: # not invalid and has an address
        print(t)
MIB_IPNETROW(11,cc-40-d0-19-73-e8,192.168.1.1,dynamic)
MIB_IPNETROW(11,e0-89-7e-15-f3-c0,192.168.1.2,dynamic)
MIB_IPNETROW(11,d0-d2-b0-12-c0-d1,192.168.1.4,dynamic)
MIB_IPNETROW(11,00-11-d9-66-13-9d,192.168.1.7,dynamic)
MIB_IPNETROW(11,ff-ff-ff-ff-ff-ff,192.168.1.255,static)
MIB_IPNETROW(11,01-00-5e-00-00-16,224.0.0.22,static)
MIB_IPNETROW(11,01-00-5e-00-00-fb,224.0.0.251,static)
MIB_IPNETROW(11,01-00-5e-00-00-fc,224.0.0.252,static)
MIB_IPNETROW(11,01-00-5e-7f-ff-fa,239.255.255.250,static)
MIB_IPNETROW(11,ff-ff-ff-ff-ff-ff,255.255.255.255,static)
MIB_IPNETROW(16,01-00-5e-00-00-16,224.0.0.22,static)

【讨论】:

  • 嘿,除了wintypes.PULONG和字符串格式,为什么不兼容python2.x?
猜你喜欢
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
相关资源
最近更新 更多