views:

49

answers:

0

I'm attempting to create python module for getting network parameters. I'm using ctypes and has some problems.

Function __getInterfaces_win2k() works with python 2.5 and 2.6, but doesn't work with python 2.7 (Unhandled exception at 0x1e001759 in python.exe: 0xC0000005: Access violation reading location 0x00000010.)

Function __getInterfaces_win_after_win2k() doesn't work in any version of python (same error).

Sometimes, before the crash program print the necessary information. I've tried compare practically all values with program in C. Everything is normal. Any help much appreciated.

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