Почему бы не использовать 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)