class Netfilter::InterfaceTable

Class representing the table of interfaces.

Constants

IFFLAGS
IFNAMSIZ

Public Class Methods

new() click to toggle source
# File lib/nfnetlink.rb, line 89
def initialize
    @lock = Mutex.new
    @nlif_handle = Netlink.nlif_open
    raise NetlinkError, "nlif_open has failed" if @nlif_handle.null?

    query_table
    ObjectSpace.define_finalizer(self, proc { Netlink.nlif_close(@nlif_handle) })
end

Public Instance Methods

[](index) click to toggle source

Gets an interface by index. Return value is a Hash with attributes :name and :flags. Returns nil if interface does not exist.

# File lib/nfnetlink.rb, line 103
def [](index)
    @lock.synchronize {
        update_table
        get_iface(index)
    }
end
each() { |iface| ... } click to toggle source

Enumerator for the list of interfaces.

# File lib/nfnetlink.rb, line 113
def each
    @lock.synchronize {
        update_table
        for index in 1..65535
            iface = get_iface(index)
            next if iface.nil?

            yield(iface)
        end
    }
end

Private Instance Methods

get_iface(index) click to toggle source
# File lib/nfnetlink.rb, line 157
def get_iface(index)
    ifname = FFI::Buffer.new(IFNAMSIZ, 1, true) 
    ret = Netlink.nlif_index2name(@nlif_handle, index, ifname)
    if ret < 0
        if FFI.errno == Errno::ENOENT::Errno
            nil
        else
            raise NetlinkError, "nlif_index2name has failed"
        end
    else
        name = ifname.get_string(0)
        return { :name => name, :flags => [] } if index == 0

        ifflags = FFI::Buffer.new(FFI.type_size(FFI::Type::UINT))
        if Netlink.nlif_get_ifflags(@nlif_handle, index, ifflags) < 0
            raise NetlinkError, "nlif_get_ifflags has failed"
        end

        flags = ifflags.read_bytes(ifflags.total).unpack("I")[0]
        flags_set = IFFLAGS.select { |bit, name| flags & bit != 0 }.values

        { :index => index,
          :name => name,
          :flags => flags_set }
    end
end
query_table() click to toggle source

Gets the internal list of interfaces.

# File lib/nfnetlink.rb, line 151
def query_table 
    if Netlink.nlif_query(@nlif_handle) < 0
        raise NetlinkError, "nlif_query has failed"
    end
end
update_table() click to toggle source

Process netlink events and updates list of interfaces.

# File lib/nfnetlink.rb, line 130
def update_table
    nlif_fd = Netlink.nlif_fd(@nlif_handle)
    raise NetlinkError, "nlif_fd has failed" if nlif_fd < 0

    nlif_io = IO.new(nlif_fd)
    nlif_io.autoclose = false

    rs, _ws, _es = IO.select([nlif_io], [], [], 0)    

    if rs and rs.length > 0 and rs[0] == nlif_io
        if Netlink.nlif_catch(@nlif_handle) < 0
            raise NetlinkError, "nlif_catch has failed"
        end
    end

    nlif_io.close
end