diff options
author | Matt Martz <matt@sivel.net> | 2022-10-13 16:09:01 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-13 16:09:01 -0500 |
commit | febf071d01c8a8dfe3a0939a1b0004a573e7ec0e (patch) | |
tree | a72124960367f713a0ce1c92a0e277403cd7766e | |
parent | 9c9a33904accf76a6e397ce277bc287d8787fd08 (diff) | |
download | ansible-febf071d01c8a8dfe3a0939a1b0004a573e7ec0e.tar.gz |
[stable-2.14] Don't assume column index for netmask and broadcast (#79121) (#79132)
* Don't assume column index for netmask and broadcast. Fixes #79117
* fix typo
(cherry picked from commit f53dbf9)
Co-authored-by: Matt Martz <matt@sivel.net>
-rw-r--r-- | changelogs/fragments/79117-bsd-ifconfig-inet-fix.yml | 4 | ||||
-rw-r--r-- | lib/ansible/module_utils/facts/network/generic_bsd.py | 27 | ||||
-rw-r--r-- | test/units/module_utils/facts/network/test_generic_bsd.py | 42 |
3 files changed, 65 insertions, 8 deletions
diff --git a/changelogs/fragments/79117-bsd-ifconfig-inet-fix.yml b/changelogs/fragments/79117-bsd-ifconfig-inet-fix.yml new file mode 100644 index 0000000000..ae211a0e66 --- /dev/null +++ b/changelogs/fragments/79117-bsd-ifconfig-inet-fix.yml @@ -0,0 +1,4 @@ +bugfixes: +- BSD network facts - Do not assume column indexes, look for ``netmask`` and + ``broadcast`` for determining the correct columns when parsing ``inet`` line + (https://github.com/ansible/ansible/issues/79117) diff --git a/lib/ansible/module_utils/facts/network/generic_bsd.py b/lib/ansible/module_utils/facts/network/generic_bsd.py index 8f4d145f8c..8d640f2152 100644 --- a/lib/ansible/module_utils/facts/network/generic_bsd.py +++ b/lib/ansible/module_utils/facts/network/generic_bsd.py @@ -221,24 +221,35 @@ class GenericBsdIfconfigNetwork(Network): address['broadcast'] = words[3] else: + # Don't just assume columns, use "netmask" as the index for the prior column + try: + netmask_idx = words.index('netmask') + 1 + except ValueError: + netmask_idx = 3 + # deal with hex netmask - if re.match('([0-9a-f]){8}', words[3]) and len(words[3]) == 8: - words[3] = '0x' + words[3] - if words[3].startswith('0x'): - address['netmask'] = socket.inet_ntoa(struct.pack('!L', int(words[3], base=16))) + if re.match('([0-9a-f]){8}$', words[netmask_idx]): + netmask = '0x' + words[netmask_idx] + else: + netmask = words[netmask_idx] + + if netmask.startswith('0x'): + address['netmask'] = socket.inet_ntoa(struct.pack('!L', int(netmask, base=16))) else: # otherwise assume this is a dotted quad - address['netmask'] = words[3] + address['netmask'] = netmask # calculate the network address_bin = struct.unpack('!L', socket.inet_aton(address['address']))[0] netmask_bin = struct.unpack('!L', socket.inet_aton(address['netmask']))[0] address['network'] = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin)) if 'broadcast' not in address: # broadcast may be given or we need to calculate - if len(words) > 5: - address['broadcast'] = words[5] - else: + try: + broadcast_idx = words.index('broadcast') + 1 + except ValueError: address['broadcast'] = socket.inet_ntoa(struct.pack('!L', address_bin | (~netmask_bin & 0xffffffff))) + else: + address['broadcast'] = words[broadcast_idx] # add to our list of addresses if not words[1].startswith('127.'): diff --git a/test/units/module_utils/facts/network/test_generic_bsd.py b/test/units/module_utils/facts/network/test_generic_bsd.py index afb698c571..f061f04d8a 100644 --- a/test/units/module_utils/facts/network/test_generic_bsd.py +++ b/test/units/module_utils/facts/network/test_generic_bsd.py @@ -173,3 +173,45 @@ class TestGenericBsdNetworkNetBSD(unittest.TestCase): 'filter': '*'} mock_module.get_bin_path = Mock(return_value=None) return mock_module + + def test_ensure_correct_netmask_parsing(self): + n = generic_bsd.GenericBsdIfconfigNetwork(None) + lines = [ + 'inet 192.168.7.113 netmask 0xffffff00 broadcast 192.168.7.255', + 'inet 10.109.188.206 --> 10.109.188.206 netmask 0xffffe000', + ] + expected = [ + ( + { + 'ipv4': [ + { + 'address': '192.168.7.113', + 'netmask': '255.255.255.0', + 'network': '192.168.7.0', + 'broadcast': '192.168.7.255' + } + ] + }, + {'all_ipv4_addresses': ['192.168.7.113']}, + ), + ( + { + 'ipv4': [ + { + 'address': '10.109.188.206', + 'netmask': '255.255.224.0', + 'network': '10.109.160.0', + 'broadcast': '10.109.191.255' + } + ] + }, + {'all_ipv4_addresses': ['10.109.188.206']}, + ), + ] + for i, line in enumerate(lines): + words = line.split() + current_if = {'ipv4': []} + ips = {'all_ipv4_addresses': []} + n.parse_inet_line(words, current_if, ips) + self.assertDictEqual(current_if, expected[i][0]) + self.assertDictEqual(ips, expected[i][1]) |