Welcome, guest | Sign In | My Account | Store | Cart

Uses the Internet Protocol Helper functions on Win32.

Python, 46 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python

import ctypes
import socket
import struct

def get_macaddress(host):
    """ Returns the MAC address of a network host, requires >= WIN2K. """
    
    # Check for api availability
    try:
        SendARP = ctypes.windll.Iphlpapi.SendARP
    except:
        raise NotImplementedError('Usage only on Windows 2000 and above')
        
    # Doesn't work with loopbacks, but let's try and help.
    if host == '127.0.0.1' or host.lower() == 'localhost':
        host = socket.gethostname()
    
    # gethostbyname blocks, so use it wisely.
    try:
        inetaddr = ctypes.windll.wsock32.inet_addr(host)
        if inetaddr in (0, -1):
            raise Exception
    except:
        hostip = socket.gethostbyname(host)
        inetaddr = ctypes.windll.wsock32.inet_addr(hostip)
    
    buffer = ctypes.c_buffer(6)
    addlen = ctypes.c_ulong(ctypes.sizeof(buffer))
    if SendARP(inetaddr, 0, ctypes.byref(buffer), ctypes.byref(addlen)) != 0:
        raise WindowsError('Retreival of mac address(%s) - failed' % host)
    
    # Convert binary data into a string.
    macaddr = ''
    for intval in struct.unpack('BBBBBB', buffer):
        if intval > 15:
            replacestr = '0x'
        else:
            replacestr = 'x'
        macaddr = ''.join([macaddr, hex(intval).replace(replacestr, '')])
    
    return macaddr.upper()

if __name__ == '__main__':
    print 'Your mac address is %s' % get_macaddress('localhost')

Although this solution is fast, it doesn't work on Windows 2000 and below. That's what the Platform SDK says: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/sendarp.asp. I have no access to any Win9x machines therefore unable to test it on them. I have tried parsing NBTSTAT.EXE output on windows to get the same results but the process is painfully slow. If anyone has access to Win9x, WinNT machines, or other platforms, hope you guys can help me wrap this function for these OSes.

3 comments

Jean Brouwers 19 years, 4 months ago  # | flag
The line

  if inetaddr == 0 or -1:
     raise Exception

will throw an exception for any value of inetaddr other than 0.  It should probably be

  if inetaddr == 0 or inetaddr == -1:

or

  if inetaddr in (0, -1):
Fadly Tabrani (author) 19 years, 4 months ago  # | flag

Changes made. Thanks Jean for pointing that out. Silly of me.

Giovanni Bajo 17 years, 4 months ago  # | flag

uuid.getnode(). Python 2.5 has a new module in its standard library (uuid), which exports a function to get the MAC address:

>>> import uuid
>>> uuid.getnode()
67474971543L
>>> hex(uuid.getnode())
'0xfb5d25b97L'