-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-28009: for AIX correct uuid.getnode() and add ctypes() based uuid._generate_time_safe #5183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7837745
f6d95f3
44aa616
64228cd
9d8148e
e6d1c0e
dd5f39a
7b25dd3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -361,6 +361,11 @@ def _is_universal(mac): | |
return not (mac & (1 << 41)) | ||
|
||
def _find_mac(command, args, hw_identifiers, get_index): | ||
# issue28009: AIX uses character '.' rather than ':' | ||
if sys.platform.startswith("aix"): | ||
c_field = b'.' | ||
else: | ||
c_field = b':' | ||
first_local_mac = None | ||
try: | ||
proc = _popen(command, *args.split()) | ||
|
@@ -373,7 +378,7 @@ def _find_mac(command, args, hw_identifiers, get_index): | |
if words[i] in hw_identifiers: | ||
try: | ||
word = words[get_index(i)] | ||
mac = int(word.replace(b':', b''), 16) | ||
mac = int(word.replace(c_field, b''), 16) | ||
if _is_universal(mac): | ||
return mac | ||
first_local_mac = first_local_mac or mac | ||
|
@@ -437,6 +442,23 @@ def _lanscan_getnode(): | |
# This might work on HP-UX. | ||
return _find_mac('lanscan', '-ai', [b'lan0'], lambda i: 0) | ||
|
||
def _netstat_getmac_posix(words,i): | ||
"""Extract the MAC address from netstat -ia from posix netstat -ia.""" | ||
word = words[i] | ||
if len(word) == 17 and word.count(b':') == 5: | ||
return(int(word.replace(b':', b''), 16)) | ||
else: | ||
return None | ||
|
||
def _netstat_getmac_aix(words,i): | ||
"""Extract the MAC address from netstat -ia specific for AIX netstat.""" | ||
word = words[i] | ||
wlen = len(word) | ||
if wlen >= 11 and wlen <=17 and word.count(b'.') == 5: | ||
return int(word.replace(b'.', b''), 16) | ||
else: | ||
return None | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the light of "functional differences better than names" -- probably detect the format instead? |
||
def _netstat_getnode(): | ||
"""Get the hardware address on Unix by running netstat.""" | ||
# This might work on AIX, Tru64 UNIX. | ||
|
@@ -454,12 +476,15 @@ def _netstat_getnode(): | |
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 _is_universal(mac): | ||
return mac | ||
first_local_mac = first_local_mac or mac | ||
if sys.platform.startswith("aix"): | ||
mac = _netstat_getmac_aix(words,i) | ||
else: | ||
mac = _netstat_getmac_posix(words,i) | ||
if not mac: | ||
continue | ||
if _is_universal(mac): | ||
return mac | ||
first_local_mac = first_local_mac or mac | ||
except (ValueError, IndexError): | ||
pass | ||
except OSError: | ||
|
@@ -573,12 +598,18 @@ def _load_system_functions(): | |
|
||
# The uuid_generate_* routines are provided by libuuid on at least | ||
# Linux and FreeBSD, and provided by libc on Mac OS X. | ||
# uuid_create() is used by other POSIX platforms (e.g., AIX, FreeBSD) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
_libnames = ['uuid'] | ||
if not sys.platform.startswith('win'): | ||
_libnames.append('c') | ||
# also need to look for uuid_create() but only look if something was located | ||
lib = None | ||
for libname in _libnames: | ||
libnm = ctypes.util.find_library(libname) | ||
if not libnm: | ||
continue | ||
try: | ||
lib = ctypes.CDLL(ctypes.util.find_library(libname)) | ||
lib = ctypes.CDLL(libnm) | ||
except Exception: # pragma: nocover | ||
continue | ||
# Try to find the safe variety first. | ||
|
@@ -601,6 +632,22 @@ def _generate_time_safe(): | |
_uuid_generate_time(_buffer) | ||
return bytes(_buffer.raw), None | ||
break | ||
# if _uuid_generate_time has not been found (Linux) then we try libc | ||
# as libc is already dynamically linked (or found above) verify a valid | ||
# lib value, then look for uuid_generate() | ||
if not lib: | ||
try: | ||
lib = ctypes.CDLL(None) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is this supposed to work? |
||
except: | ||
lib = None | ||
if lib: | ||
if hasattr(lib, 'uuid_create'): # pragma: nocover | ||
_uuid_generate_time = lib.uuid_create | ||
def _generate_time_safe(): | ||
_buffer = ctypes.create_string_buffer(16)# uuid | ||
_status = ctypes.create_string_buffer(2) # c_ushort | ||
_uuid_generate_time(_buffer, _status) | ||
return bytes(_buffer.raw), bytes(_status.raw) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This only searches the last found lib, whatever it happens to be. Better search |
||
|
||
# On Windows prior to 2000, UuidCreate gives a UUID containing the | ||
# hardware address. On Windows 2000 and later, UuidCreate makes a | ||
|
@@ -656,7 +703,12 @@ def _random_getnode(): | |
|
||
_node = None | ||
|
||
def getnode(): | ||
_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] | ||
|
||
_NODE_GETTERS_UNIX = [_unix_getnode, _ifconfig_getnode, _ip_getnode, | ||
_arp_getnode, _lanscan_getnode, _netstat_getnode] | ||
|
||
def getnode(*, getters=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't see the purpose of any changes from here and further. About this one specifically:
|
||
"""Get the hardware address as a 48-bit positive integer. | ||
|
||
The first time this runs, it may launch a separate program, which could | ||
|
@@ -669,19 +721,18 @@ def getnode(): | |
return _node | ||
|
||
if sys.platform == 'win32': | ||
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] | ||
getters = _NODE_GETTERS_WIN32 | ||
else: | ||
getters = [_unix_getnode, _ifconfig_getnode, _ip_getnode, | ||
_arp_getnode, _lanscan_getnode, _netstat_getnode] | ||
getters = _NODE_GETTERS_UNIX | ||
|
||
for getter in getters + [_random_getnode]: | ||
try: | ||
_node = getter() | ||
except: | ||
continue | ||
if _node is not None: | ||
if (_node is not None) and (0 <= _node < (1 << 48)): | ||
return _node | ||
assert False, '_random_getnode() returned None' | ||
assert False, '_random_getnode() returned invalid value: {}'.format(_node) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getters are supposed to return valid ids or |
||
|
||
|
||
_last_timestamp = None | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
* AIX uses the character '.' rather than ':' to seperate the MAC ADDR values | ||
returned by 'netstat -i' command. | ||
* The commands 'arp' and 'ifconfig' do not return a local MAC address | ||
* define uuid._generate_time_safe in uuid.py based on ctypes() | ||
lib.uuid_create (for when _uuid is not available) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AIX <commands involved> use '.' as MAC delimiter
mac_delim
)