Skip to content

Instantly share code, notes, and snippets.

@kuredev
Created Aug 11, 2021
Embed
What would you like to do?
require "ipaddr"
class RouteTable
def initialize(routes)
@routes = routes
end
# IPAddr or nil
# nil -> direct connected
def next_hop_route_entry(dst_addr)
return nil if direct_connected?(dst_addr)
# デフォルトルートの場合
default_routes = @routes.select { |route| route.direct_network_addr.nil? }
# デフォルトルートのうち、メトリクス値が無いのがあった場合はそれを返す
top_priority_route = default_routes.find { |default_routes| default_routes.metric.nil? }
return top_priority_route unless top_priority_route.nil?
# 最もメトリクス値が小さいデフォルトルートのエントリを返す
default_routes.min_by do |default_route|
default_route.metric
end
end
private
def direct_connected?(dst_addr)
@routes.find do |route|
next if route.direct_network_addr.nil?
route.direct_network_addr.include?(IPAddr.new(dst_addr))
end
end
end
class RouteEntry
attr_reader :direct_network_addr, :next_hop_addr, :next_hop_device, :direct_network_addr, :direct_network_device, :metric
# ex)
# default via 172.31.0.1 dev eth0
# 172.18.0.0/16 dev br-8140256d9f85 proto kernel scope link src 172.18.0.1 linkdown
# 172.31.34.0/24 dev eth2 proto kernel scope link src 172.31.34.23
def initialize(route_string: nil)
@route_string = route_string
parse_route_from_string unless @route_string.empty?
end
def to_s
"direct_connected: #{@direct_connected}, next_hop_addr: #{@next_hop_addr}, " + \
"next_hop_device: #{@next_hop_device}, direct_network_addr: #{@direct_network_addr}, " + \
"direct_network_device: #{@direct_network_device}"
end
private
def parse_route_from_string
params = @route_string.split(" ")
if params[0] == "default"
@direct_connected = true
@next_hop_addr = IPAddr.new(params[2])
@next_hop_device = params[4]
@direct_network_addr = nil
@direct_network_device = nil
@metric = params[6] # metric 値がない(最優先のルート)場合は nil
else
@direct_connected = false
@next_hop_addr = nil
@next_hop_device = nil
@direct_network_addr = IPAddr.new(params[0])
@direct_network_device = params[2]
@metric = nil
end
end
end
output = `ip route`
routes_string = output.split("\n")
routes = routes_string.map do |route_string|
RouteEntry.new(route_string: route_string)
end
rt = RouteTable.new(routes)
pp rt.next_hop_route_entry("8.8.8.8") # #<RouteEntry 172.31.0.1/255.255.255.255>
pp rt.next_hop_route_entry("172.31.34.1") # nil
@kuredev
Copy link
Author

kuredev commented Aug 11, 2021

NextHopのアドレスを取得するスクリプト

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment