Проблема с использованием Win32 IPHelper API в Python - PullRequest
2 голосов
/ 24 сентября 2010

Я пытаюсь создать модуль Python для получения параметров сети. Я использую ctypes и у меня есть некоторые проблемы.

Функция __getInterfaces_win2k () работает с python 2.5 и 2.6, но не работает с python 2.7 (необработанное исключение 0x1e001759 в python.exe: 0xC0000005: место чтения нарушения доступа 0x00000010.)

Функция __getInterfaces_win_after_win2k () не работает ни в одной версии python (та же ошибка).

Иногда перед сбоем программы выводят необходимую информацию. Я пробовал сравнить практически все значения с программой на C. Все нормально. Любая помощь высоко ценится.

'''
    Get different network parameters (interfaces, routing table, etc)
'''

from platform import system
from sys import getwindowsversion

def getInterfaces():
    if system() == 'Windows':
        winversion = getwindowsversion() 
        #from table on page OSVERSIONINFO Structure for GetVersionEx Function
        if winversion[0] > 5 or (winversion[0] == 5 and winversion[1] > 0):
            return __getInterfaces_win_after_win2k()
        else:
            return __getInterfaces_win2k()
    else:
        pass

MAX_ADAPTER_ADDRESS_LENGTH = 8

def __getInterfaces_win_after_win2k():
    import ctypes.wintypes

    class HEADER_STRUCT(ctypes.Structure):
        _fields_ = [
            ("Length", ctypes.c_ulong),
            ("IfIndex", ctypes.c_ulong)]

    class HEADER_UNION(ctypes.Union):
        _fields_ = [
            ("Alignment", ctypes.c_ulonglong),
            ("HEADER_STRUCT", HEADER_STRUCT)]

    class SOCKADDR(ctypes.Structure):
        _fields_ = [
            ("sa_family", ctypes.c_ushort),
            ("sa_data", ctypes.c_byte * 14)]
    PSOCKADDR = ctypes.POINTER(SOCKADDR)

    class SOCKET_ADDRESS(ctypes.Structure):
        _fields_ = [
            ("pSockaddr", PSOCKADDR),
            ("iSockaddrLength", ctypes.c_int)]

    class IP_ADAPTER_UNICAST_ADDRESS(ctypes.Structure):
        pass
    PIP_ADAPTER_UNICAST_ADDRESS = ctypes.POINTER(IP_ADAPTER_UNICAST_ADDRESS)
    IP_ADAPTER_UNICAST_ADDRESS._fields_ = [
        ("length", ctypes.c_ulong),
        ("flags", ctypes.c_ulong),
        ("next", PIP_ADAPTER_UNICAST_ADDRESS),
        ("address", SOCKET_ADDRESS),
        ("prefixOrigin", ctypes.c_int),
        ("suffixOrigin", ctypes.c_int),
        ("dadState", ctypes.c_int),
        ("validLifetime", ctypes.c_ulong),
        ("preferredLifetime", ctypes.c_ulong),
        ("leaseLifetime", ctypes.c_ulong),
        ("onLinkPrefixLength", ctypes.c_byte)]

    class IP_ADAPTER_ANYCAST_ADDRESS(ctypes.Structure):
        pass
    PIP_ADAPTER_ANYCAST_ADDRESS = ctypes.POINTER(IP_ADAPTER_ANYCAST_ADDRESS)
    IP_ADAPTER_ANYCAST_ADDRESS._fields_ = [
        ("alignment", ctypes.c_ulonglong),
        ("next", PIP_ADAPTER_ANYCAST_ADDRESS),
        ("address", SOCKET_ADDRESS)]

    class IP_ADAPTER_MULTICAST_ADDRESS(ctypes.Structure):
        pass
    PIP_ADAPTER_MULTICAST_ADDRESS = ctypes.POINTER(IP_ADAPTER_MULTICAST_ADDRESS)
    IP_ADAPTER_MULTICAST_ADDRESS._fields_ = [
        ("alignment", ctypes.c_ulonglong),
        ("next", PIP_ADAPTER_MULTICAST_ADDRESS),
        ("address", SOCKET_ADDRESS)]

    class IP_ADAPTER_DNS_SERVER_ADDRESS(ctypes.Structure):
        pass
    PIP_ADAPTER_DNS_SERVER_ADDRESS = ctypes.POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)
    IP_ADAPTER_DNS_SERVER_ADDRESS._fields_ = [
        ("alignment", ctypes.c_ulonglong),
        ("next", PIP_ADAPTER_DNS_SERVER_ADDRESS),
        ("address", SOCKET_ADDRESS)]

    class IP_ADAPTER_PREFIX(ctypes.Structure):
        pass
    PIP_ADAPTER_PREFIX = ctypes.POINTER(IP_ADAPTER_PREFIX)
    IP_ADAPTER_PREFIX._fields_ = [
        ("alignment", ctypes.c_ulonglong),
        ("next", PIP_ADAPTER_PREFIX),
        ("address", SOCKET_ADDRESS),
        ("prefixLength", ctypes.c_ulong)]

    class IP_ADAPTER_WINS_SERVER_ADDRESS(ctypes.Structure):
        pass
    PIP_ADAPTER_WINS_SERVER_ADDRESS = ctypes.POINTER(IP_ADAPTER_WINS_SERVER_ADDRESS)
    IP_ADAPTER_WINS_SERVER_ADDRESS._fields_ = [
        ("alignment", ctypes.c_ulonglong),
        ("next", PIP_ADAPTER_WINS_SERVER_ADDRESS),
        ("address", SOCKET_ADDRESS)]

    class IP_ADAPTER_GATEWAY_ADDRESS(ctypes.Structure):
        pass
    PIP_ADAPTER_GATEWAY_ADDRESS = ctypes.POINTER(IP_ADAPTER_GATEWAY_ADDRESS)
    IP_ADAPTER_GATEWAY_ADDRESS._fields_ = [
        ("alignment", ctypes.c_ulonglong),
        ("next", PIP_ADAPTER_GATEWAY_ADDRESS),
        ("address", SOCKET_ADDRESS)]

    #ifdef.h
    class NET_LUID(ctypes.Structure):
        _fields_ = [
            ("value", ctypes.c_ulonglong)]

    class GUID(ctypes.Structure):
        _fields_ = [
            ("data1", ctypes.wintypes.DWORD),
            ("data2", ctypes.wintypes.WORD),
            ("data3", ctypes.wintypes.WORD),
            ("data4", ctypes.c_byte * 8)]

    MAX_DNS_SUFFIX_STRING_LENGTH = 256
    class IP_ADAPTER_DNS_SUFFIX(ctypes.Structure):
        pass
    PIP_ADAPTER_DNS_SUFFIX = ctypes.POINTER(IP_ADAPTER_DNS_SUFFIX)
    IP_ADAPTER_DNS_SUFFIX._fields_ = [
        ("next", PIP_ADAPTER_DNS_SUFFIX),
        ("string", ctypes.c_wchar * MAX_DNS_SUFFIX_STRING_LENGTH)]

    class IP_ADAPTER_ADDRESSES(ctypes.Structure):
        pass
    PIP_ADAPTER_ADDRESSES = ctypes.POINTER(IP_ADAPTER_ADDRESSES)
    MAX_DHCPV6_DUID_LENGTH = 130 #IPTypes.h
    IP_ADAPTER_ADDRESSES._fields_ = [
        ("header", HEADER_UNION),
        ("next", PIP_ADAPTER_ADDRESSES),
        ("adapterName", ctypes.c_char_p),
        ("firstUnicastAddress", PIP_ADAPTER_UNICAST_ADDRESS),
        ("firstAnycastAddress", PIP_ADAPTER_ANYCAST_ADDRESS),
        ("firstMulticastAddress", PIP_ADAPTER_MULTICAST_ADDRESS),
        ("firstDnsServerAddress", PIP_ADAPTER_DNS_SERVER_ADDRESS),
        ("dnsSuffix", ctypes.c_wchar_p),
        ("description", ctypes.c_wchar_p),
        ("friendlyName", ctypes.c_wchar_p),
        ("physicalAddress", ctypes.c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
        ("physicalAddressLength", ctypes.wintypes.DWORD),
        ("flags", ctypes.wintypes.DWORD),
        ("mtu", ctypes.wintypes.DWORD),
        ("ifType", ctypes.wintypes.DWORD),
        ("operStatus", ctypes.c_int),
        ("ipv6IfIndex", ctypes.wintypes.DWORD),
        ("zoneIndices", ctypes.wintypes.DWORD * 16),
        ("firstPrefix", PIP_ADAPTER_PREFIX),
        ("transmitLinkSpeed", ctypes.c_ulonglong),
        ("receiveLinkSpeed", ctypes.c_ulonglong),
        ("firstWinsServerAddress", PIP_ADAPTER_WINS_SERVER_ADDRESS),
        ("firstGatewayAddress", PIP_ADAPTER_GATEWAY_ADDRESS),
        ("ipv4Metric", ctypes.c_ulong),
        ("ipv6Metric", ctypes.c_ulong),
        ("luid", NET_LUID),#ifdef.h
        ("dhcpv4Server", SOCKET_ADDRESS),
        ("compartmentId", ctypes.c_uint32),#ifdef.h
        ("networkGuid", GUID),
        ("connectionType", ctypes.c_int),
        ("tunnelType", ctypes.c_int),
        ("dhcpv6Server", SOCKET_ADDRESS),
        ("dhcpv6ClientDuid", ctypes.c_byte * MAX_DHCPV6_DUID_LENGTH),
        ("dhcpv6ClientDuidLength", ctypes.c_ulong),
        ("dhcpv6Iaid", ctypes.c_ulong)]

    GetAdaptersAddresses = ctypes.windll.iphlpapi.GetAdaptersAddresses
    GetAdaptersAddresses.restype = ctypes.c_ulong
    GetAdaptersAddresses.argtypes = [
        ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p,
        PIP_ADAPTER_ADDRESSES, ctypes.POINTER(ctypes.c_ulong)]

    outBufLen = ctypes.c_ulong(15000)
    adapters = ctypes.pointer(IP_ADAPTER_ADDRESSES())
    ctypes.resize(adapters, outBufLen.value)

    from socket import AF_INET
    GAA_FLAG_INCLUDE_PREFIX = ctypes.c_ulong(0x0010)

    GetAdaptersAddresses(ctypes.c_ulong(AF_INET), GAA_FLAG_INCLUDE_PREFIX, None,
                         adapters, ctypes.byref(outBufLen))

    a = adapters[0]
    ifaces = {}
    while a:
        iface = {}

        iface['desc'] = a.description

#        iface['mac'] = ':'.join(["%02X" % part for part in a.address])
#                  
#        adNode = a.ipAddressList
#        iface['ip'] = []
#        while True:
#            ipAddr = adNode.ipAddress
#            if ipAddr:
#                iface['ip'].append( (ipAddr, adNode.ipMask) )
#            if adNode.next:
#                adNode = adNode.next.contents
#            else:
#                break

        ifaces[a.adapterName] = iface

        if a.next:
            a = a.next.contents
        else:
            break


    return ifaces    

def __getInterfaces_win2k():
    import ctypes.wintypes

    MAX_ADAPTER_NAME_LENGTH = 256
    MAX_ADAPTER_DESCRIPTION_LENGTH = 128

    class IP_ADDR_STRING(ctypes.Structure):
        pass
    LP_IP_ADDR_STRING = ctypes.POINTER(IP_ADDR_STRING)
    IP_ADDR_STRING._fields_ = [
        ("next", LP_IP_ADDR_STRING),
        ("ipAddress", ctypes.c_char * 16),
        ("ipMask", ctypes.c_char * 16),
        ("context", ctypes.wintypes.DWORD)]

    class IP_ADAPTER_INFO (ctypes.Structure):
        pass
    LP_IP_ADAPTER_INFO = ctypes.POINTER(IP_ADAPTER_INFO)
    IP_ADAPTER_INFO._fields_ = [
        ("next", LP_IP_ADAPTER_INFO),
        ("comboIndex", ctypes.wintypes.DWORD),
        ("adapterName", ctypes.c_char * (MAX_ADAPTER_NAME_LENGTH + 4)),
        ("description", ctypes.c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)),
        ("addressLength", ctypes.c_uint),
        ("address", ctypes.c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
        ("index", ctypes.wintypes.DWORD),
        ("type", ctypes.c_uint),
        ("dhcpEnabled", ctypes.c_uint),
        ("currentIpAddress", LP_IP_ADDR_STRING),
        ("ipAddressList", IP_ADDR_STRING),
        ("gatewayList", IP_ADDR_STRING),
        ("dhcpServer", IP_ADDR_STRING),
        ("haveWins", ctypes.c_uint),
        ("primaryWinsServer", IP_ADDR_STRING),
        ("secondaryWinsServer", IP_ADDR_STRING),
        ("leaseObtained", ctypes.c_ulong),
        ("leaseExpires", ctypes.c_ulong)]

    GetAdaptersInfo = ctypes.windll.iphlpapi.GetAdaptersInfo
    GetAdaptersInfo.restype = ctypes.wintypes.DWORD
    GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, ctypes.POINTER(ctypes.c_ulong)]

    adapters = ctypes.pointer(IP_ADAPTER_INFO())
    buflen = ctypes.c_ulong(ctypes.sizeof(IP_ADAPTER_INFO))
    GetAdaptersInfo(adapters, ctypes.byref(buflen))

    ctypes.resize(adapters, buflen.value)
    GetAdaptersInfo(adapters, ctypes.byref(buflen))

    a = adapters.contents
    ifaces = {}
    while a:
        iface = {}

        iface['desc'] = a.description

        iface['mac'] = ':'.join(["%02X" % part for part in a.address])

        adNode = a.ipAddressList
        iface['ip'] = []
        while True:
            ipAddr = adNode.ipAddress
            if ipAddr:
                iface['ip'].append( (ipAddr, adNode.ipMask) )
            if adNode.next:
                adNode = adNode.next.contents
            else:
                break

        ifaces[a.adapterName] = iface

        if a.next:
            a = a.next.contents
        else:
            break


    return ifaces

