This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Michael.Felt
Recipients Michael.Felt
Date 2016-09-07.23:18:34
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1473290315.48.0.840701308825.issue28009@psf.upfronthosting.co.za>
In-reply-to
Content
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]
History
Date User Action Args
2016-09-07 23:18:36Michael.Feltsetrecipients: + Michael.Felt
2016-09-07 23:18:35Michael.Feltsetmessageid: <1473290315.48.0.840701308825.issue28009@psf.upfronthosting.co.za>
2016-09-07 23:18:35Michael.Feltlinkissue28009 messages
2016-09-07 23:18:34Michael.Feltcreate