Short version:
the five routines get_node() calls to get the MAC address either fail by definition, or is wrong.
The one routine that works - is wrong because it returns the same value regardless of the system it runs on - wrong character is used to identify the string containing the mac address.
Recommended: correct and call the one routine that can work for AIX.
Details (using Python2.7 as template, applies to all Python3 versions as well)
+511 def getnode():
+512 """Get the hardware address as a 48-bit positive integer.
+513
+514 The first time this runs, it may launch a separate program, which could
+515 be quite slow. If all attempts to obtain the hardware address fail, we
+516 choose a random 48-bit number with its eighth bit set to 1 as recommended
+517 in RFC 4122.
+518 """
+519
+520 global _node
+521 if _node is not None:
+522 return _node
+523
+524 import sys
+525 if sys.platform == 'win32':
+526 getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+527 else:
+528 getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
+529 _lanscan_getnode, _netstat_getnode]
+530
+531 for getter in getters + [_random_getnode]:
+532 try:
+533 _node = getter()
+534 except:
+535 continue
+536 if _node is not None:
+537 return _node
+538
+539 _last_timestamp = None
unixdll_getnode depends on finding uuid_generate_time in either libuuid, libc, or None
On a default install of AIX:
find_library("uuid") returns None
nm -Ae /usr/lib/*.a | grep uuid_generate # does not return a function name, no .a archives are stripped
+339 def _ifconfig_getnode():
+340 """Get the hardware address on Unix by running ifconfig."""
+341 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
+342 for args in ('', '-a', '-av'):
+343 mac = _find_mac('ifconfig', args, ['hwaddr', 'ether'], lambda i: i+1)
+344 if mac:
+345 return mac
Does not work on AIX - why call it?
+347 def _arp_getnode():
+348 """Get the hardware address on Unix by running arp."""
+349 import os, socket
+350 try:
+351 ip_addr = socket.gethostbyname(socket.gethostname())
+352 except EnvironmentError:
+353 return None
+354
+355 # Try getting the MAC addr from arp based on our IP address (Solaris).
+356 return _find_mac('arp', '-an', [ip_addr], lambda i: -1)
Does not work on one Linux system I tried
root@x066:~# arp -an 192.168.129.66
arp: in 2 entries no match found.
on AIX:
root@x064:[/data/prj/aixtools/python/python-2.7.12.1]arp -an 192.168.129.64
? (192.168.129.254) at XX:YY:11:aa:ZZ:ca [ethernet] stored in bucket 27
...
Nothing for it's own IP address
again, why call it.
+358 def _lanscan_getnode():
+359 """Get the hardware address on Unix by running lanscan."""
+360 # This might work on HP-UX.
+361 return _find_mac('lanscan', '-ai', ['lan0'], lambda i: 0)
Again, from comments - looks like it should work on HP-UX, so why call it on AIX
(linux was probably solved via one of the first two, so no impact there)
So, finally, after 4 guaranteed failures the following is called:
+363 def _netstat_getnode():
+364 """Get the hardware address on Unix by running netstat."""
+365 # This might work on AIX, Tru64 UNIX and presumably on IRIX.
+366 try:
+367 pipe = _popen('netstat', '-ia')
+368 if not pipe:
+369 return
+370 with pipe:
+371 words = pipe.readline().rstrip().split()
+372 try:
+373 i = words.index('Address')
+374 except ValueError:
+375 return
+376 for line in pipe:
+377 try:
+378 words = line.rstrip().split()
+379 word = words[i]
+380 if len(word) == 17 and word.count(':') == 5:
+381 mac = int(word.replace(':', ''), 16)
+382 if mac:
+383 return mac
+384 except (ValueError, IndexError):
+385 pass
+386 except OSError:
+387 pass
For AIX - lines 380 and 381 do work - except the answer is ALWAYS the same:
See host x071:
michael@x071:[/usr/lib]netstat -ia
Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll
en0 1500 link#2 fa.d1.8c.f7.62.4 553220627 0 181051589 0 0
01:00:5e:00:00:01
en0 1500 192.168.129 x071 553220627 0 181051589 0 0
224.0.0.1
en1 65390 link#3 fa.d1.8c.f7.62.5 8004448 0 11655497 0 0
01:00:5e:00:00:01
en1 65390 192.168.2 mail.aixtools.co 8004448 0 11655497 0 0
224.0.0.1
lo0 16896 link#1 197583 0 197583 0 0
lo0 16896 127 loopback 197583 0 197583 0 0
224.0.0.1
lo0 16896 loopback 197583 0 197583 0 0
ff01::1
ff02::1:ff00:1
See host x064:
root@x064:[/data/prj/aixtools/python/python-2.7.12.1]netstat -ia
Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll
en0 1500 link#2 0.21.5e.a3.c7.44 192718 0 93218 0 0
01:00:5e:00:00:01
en0 1500 192.168.129 x064 192718 0 93218 0 0
224.0.0.1
lo0 16896 link#1 231 0 240 0 0
lo0 16896 127 loopback 231 0 240 0 0
224.0.0.1
lo0 16896 ::1 231 0 240 0 0
ff01::1
ff02::1:ff00:1
ff02::1
The answer found is always
01:00:5e:00:00:01
Where, for AIX at least, line 380 and line 381 should be looking at the character '.', not ':'
which is valid for linux, and perhaps others.
So,
two corrections suggested:
line 380 + 381 (or as appropriate per Python version) - modify:
+378 words = line.rstrip().split()
+379 word = words[i]
+380 if sys.platform.startswith("aix"):
+381 str = "."
+382 else:
+383 str = ":"
+384 if len(word) == 17 and word.count(str) == 5:
+385 mac = int(word.replace(str, ''), 16)
+386 if mac:
+387 return mac
NOTE: if str need to be a chr, then use that instead.
But much earlier in program logic - modify:
+525 if sys.platform == 'win32':
+526 getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+527 else:
+528 getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
+529 _lanscan_getnode, _netstat_getnode]
to
+529 if sys.platform == 'win32':
+530 getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
+531 elif sys.platform.startswith("aix"):
+532 getters = [_netstat_getnode]
+533 else:
+534 getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
+535 _lanscan_getnode, _netstat_getnode] |