if __name__ == "__main__":
    ifaces = getInterfaces()
    for k, v in ifaces.iteritems():
        print k
        for k2, v2 in v.iteritems():
            print '\t', k2, v2

Ответы [ 3 ]

0 голосов
/ 28 февраля 2012

Я не могу найти информацию об изменениях версии Python размера байта ctypes, но я столкнулся с проблемой, связанной со структурой IP_ADAPTER_INFO и размером time_t.

Решение можно найти здесь http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/fe17ff48-71e4-401b-9982-84addb809eea.

Так что, может быть, изменить строки

("leaseObtained", ctypes.c_ulong) 
("leaseExpires", ctypes.c_ulong)

до

("leaseObtained", ctypes.c_uint)
("leaseExpires", ctypes.c_uint)
0 голосов
/ 06 мая 2013

Вы можете найти функционал ctypes Python для сетей Windows в http://code.google.com/p/pywingui/source/browse/#svn/trunk/pywingui/network и примеры http://code.google.com/p/pywingui/source/browse/#svn/trunk/pywingui_tests

0 голосов
/ 13 ноября 2010

не знаю, является ли это причиной вашей проблемы, но последнее поле структуры NET_LUID, по-видимому, отсутствует: 64-битная структура Info.Также отсутствует последнее поле структуры IP_ADAPTER_ADDRESSES (FirstDnsSuffix), но это имеет значение только на сервере W2k8 - я полагаю, вы используете этот код для Vista или XP.

...