2010-09-24 3 views
1

Je tente de créer un module python pour obtenir les paramètres réseau. J'utilise des ctypes et j'ai quelques problèmes.Problème avec l'utilisation de l'API Win32 IPHelper en python

Fonction __getInterfaces_win2k() fonctionne avec Python 2.5 et 2.6, mais ne fonctionne pas avec Python 2.7 (exception non gérée à 0x1e001759 dans python.exe: 0xC0000005: emplacement lecture violation d'accès 0x00000010.)

Fonction __getInterfaces_win_after_win2k() ne fonctionne pas dans une version de python (même erreur).

Parfois, avant le programme d'écrasement, imprimez les informations nécessaires. J'ai essayé de comparer pratiquement toutes les valeurs avec le programme en C. Tout est normal. Toute aide très appréciée.

''' 
    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 

Répondre

0

ne sais pas si cela est la cause de votre problème, mais le dernier champ de la structure NET_LUID semble manquer: la structure large « Info » 64 bits. Aussi le dernier champ de la structure IP_ADAPTER_ADDRESSES (FirstDnsSuffix) est manquant, mais cela n'a d'importance que sur un serveur W2k8 - je suppose que vous utilisez ce code pour Vista ou XP.

+2

NET_LUID est l'union de "ULONG64 Value" et "struct Info". Pour la simplicité, je le définis comme "valeur ULONG64". –

0

Je ne trouve aucune information sur les changements de version python de la taille en octets des ctypes, mais j'ai rencontré un problème en considérant la structure IP_ADAPTER_INFO et la taille time_t.

La solution peut être trouvée ici http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/fe17ff48-71e4-401b-9982-84addb809eea.

Alors peut-être changer les lignes

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

à

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