Files
netlinkrb/lib/linux/iptables4.rb
Brian Candler 40fbefa06b Experiment: try using FFI::Struct for iptables instead of CStruct
FFI::Struct handles nested structs and nested arrays much better, and avoids
duplicating logic about structure alignment (which it probably does more
correctly that CStruct)

However it's awkward to use in other ways. e.g. no accessor methods;
no proper #inspect; no ntohl for in_addr; no zero-sized arrays at end
of struct; no hooks to convert int32 <-> IPAddr as far as I can see.
2011-05-06 17:01:50 +01:00

82 lines
2.2 KiB
Ruby

require 'linux/iptables'
require 'ipaddr'
module Linux
#-
# Definitions mainly from linux/netfilter_ipv4/ip_tables.h
#+
# struct ipt_getinfo
class IPTGetInfo < FFI::Struct
layout :name, [:char, IPT_TABLE_MAXNAMELEN],
:valid_hooks, :uint,
:hook_entry, [:uint, NF_INET_NUMHOOKS],
:underflow, [:uint, NF_INET_NUMHOOKS],
:num_entries, :uint,
:size, :uint
end
class IPTIP < FFI::Struct
layout :src, :int32, # FIXME: needs ntohl
:dst, :int32,
:smsk, :int32,
:dmsk, :int32,
:iniface, [:char, IFNAMSIZ],
:outiface, [:char, IFNAMSIZ],
:iniface_mask, [:uchar, IFNAMSIZ],
:outiface_mask, [:uchar, IFNAMSIZ],
:proto, :uint16,
:flags, :uint8,
:invflags, :uint8
end
# struct xt_counters (netfilter/x_tables.h)
class XTCounters < FFI::Struct
layout :pcnt, :uint64,
:bcnt, :uint64
end
# struct ipt_entry
class IPTEntry < FFI::Struct
layout :ip, IPTIP,
:nfcache, :uint,
:target_offset, :uint16, # size of ipt_entry + matches
:next_offset, :uint16, # size of ipt_entry + matches + target
:comefrom, :uint,
:counters, XTCounters,
:elems, [:uchar, 1] # should be [:uchar, 0]
end
# struct ipt_get_entries
class IPTGetEntries < FFI::Struct
layout :name, [:uchar, IPT_TABLE_MAXNAMELEN],
:size, :uint,
:entrytable, [IPTEntry, 1] # should be [IPTEntry, 0]
end
# Class for handling iptables. Note that this doesn't actually use
# Netlink at all :-(
class Iptables4 < Iptables
PROC_TABLES = "/proc/net/ip_tables_names"
PROC_TARGETS = "/proc/net/ip_tables_targets"
PROC_MATCHES = "/proc/net/ip_tables_matches"
TABLE_MAXNAMELEN = IPT_TABLE_MAXNAMELEN
TC_AF = Socket::AF_INET
TC_IPPROTO = Socket::IPPROTO_IP
SO_GET_INFO = IPT_SO_GET_INFO
SO_GET_ENTRIES = IPT_SO_GET_ENTRIES
STRUCT_ENTRY = IPTEntry
STRUCT_GETINFO = IPTGetInfo
STRUCT_GET_ENTRIES = IPTGetEntries
# This is a frig because of [1] instead of [0] above
STRUCT_GET_ENTRIES_SIZE = IPTGetEntries.offset_of(:entrytable)
end
end
if __FILE__ == $0
require 'pp'
pp Linux::Iptables4.tables
pp Linux::Iptables4.table("filter").rules
end