Skip to content

Commit 4c6519c

Browse files
committed
Fix ifconfig parse logic failing on some tunnels
Tunnel interfaces that have a line similar to "tunnel inet 192.0.2.1 --> 192.0.2.2" would fail the network resolver because IPs were extracted through two separate IP + mask patterns. However, in the example above, there is no such thing as a netmask. This fix merges the patterns and extracts the IPs and netmasks together so that no mismatches can occur. It might also fix some cases where only the netmask would be nil and therefore produce an invalid binding that could in turn resolve to the wrong (outer) IP of the tunnel instead of the inner IP.
1 parent 7cbaac0 commit 4c6519c

File tree

2 files changed

+34
-14
lines changed

2 files changed

+34
-14
lines changed

lib/facter/resolvers/networking.rb

+20-13
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,35 @@ def extract_dhcp(interface_name, raw_data, parsed_interface_data)
8080
end
8181

8282
def extract_ip_data(raw_data, parsed_interface_data)
83-
ip = extract_values(raw_data, /inet (\S+)/)
84-
mask = extract_values(raw_data, /netmask (\S+)/).map { |val| val.hex.to_s(2).count('1') }
83+
inets = extract_values(raw_data, /inet (\S+).+netmask (\S+)/, :extract_ip4_data)
84+
bindings = create_bindings(inets)
85+
parsed_interface_data[:bindings] = bindings unless bindings.empty?
8586

86-
ip6 = extract_values(raw_data, /inet6 (\S+)/).map { |val| val.gsub(/%.+/, '') }
87-
mask6 = extract_values(raw_data, /prefixlen (\S+)/)
88-
89-
parsed_interface_data[:bindings] = create_bindings(ip, mask) unless ip.empty?
90-
parsed_interface_data[:bindings6] = create_bindings(ip6, mask6) unless ip6.empty?
87+
inets = extract_values(raw_data, /inet6 (\S+).+prefixlen (\S+)/, :extract_ip6_data)
88+
bindings = create_bindings(inets)
89+
parsed_interface_data[:bindings6] = bindings unless bindings.empty?
9190
end
9291

93-
def extract_values(data, regex)
92+
def extract_values(data, regex, ip_func)
9493
results = []
95-
data.scan(regex).flatten.each do |val|
96-
results << val
94+
data.scan(regex).flatten.each_slice(2) do |val|
95+
results << method(ip_func).call(val)
9796
end
9897
results
9998
end
10099

101-
def create_bindings(ips, masks)
100+
def extract_ip4_data(inet)
101+
[inet[0], inet[1].hex.to_s(2).count('1')]
102+
end
103+
104+
def extract_ip6_data(inet)
105+
[inet[0].gsub(/%.+/, ''), inet[1]]
106+
end
107+
108+
def create_bindings(inets)
102109
bindings = []
103-
ips.zip(masks).each do |ip, mask|
104-
bindings << Facter::Util::Resolvers::Networking.build_binding(ip, mask)
110+
inets.each do |inet|
111+
bindings << Facter::Util::Resolvers::Networking.build_binding(inet[0], inet[1])
105112
end
106113
bindings
107114
end

spec/facter/resolvers/networking_spec.rb

+14-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
end
4141

4242
it 'detects all interfaces' do
43-
expected = %w[lo0 gif0 stf0 en0 en0.1 en1 en2 bridge0 p2p0 awdl0 llw0 utun0 utun1 utun2 utun3 ib0 ib1]
43+
expected = %w[lo0 gif0 stf0 en0 en0.1 en1 en2 bridge0 p2p0 awdl0 llw0 utun0 utun1 utun2 utun3 utun4 utun5 ib0 ib1]
4444
expect(networking.resolve(:interfaces).keys).to match_array(expected)
4545
end
4646

@@ -138,6 +138,19 @@
138138
expect(networking.resolve(:interfaces)['utun3']).to include(expected)
139139
end
140140

141+
it 'checks interface utun4' do
142+
expected = { bindings: [{ address: '192.0.2.100', netmask: '255.255.255.255', network: '192.0.2.100' }] }
143+
expect(networking.resolve(:interfaces)['utun4']).to include(expected)
144+
end
145+
146+
it 'checks interface utun5' do
147+
expected = { bindings6: [
148+
{ address: '2001:db8::1', netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
149+
network: '2001:db8::1', scope6: 'global' }
150+
] }
151+
expect(networking.resolve(:interfaces)['utun5']).to include(expected)
152+
end
153+
141154
it 'checks interface ib0 has the expected mac' do
142155
expected = { mac: '80:00:02:08:FA:81:00:00:00:00:00:00:00:00:00:00:00:00:00:00' }
143156
expect(networking.resolve(:interfaces)['ib0']).to include(expected)

0 commit comments

Comments
 (0)