diff options
author | tpowell-progress <104777878+tpowell-progress@users.noreply.github.com> | 2022-05-31 14:44:17 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-31 14:44:17 -0500 |
commit | 06fc3473963d182f83e4b55622e10e0faab54f98 (patch) | |
tree | 5ff3b8f5f328839daf7e4447f4db34f799f3facf | |
parent | 062d2b42bc3c235335956ee2ff62d1f520714637 (diff) | |
parent | eab8a763263295dff15d1893f257312b1851749c (diff) | |
download | ohai-06fc3473963d182f83e4b55622e10e0faab54f98.tar.gz |
Merge pull request #1741 from mattp-/main
networking/linux: map src only default routes accordingly
-rw-r--r-- | lib/ohai/plugins/linux/network.rb | 21 | ||||
-rw-r--r-- | spec/unit/plugins/linux/network_spec.rb | 68 |
2 files changed, 86 insertions, 3 deletions
diff --git a/lib/ohai/plugins/linux/network.rb b/lib/ohai/plugins/linux/network.rb index 4a5ddb3c..eb83843c 100644 --- a/lib/ohai/plugins/linux/network.rb +++ b/lib/ohai/plugins/linux/network.rb @@ -103,9 +103,24 @@ Ohai.plugin(:Network) do next end route_endings.each do |route_ending| + route_entry = Mash.new(destination: route_dest, + family: family[:name]) + route_int = nil if route_ending =~ /\bdev\s+([^\s]+)\b/ route_int = $1 - else + end + # does any known interface own the src address? + # we try to infer the interface/device from its address if it isn't specified + # we want to override the interface set via nexthop but only if possible + if line =~ /\bsrc\s+([^\s]+)\b/ && (!route_int || line.include?("nexthop")) + # only clobber previously set route_int if we find a match + if (match = iface.select { |name, intf| intf.fetch("addresses", {}).any? { |addr, _| addr == $1 } }.keys.first) + route_int = match + route_entry[:inferred] = true + end + end + + unless route_int logger.trace("Plugin Network: Skipping route entry without a device: '#{line}'") next end @@ -116,8 +131,6 @@ Ohai.plugin(:Network) do next end - route_entry = Mash.new(destination: route_dest, - family: family[:name]) %w{via scope metric proto src}.each do |k| # http://rubular.com/r/pwTNp65VFf route_entry[k] = $1 if route_ending =~ /\b#{k}\s+([^\s]+)/ @@ -645,10 +658,12 @@ Ohai.plugin(:Network) do # sorting the selected routes: # - getting default routes first # - then sort by metric + # - then sort by if the device was inferred or not (preferring explicit to inferred) # - then by prefixlen [ r[:destination] == "default" ? 0 : 1, r[:metric].nil? ? 0 : r[:metric].to_i, + r[:inferred] ? 1 : 0, # for some reason IPAddress doesn't accept "::/0", it doesn't like prefix==0 # just a quick workaround: use 0 if IPAddress fails begin diff --git a/spec/unit/plugins/linux/network_spec.rb b/spec/unit/plugins/linux/network_spec.rb index 48f84ffc..810fc37f 100644 --- a/spec/unit/plugins/linux/network_spec.rb +++ b/spec/unit/plugins/linux/network_spec.rb @@ -477,6 +477,7 @@ describe Ohai::System, "Linux Network Plugin" do end before do + allow(File).to receive(:exist?).and_call_original allow(plugin).to receive(:collect_os).and_return(:linux) allow(plugin).to receive(:shell_out).with("ip addr").and_return(mock_shell_out(0, linux_ip_addr, "")) @@ -1335,6 +1336,73 @@ describe Ohai::System, "Linux Network Plugin" do end end + # notes: + # route 172.16.19.39 is the addr of tun0 ; see :linux_ifconfig at top of file + # route 10.116.201.0/24 is discarded because it is not a default route + # route 192.168.0.0/24 is discarded because src 192.168.0.2 does not match eth0 ("Skipping route entry whose src does not match the interface IP") + # route 172.16.19.39 is chosen over 10.116.201.254 because its metric is lower (10 < 20) + describe "when there's a source field in a local route entry but no dev in the route" do + let(:linux_ip_route) do + <<~EOM + default proto bird src 172.16.19.39 metric 10 \\ nexthop via 10.1.81.1 dev eth0 weight 20 + default via 10.116.201.254 dev eth0 metric 20 src 10.116.201.74 + 10.116.201.0/24 dev eth0 proto kernel src 10.116.201.76 + 192.168.0.0/24 dev eth0 proto kernel src 192.168.0.2 + EOM + end + let(:linux_ip_route_inet6) { "" } + + it "maps the no-dev route and sets ipaddress" do + plugin.run + expect(plugin["ipaddress"]).to eq("172.16.19.39") + end + end + + # notes: + # route 172.16.19.39 is the addr of tun0 ; see :linux_ifconfig at top of file + # route 10.116.201.0/24 is discarded because it is not a default route + # route 192.168.0.0/24 is discarded because src 192.168.0.2 does not match eth0 ("Skipping route entry whose src does not match the interface IP") + # route 10.116.201.254 is chosen over 172.16.19.39 and 10.116.201.1 because its metric is lower (5 < 10, 10) + describe "when there's a source field in a local route entry but no dev with a higher priority default route" do + let(:linux_ip_route) do + <<~EOM + default via 10.116.201.254 dev eth0 metric 5 src 10.116.201.74 + default proto bird src 172.16.19.39 metric 10 \\ nexthop via 10.1.81.1 dev eth0 weight 20 + default via 10.116.201.1 dev eth0 metric 10 src 10.116.201.1 + 10.116.201.0/24 dev eth0 proto kernel src 10.116.201.76 + 192.168.0.0/24 dev eth0 proto kernel src 192.168.0.2 + EOM + end + let(:linux_ip_route_inet6) { "" } + + it "maps the dev route and sets ipaddress" do + plugin.run + expect(plugin["ipaddress"]).to eq("10.116.201.74") + end + end + + # notes: + # route 172.16.19.39 is the addr of tun0 ; see :linux_ifconfig at top of file + # route 10.116.201.0/24 is discarded because it is not a default route + # route 192.168.0.0/24 is discarded because src 192.168.0.2 does not match eth0 ("Skipping route entry whose src does not match the interface IP") + # route 10.116.201.254 is chosen over 172.16.19.39 because routes with an explict device are preferred over ones that are inferred when metrics are equal + describe "when there's a source field in a local route entry but no dev, but a dev route with the same metric" do + let(:linux_ip_route) do + <<~EOM + default proto bird src 172.16.19.39 metric 10 \\ nexthop via 10.1.81.1 dev eth0 weight 20 + default via 10.116.201.254 dev eth0 metric 10 src 10.116.201.74 + 10.116.201.0/24 dev eth0 proto kernel src 10.116.201.76 + 192.168.0.0/24 dev eth0 proto kernel src 192.168.0.2 + EOM + end + let(:linux_ip_route_inet6) { "" } + + it "maps the dev route and sets ipaddress" do + plugin.run + expect(plugin["ipaddress"]).to eq("10.116.201.74") + end + end + describe "with a link level default route" do let(:linux_ip_route) do <<~EOM |