Simple grouping by ifindex
This commit is contained in:
@@ -60,12 +60,12 @@ module Netlink
|
||||
# msg = Foo.new(:bar => 123) # or ("bar" => 123)
|
||||
# msg2 = Foo.new(msg)
|
||||
# msg3 = Foo.new(:qux => 999) # error, no method "qux="
|
||||
def initialize(h={})
|
||||
def initialize(h=nil)
|
||||
if h.instance_of?(self.class)
|
||||
@attrs = h.to_hash.dup
|
||||
else
|
||||
@attrs = self.class::DEFAULTS.dup
|
||||
h.each { |k,v| self[k] = v }
|
||||
h.each { |k,v| self[k] = v } if h
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -109,14 +109,15 @@ module Netlink
|
||||
# are accepted.
|
||||
#
|
||||
# (Compare: rtnl_dump_filter_l in lib/libnetlink.c)
|
||||
def receive_until_done(timeout=@timeout, junk_handler=nil, &blk) #:yields: type, flags, obj
|
||||
def receive_until_done(expect_type=nil, timeout=@timeout, junk_handler=nil, &blk) #:yields: type, flags, obj
|
||||
res = []
|
||||
blk ||= lambda { |type, flags, obj| res << obj if obj }
|
||||
junk_handler ||= lambda { |obj| warn "Discarding junk message #{obj}" } if $VERBOSE
|
||||
junk_handler ||= lambda { |type, flags, seq, pid, obj|
|
||||
warn "Discarding junk message (#{type}) #{obj}" } if $VERBOSE
|
||||
loop do
|
||||
receive_response(timeout) do |type, flags, seq, pid, obj|
|
||||
if pid != @pid || seq != @seq
|
||||
junk_handler[obj] if junk_handler
|
||||
junk_handler[type, flags, seq, pid, obj] if junk_handler
|
||||
next
|
||||
end
|
||||
case type
|
||||
@@ -125,6 +126,10 @@ module Netlink
|
||||
when NLMSG_ERROR
|
||||
raise "Netlink Error received"
|
||||
end
|
||||
if expect_type && type != expect_type
|
||||
junk_handler[type, flags, seq, pid, obj] if junk_handler
|
||||
next
|
||||
end
|
||||
blk.call(type, flags, obj)
|
||||
end
|
||||
end
|
||||
|
@@ -8,38 +8,74 @@ module Netlink
|
||||
super(opt.merge(:protocol => Netlink::NETLINK_ROUTE))
|
||||
end
|
||||
|
||||
# List links. Returns an array of Netlink::Link objects
|
||||
def link_list(opt)
|
||||
# List links (interfaces). Returns an array of Netlink::Link objects.
|
||||
# res = nl.link_list
|
||||
# p res
|
||||
# [#<Netlink::Link {:family=>0, :pad=>0, :type=>772, :index=>1,
|
||||
# :flags=>65609, :change=>0, :ifname=>"lo", :txqlen=>0, :operstate=>0,
|
||||
# :linkmode=>0, :mtu=>16436, :qdisc=>"noqueue", :map=>"...",
|
||||
# :address=>"\x00\x00\x00\x00\x00\x00", :broadcast=>"\x00\x00\x00\x00\x00\x00",
|
||||
# :stats=>#<struct Netlink::LinkStats rx_packets=22, ...>,
|
||||
# :stats64=>#<struct Netlink::LinkStats rx_packets=22, ...>}>, ...]
|
||||
def links(opt=nil)
|
||||
send_request RTM_GETLINK, Link.new(opt),
|
||||
NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST
|
||||
receive_until_done
|
||||
receive_until_done(RTM_NEWLINK)
|
||||
end
|
||||
|
||||
# Return a Hash of Netlink::Link objects keyed by interface index, which
|
||||
# is what the 'routes' and 'addrs' objects point to.
|
||||
def links_by_index(opt=nil)
|
||||
res = {}
|
||||
links(opt).each { |obj| res[obj.index] = obj }
|
||||
res
|
||||
end
|
||||
|
||||
# List routes. Returns an array of Netlink::Route objects
|
||||
# res = nl.routes(:family => Socket::AF_INET)
|
||||
# #=> [..., ...]
|
||||
def route_list(opt)
|
||||
# p res
|
||||
# [#<Netlink::Route {:family=>2, :dst_len=>32, :src_len=>0, :tos=>0,
|
||||
# :table=>255, :protocol=>2, :scope=>253, :type=>3, :flags=>0, :table2=>255,
|
||||
# :dst=>#<IPAddr: IPv4:127.255.255.255/255.255.255.255>,
|
||||
# :prefsrc=>#<IPAddr: IPv4:127.0.0.1/255.255.255.255>, :oif=>1}>, ...]
|
||||
#
|
||||
# Note that not all attributes will always be present. In particular,
|
||||
# a defaultroute (dst_len=0) misses out the dst address completely:
|
||||
#
|
||||
# [#<Netlink::Route {:family=>2, :dst_len=>0, :src_len=>0, :tos=>0,
|
||||
# :table=>254, :protocol=>4, :scope=>0, :type=>1, :flags=>0, :table2=>254,
|
||||
# :gateway=>#<IPAddr: IPv4:10.69.255.253/255.255.255.255>, :oif=>2}>, ...]
|
||||
def routes(opt=nil)
|
||||
send_request RTM_GETROUTE, Route.new(opt),
|
||||
NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST
|
||||
receive_until_done
|
||||
receive_until_done(RTM_NEWROUTE)
|
||||
end
|
||||
|
||||
def addr_list(opt)
|
||||
# Return routes as a hash of {index=>[route,route], index=>[route,route]}
|
||||
def routes_by_oif(opt=nil)
|
||||
res = routes(opt).group_by { |obj| obj.oif }
|
||||
res.default = [].freeze
|
||||
res
|
||||
end
|
||||
|
||||
# List addresses. Return an array of Netlink::Addr objects.
|
||||
# You will need to use the 'index' to cross reference to the interface.
|
||||
# res = nl.addrs(:family => Socket::AF_INET)
|
||||
# p res
|
||||
# [#<Netlink::Addr {:family=>2, :prefixlen=>8, :flags=>128, :scope=>254,
|
||||
# :index=>1, :address=>#<IPAddr: IPv4:127.0.0.1/255.255.255.255>,
|
||||
# :local=>#<IPAddr: IPv4:127.0.0.1/255.255.255.255>, :label=>"lo"}>, ...]
|
||||
def addrs(opt=nil)
|
||||
send_request RTM_GETADDR, Addr.new(opt),
|
||||
NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST
|
||||
receive_until_done
|
||||
receive_until_done(RTM_NEWADDR)
|
||||
end
|
||||
|
||||
# Add a route
|
||||
# nl.add_route(:family => Socket::AF_INET, ...)
|
||||
def route_add(r)
|
||||
send_request RTM_NEWROUTE, Route.new(r)
|
||||
# Do we get any success/fail?
|
||||
end
|
||||
|
||||
# Delete a route
|
||||
def route_delete(r)
|
||||
send_request RTM_DELROUTE, Route.new(r)
|
||||
# Return addresses as a hash of {index=>[addr,addr], index=>[addr,addr]}
|
||||
def addrs_by_index(opt=nil)
|
||||
res = addrs(opt).group_by { |obj| obj.index }
|
||||
res.default = [].freeze
|
||||
res
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -47,10 +83,23 @@ end
|
||||
if __FILE__ == $0
|
||||
require 'pp'
|
||||
nl = Netlink::RTSocket.new
|
||||
puts "*** routes ***"
|
||||
pp nl.route_list(:family => Socket::AF_INET)
|
||||
puts "*** links ***"
|
||||
pp nl.link_list(:family => Socket::AF_INET)
|
||||
puts "*** addrs ***"
|
||||
pp nl.addr_list(:family => Socket::AF_INET)
|
||||
#puts "*** routes ***"
|
||||
#pp nl.routes(:family => Socket::AF_INET)
|
||||
#puts "*** links ***"
|
||||
#pp nl.links(:family => Socket::AF_INET)
|
||||
#puts "*** addrs ***"
|
||||
#pp nl.addrs(:family => Socket::AF_INET)
|
||||
links = nl.links
|
||||
addrs = nl.addrs_by_index(:family=>Socket::AF_UNSPEC)
|
||||
routes = nl.routes_by_oif(:family=>Socket::AF_UNSPEC)
|
||||
links.each do |link|
|
||||
puts "#{link.ifname}"
|
||||
addrs[link.index].each do |addr|
|
||||
puts " family=#{addr.family} #{addr.address}/#{addr.prefixlen} label=#{addr.label}"
|
||||
end
|
||||
routes[link.index].each do |route|
|
||||
#p route
|
||||
puts " >> family=#{route.family} #{route.dst}/#{route.dst_len} gw=#{route.gateway}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user