Skip to content

Commit

Permalink
Fix ifconfig parse logic failing on some tunnels
Browse files Browse the repository at this point in the history
  • Loading branch information
Woellchen committed Oct 22, 2024
1 parent eca23ba commit 8260822
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 30 deletions.
33 changes: 20 additions & 13 deletions lib/facter/resolvers/networking.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,35 @@ def extract_dhcp(interface_name, raw_data, parsed_interface_data)
end

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

ip6 = extract_values(raw_data, /inet6 (\S+)/).map { |val| val.gsub(/%.+/, '') }
mask6 = extract_values(raw_data, /prefixlen (\S+)/)

parsed_interface_data[:bindings] = create_bindings(ip, mask) unless ip.empty?
parsed_interface_data[:bindings6] = create_bindings(ip6, mask6) unless ip6.empty?
inets = extract_values(raw_data, /inet6 (\S+).+prefixlen (\S+)/, :extract_ip6_data)
bindings = create_bindings(inets)
parsed_interface_data[:bindings6] = bindings unless bindings.empty?
end

def extract_values(data, regex)
def extract_values(data, regex, ip_func)
results = []
data.scan(regex).flatten.each do |val|
results << val
data.scan(regex).flatten.each_slice(2) do |val|
results << method(ip_func).call(val)
end
results
end

def create_bindings(ips, masks)
def extract_ip4_data(inet)
[inet[0], inet[1].hex.to_s(2).count('1')]
end

def extract_ip6_data(inet)
[inet[0].gsub(/%.+/, ''), inet[1]]
end

def create_bindings(inets)
bindings = []
ips.zip(masks).each do |ip, mask|
bindings << Facter::Util::Resolvers::Networking.build_binding(ip, mask)
inets.each do |inet|
bindings << Facter::Util::Resolvers::Networking.build_binding(inet[0], inet[1])
end
bindings
end
Expand Down
17 changes: 16 additions & 1 deletion spec/facter/resolvers/networking_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
describe Facter::Resolvers::Networking do
subject(:networking) { Facter::Resolvers::Networking }

let(:log_spy) { instance_spy(Facter::Log) }

describe '#resolve' do
before do
allow(Facter::Util::Resolvers::Networking::PrimaryInterface)
Expand Down Expand Up @@ -37,7 +39,7 @@
end

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

Expand Down Expand Up @@ -135,6 +137,19 @@
expect(networking.resolve(:interfaces)['utun3']).to include(expected)
end

it 'checks interface utun4' do
expected = { bindings: [{ address: '192.0.2.100', netmask: '255.255.255.255', network: '192.0.2.100' }] }
expect(networking.resolve(:interfaces)['utun4']).to include(expected)
end

it 'checks interface utun5' do
expected = { bindings6: [
{ address: '2001:db8::1', netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
network: '2001:db8::1', scope6: 'global' }
] }
expect(networking.resolve(:interfaces)['utun5']).to include(expected)
end

it 'checks interface ib0 has the expected mac' do
expected = { mac: '80:00:02:08:FA:81:00:00:00:00:00:00:00:00:00:00:00:00:00:00' }
expect(networking.resolve(:interfaces)['ib0']).to include(expected)
Expand Down
37 changes: 21 additions & 16 deletions spec/fixtures/ifconfig_mac
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=400<CHANNEL_IO>
ether 64:5a:ed:ea:5c:81
ether 64:5a:ed:ea:5c:81
inet 192.168.143.212 netmask 0xffffff00 broadcast 192.168.143.255
media: autoselect
status: active
Expand All @@ -23,17 +23,17 @@ en0.1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=460<TSO4,TSO6,CHANNEL_IO>
ether 82:17:0e:93:9d:00
ether 82:17:0e:93:9d:00
media: autoselect <full-duplex>
status: inactive
en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=460<TSO4,TSO6,CHANNEL_IO>
ether 82:17:0e:93:9d:01
ether 82:17:0e:93:9d:01
media: autoselect <full-duplex>
status: inactive
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=63<RXCSUM,TXCSUM,TSO4,TSO6>
ether 82:17:0e:93:9d:00
ether 82:17:0e:93:9d:00
Configuration:
id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
Expand All @@ -47,33 +47,39 @@ bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
status: inactive
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
options=400<CHANNEL_IO>
ether 06:5a:ed:ea:5c:81
ether 06:5a:ed:ea:5c:81
media: autoselect
status: inactive
awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484
options=400<CHANNEL_IO>
ether 2e:ba:e4:83:4b:b7
inet6 fe80::2cba:e4ff:fe83:4bb7%awdl0 prefixlen 64 scopeid 0x9
ether 2e:ba:e4:83:4b:b7
inet6 fe80::2cba:e4ff:fe83:4bb7%awdl0 prefixlen 64 scopeid 0x9
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: active
llw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=400<CHANNEL_IO>
ether 2e:ba:e4:83:4b:b7
inet6 fe80::2cba:e4ff:fe83:4bb7%llw0 prefixlen 64 scopeid 0xa
ether 2e:ba:e4:83:4b:b7
inet6 fe80::2cba:e4ff:fe83:4bb7%llw0 prefixlen 64 scopeid 0xa
nd6 options=201<PERFORMNUD,DAD>
media: aumm,l.j hn toselect
status: active
utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
inet6 fe80::ba29:a797:6aa:9eb%utun0 prefixlen 64 scopeid 0xb
inet6 fe80::ba29:a797:6aa:9eb%utun0 prefixlen 64 scopeid 0xb
nd6 options=201<PERFORMNUD,DAD>
utun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000
inet6 fe80::64c6:1885:bec0:c316%utun1 prefixlen 64 scopeid 0xc
inet6 fe80::64c6:1885:bec0:c316%utun1 prefixlen 64 scopeid 0xc
nd6 options=201<PERFORMNUD,DAD>
utun2: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
inet 10.16.132.213 --> 10.16.132.213 netmask 0xfffffe00
inet 10.16.132.213 --> 10.16.132.213 netmask 0xfffffe00
utun3: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
inet6 2001:db8:cafe::132:213 --> 2001:db8:cafe::132:213 prefixlen 128
utun4: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
tunnel inet 192.0.2.1 --> 192.0.2.2
inet 192.0.2.100 --> 192.0.2.101 netmask 0xffffffff
utun5: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
tunnel inet 192.0.2.1 --> 192.0.2.2
inet6 2001:db8::1 --> 2001:db8::2 prefixlen 128
ib0: flags=4099<UP,BROADCAST,MULTICAST> mtu 4092
infiniband 80:00:02:08:FA:81:00:00:00:00:00:00:00:00:00:00:00:00:00:00 txqueuelen 256 (InfiniBand)
RX packets 0 bytes 0 (0.0 B)
Expand All @@ -87,4 +93,3 @@ ib1: flags=4099<UP,BROADCAST,MULTICAST> mtu 4092
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

0 comments on commit 8260822

Please sign in to comment.