summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Martz <matt@sivel.net>2022-10-26 16:07:29 -0500
committerGitHub <noreply@github.com>2022-10-26 16:07:29 -0500
commite0d20bc4781ff003c59ed7815fd2252656a9dd4a (patch)
tree325ba76019abba263d4b8619b2c450e26e107f73
parent1a583e3c0d67a63cef1b1a433f176b7983d39812 (diff)
downloadansible-e0d20bc4781ff003c59ed7815fd2252656a9dd4a.tar.gz
[stable-2.13] Don't assume column index for netmask and broadcast (#79121) (#79133)
* 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.yml4
-rw-r--r--lib/ansible/module_utils/facts/network/generic_bsd.py27
-rw-r--r--test/units/module_utils/facts/network/test_generic_bsd.py42
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])