New submission from Michael Felt: 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] ---------- components: Library (Lib) messages: 274909 nosy: Michael.Felt priority: normal severity: normal status: open title: core logic of uuid.getnode() is broken for AIX - all versions type: behavior versions: Python 2.7, Python 3.3, Python 3.4, Python 3.5, Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28009> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com