mirror of https://github.com/python/cpython
Issue #17293: uuid.getnode() now determines MAC address on AIX using netstat.
Based on patch by Aivars Kalvāns.
This commit is contained in:
commit
57b967791a
|
@ -320,6 +320,24 @@ class TestUUID(unittest.TestCase):
|
|||
if node is not None:
|
||||
self.check_node(node, 'ifconfig')
|
||||
|
||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
||||
def test_arp_getnode(self):
|
||||
node = uuid._arp_getnode()
|
||||
if node is not None:
|
||||
self.check_node(node, 'arp')
|
||||
|
||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
||||
def test_lanscan_getnode(self):
|
||||
node = uuid._lanscan_getnode()
|
||||
if node is not None:
|
||||
self.check_node(node, 'lanscan')
|
||||
|
||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
||||
def test_netstat_getnode(self):
|
||||
node = uuid._netstat_getnode()
|
||||
if node is not None:
|
||||
self.check_node(node, 'netstat')
|
||||
|
||||
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
|
||||
def test_ipconfig_getnode(self):
|
||||
node = uuid._ipconfig_getnode()
|
||||
|
@ -377,7 +395,7 @@ eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab
|
|||
return_value=popen):
|
||||
mac = uuid._find_mac(
|
||||
command='ifconfig',
|
||||
arg='',
|
||||
args='',
|
||||
hw_identifiers=[b'hwaddr'],
|
||||
get_index=lambda x: x + 1,
|
||||
)
|
||||
|
|
81
Lib/uuid.py
81
Lib/uuid.py
|
@ -304,7 +304,7 @@ class UUID(object):
|
|||
if self.variant == RFC_4122:
|
||||
return int((self.int >> 76) & 0xf)
|
||||
|
||||
def _find_mac(command, arg, hw_identifiers, get_index):
|
||||
def _popen(command, *args):
|
||||
import os, shutil, subprocess
|
||||
executable = shutil.which(command)
|
||||
if executable is None:
|
||||
|
@ -312,28 +312,32 @@ def _find_mac(command, arg, hw_identifiers, get_index):
|
|||
executable = shutil.which(command, path=path)
|
||||
if executable is None:
|
||||
return None
|
||||
# LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
|
||||
# on stderr (Note: we don't have an example where the words we search
|
||||
# for are actually localized, but in theory some system could do so.)
|
||||
env = dict(os.environ)
|
||||
env['LC_ALL'] = 'C'
|
||||
proc = subprocess.Popen((executable,) + args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
env=env)
|
||||
return proc
|
||||
|
||||
def _find_mac(command, args, hw_identifiers, get_index):
|
||||
try:
|
||||
# LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
|
||||
# on stderr (Note: we don't have an example where the words we search
|
||||
# for are actually localized, but in theory some system could do so.)
|
||||
env = dict(os.environ)
|
||||
env['LC_ALL'] = 'C'
|
||||
cmd = [executable]
|
||||
if arg:
|
||||
cmd.append(arg)
|
||||
proc = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
env=env)
|
||||
proc = _popen(command, *args.split())
|
||||
if not proc:
|
||||
return
|
||||
with proc:
|
||||
for line in proc.stdout:
|
||||
words = line.lower().split()
|
||||
words = line.lower().rstrip().split()
|
||||
for i in range(len(words)):
|
||||
if words[i] in hw_identifiers:
|
||||
try:
|
||||
return int(
|
||||
words[get_index(i)].replace(b':', b''), 16)
|
||||
word = words[get_index(i)]
|
||||
mac = int(word.replace(b':', b''), 16)
|
||||
if mac:
|
||||
return mac
|
||||
except (ValueError, IndexError):
|
||||
# Virtual interfaces, such as those provided by
|
||||
# VPNs, do not have a colon-delimited MAC address
|
||||
|
@ -346,28 +350,50 @@ def _find_mac(command, arg, hw_identifiers, get_index):
|
|||
|
||||
def _ifconfig_getnode():
|
||||
"""Get the hardware address on Unix by running ifconfig."""
|
||||
import os
|
||||
|
||||
# This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
|
||||
for args in ('', '-a', '-av'):
|
||||
mac = _find_mac('ifconfig', args, [b'hwaddr', b'ether'], lambda i: i+1)
|
||||
if mac:
|
||||
return mac
|
||||
|
||||
import socket
|
||||
def _arp_getnode():
|
||||
"""Get the hardware address on Unix by running arp."""
|
||||
import os, socket
|
||||
ip_addr = socket.gethostbyname(socket.gethostname())
|
||||
|
||||
# Try getting the MAC addr from arp based on our IP address (Solaris).
|
||||
mac = _find_mac('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
|
||||
if mac:
|
||||
return mac
|
||||
return _find_mac('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
|
||||
|
||||
def _lanscan_getnode():
|
||||
"""Get the hardware address on Unix by running lanscan."""
|
||||
# This might work on HP-UX.
|
||||
mac = _find_mac('lanscan', '-ai', [b'lan0'], lambda i: 0)
|
||||
if mac:
|
||||
return mac
|
||||
return _find_mac('lanscan', '-ai', [b'lan0'], lambda i: 0)
|
||||
|
||||
return None
|
||||
def _netstat_getnode():
|
||||
"""Get the hardware address on Unix by running netstat."""
|
||||
# This might work on AIX, Tru64 UNIX and presumably on IRIX.
|
||||
try:
|
||||
proc = _popen('netstat', '-ia')
|
||||
if not proc:
|
||||
return
|
||||
with proc:
|
||||
words = proc.stdout.readline().rstrip().split()
|
||||
try:
|
||||
i = words.index(b'Address')
|
||||
except ValueError:
|
||||
return
|
||||
for line in proc.stdout:
|
||||
try:
|
||||
words = line.rstrip().split()
|
||||
word = words[i]
|
||||
if len(word) == 17 and word.count(b':') == 5:
|
||||
mac = int(word.replace(b':', b''), 16)
|
||||
if mac:
|
||||
return mac
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _ipconfig_getnode():
|
||||
"""Get the hardware address on Windows by running ipconfig.exe."""
|
||||
|
@ -509,7 +535,8 @@ def getnode():
|
|||
if sys.platform == 'win32':
|
||||
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
|
||||
else:
|
||||
getters = [_unixdll_getnode, _ifconfig_getnode]
|
||||
getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode,
|
||||
_lanscan_getnode, _netstat_getnode]
|
||||
|
||||
for getter in getters + [_random_getnode]:
|
||||
try:
|
||||
|
|
|
@ -183,6 +183,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #17293: uuid.getnode() now determines MAC address on AIX using netstat.
|
||||
Based on patch by Aivars Kalvāns.
|
||||
|
||||
- Issue #22769: Fixed ttk.Treeview.tag_has() when called without arguments.
|
||||
|
||||
- Issue #22417: Verify certificates by default in httplib (PEP 476).
|
||||
|
|
Loading…
Reference in New Issue