diff --git a/lib/linux/iptables.rb b/lib/linux/iptables.rb index 0af7cf0..a504367 100644 --- a/lib/linux/iptables.rb +++ b/lib/linux/iptables.rb @@ -6,13 +6,15 @@ require 'ffi' # - robust pre-existing code # - good handling of nested structures and nested arrays # Bad things about FFI::Struct: -# - no Hash initialization: MyStruct.new(:foo=>1, :bar=>2) -# - no accessor methods m.foo = 1 +# - no Hash initialization: MyStruct.new(:foo=>1, :bar=>2) [*] +# - no accessor methods m.foo = 1 [*] # - can't do zero size array at end of struct: layout :foo, [Foo, 0] # - no network-order fields? (in_addr) -# - no decent inspect (fix this below) +# - no decent inspect [*] +# [*] Fixed below in FFI::AStruct -class FFI::Struct +class FFI::AStruct < FFI::Struct + # https://github.com/ffi/ffi/issues/102 def inspect res = "#<#{self.class}" members.zip(values).each do |m,v| @@ -20,8 +22,34 @@ class FFI::Struct end res << ">" end + + # https://github.com/ffi/ffi/issues/106 + def initialize(*args) + if args.first.is_a? Hash + super(nil, *args[1..-1]) + src.each { |k,v| self[k] = v } + else + super + end + end + + # https://github.com/ffi/ffi/issues/107 + def self.layout(*fields) + super + fields.each_slice(2) do |name,type| + # Structure building is screwed up if there's a 'size' member! + next if instance_methods.find { |m| m.to_sym == name } + define_method name do + self[name] + end + define_method "#{name}=" do |v| + self[name] = v + end + end + end end +# https://github.com/ffi/ffi/issues/102 class FFI::StructLayout::CharArray def inspect to_s.inspect diff --git a/lib/linux/iptables4.rb b/lib/linux/iptables4.rb index e4239f7..6a87080 100644 --- a/lib/linux/iptables4.rb +++ b/lib/linux/iptables4.rb @@ -7,7 +7,7 @@ module Linux #+ # struct ipt_getinfo - class IPTGetInfo < FFI::Struct + class IPTGetInfo < FFI::AStruct layout :name, [:char, IPT_TABLE_MAXNAMELEN], :valid_hooks, :uint, :hook_entry, [:uint, NF_INET_NUMHOOKS], @@ -16,7 +16,7 @@ module Linux :size, :uint end - class IPTIP < FFI::Struct + class IPTIP < FFI::AStruct layout :src, :int32, # FIXME: needs ntohl :dst, :int32, :smsk, :int32, @@ -31,13 +31,13 @@ module Linux end # struct xt_counters (netfilter/x_tables.h) - class XTCounters < FFI::Struct + class XTCounters < FFI::AStruct layout :pcnt, :uint64, :bcnt, :uint64 end # struct ipt_entry - class IPTEntry < FFI::Struct + class IPTEntry < FFI::AStruct layout :ip, IPTIP, :nfcache, :uint, :target_offset, :uint16, # size of ipt_entry + matches @@ -48,7 +48,7 @@ module Linux end # struct ipt_get_entries - class IPTGetEntries < FFI::Struct + class IPTGetEntries < FFI::AStruct layout :name, [:uchar, IPT_TABLE_MAXNAMELEN], :size, :uint, :entrytable, [IPTEntry, 1] # should be [IPTEntry, 0]