update to iptables-1.3.8 netfilter
authorMarc Fiuczynski <mef@cs.princeton.edu>
Tue, 27 Nov 2007 19:16:34 +0000 (19:16 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Tue, 27 Nov 2007 19:16:34 +0000 (19:16 +0000)
195 files changed:
Makefile
Rules.make
extensions/.BALANCE-test [deleted file]
extensions/.FTOS-test [deleted file]
extensions/.IPMARK-test [deleted file]
extensions/.NETLINK-test [deleted file]
extensions/.NFLOG-test [new file with mode: 0755]
extensions/.NFLOG-test6 [new file with mode: 0755]
extensions/.ROUTE-test [deleted file]
extensions/.ROUTE-test6 [deleted file]
extensions/.TARPIT-test [new file with mode: 0755]
extensions/.TCPLAG-test [deleted file]
extensions/.XOR-test [deleted file]
extensions/.account-test [deleted file]
extensions/.childlevel-test [deleted file]
extensions/.connbytes-test
extensions/.connrate-test [deleted file]
extensions/.dstlimit-test [deleted file]
extensions/.esp-test6
extensions/.fuzzy-test [deleted file]
extensions/.fuzzy-test6 [deleted file]
extensions/.hashlimit-test6 [new file with mode: 0755]
extensions/.mh-test6 [new file with mode: 0755]
extensions/.mport-test [deleted file]
extensions/.nth-test [deleted file]
extensions/.nth-test6 [deleted file]
extensions/.osf-test [deleted file]
extensions/.psd-test [deleted file]
extensions/.quota-test
extensions/.random-test [deleted file]
extensions/.random-test6 [deleted file]
extensions/.record-rpc-test [deleted file]
extensions/.sctp-test6 [new file with mode: 0755]
extensions/.statistic-test [new file with mode: 0755]
extensions/.time-test [deleted file]
extensions/Makefile
extensions/libip6t_CONNSECMARK.c [new file with mode: 0644]
extensions/libip6t_CONNSECMARK.man [new file with mode: 0644]
extensions/libip6t_LOG.c
extensions/libip6t_NFLOG.c [new file with mode: 0644]
extensions/libip6t_ROUTE.c [deleted file]
extensions/libip6t_ROUTE.man [deleted file]
extensions/libip6t_SECMARK.c [new file with mode: 0644]
extensions/libip6t_SECMARK.man [new file with mode: 0644]
extensions/libip6t_TCPMSS.c [new file with mode: 0644]
extensions/libip6t_TCPMSS.man [new file with mode: 0644]
extensions/libip6t_TRACE.c [deleted file]
extensions/libip6t_TRACE.man [deleted file]
extensions/libip6t_esp.c
extensions/libip6t_eui64.man
extensions/libip6t_fuzzy.c [deleted file]
extensions/libip6t_fuzzy.man [deleted file]
extensions/libip6t_hashlimit.c [new file with mode: 0644]
extensions/libip6t_icmp6.c [moved from extensions/libip6t_icmpv6.c with 96% similarity]
extensions/libip6t_icmp6.man [moved from extensions/libip6t_icmpv6.man with 79% similarity]
extensions/libip6t_mh.c [new file with mode: 0644]
extensions/libip6t_mh.man [new file with mode: 0644]
extensions/libip6t_multiport.c
extensions/libip6t_multiport.man
extensions/libip6t_nth.c [deleted file]
extensions/libip6t_nth.man [deleted file]
extensions/libip6t_random.c [deleted file]
extensions/libip6t_random.man [deleted file]
extensions/libip6t_sctp.c [new file with mode: 0644]
extensions/libip6t_state.c
extensions/libip6t_tcp.c
extensions/libip6t_tcp.man
extensions/libip6t_udp.c
extensions/libip6t_udp.man
extensions/libipt_BALANCE.c [deleted file]
extensions/libipt_BALANCE.man [deleted file]
extensions/libipt_CONNSECMARK.c [new file with mode: 0644]
extensions/libipt_CONNSECMARK.man [new file with mode: 0644]
extensions/libipt_DNAT.c
extensions/libipt_DNAT.man
extensions/libipt_FTOS.c [deleted file]
extensions/libipt_IPMARK.c [deleted file]
extensions/libipt_IPMARK.man [deleted file]
extensions/libipt_LOG.c
extensions/libipt_MARK.man
extensions/libipt_MASQUERADE.c
extensions/libipt_MASQUERADE.man
extensions/libipt_NETLINK.c [deleted file]
extensions/libipt_NETMAP.c
extensions/libipt_NFLOG.c [new file with mode: 0644]
extensions/libipt_REDIRECT.c
extensions/libipt_REDIRECT.man
extensions/libipt_ROUTE.c [deleted file]
extensions/libipt_ROUTE.man [deleted file]
extensions/libipt_SAME.c
extensions/libipt_SAME.man
extensions/libipt_SECMARK.c [new file with mode: 0644]
extensions/libipt_SECMARK.man [new file with mode: 0644]
extensions/libipt_SET.c
extensions/libipt_SNAT.c
extensions/libipt_SNAT.man
extensions/libipt_TCPLAG.c [deleted file]
extensions/libipt_TRACE.c [deleted file]
extensions/libipt_TRACE.man [deleted file]
extensions/libipt_ULOG.c
extensions/libipt_XOR.c [deleted file]
extensions/libipt_XOR.man [deleted file]
extensions/libipt_account.c [deleted file]
extensions/libipt_account.man [deleted file]
extensions/libipt_childlevel.c [deleted file]
extensions/libipt_childlevel.man [deleted file]
extensions/libipt_connbytes.c
extensions/libipt_connlimit.c [deleted file]
extensions/libipt_connlimit.man [deleted file]
extensions/libipt_connrate.c
extensions/libipt_conntrack.c
extensions/libipt_dccp.c
extensions/libipt_dscp_helper.c
extensions/libipt_dstlimit.c [deleted file]
extensions/libipt_dstlimit.man [deleted file]
extensions/libipt_esp.c
extensions/libipt_fuzzy.c [deleted file]
extensions/libipt_fuzzy.man [deleted file]
extensions/libipt_hashlimit.man
extensions/libipt_icmp.c
extensions/libipt_icmp.man
extensions/libipt_iprange.c
extensions/libipt_ipv4options.c
extensions/libipt_mport.c [deleted file]
extensions/libipt_mport.man [deleted file]
extensions/libipt_multiport.c
extensions/libipt_nth.c [deleted file]
extensions/libipt_nth.man [deleted file]
extensions/libipt_osf.c [deleted file]
extensions/libipt_osf.man [deleted file]
extensions/libipt_psd.c [deleted file]
extensions/libipt_psd.man [deleted file]
extensions/libipt_quota.c
extensions/libipt_quota.man
extensions/libipt_random.c [deleted file]
extensions/libipt_random.man [deleted file]
extensions/libipt_realm.c
extensions/libipt_realm.man
extensions/libipt_record_rpc.c [deleted file]
extensions/libipt_rpc.c [deleted file]
extensions/libipt_sctp.c
extensions/libipt_set.c
extensions/libipt_set.h
extensions/libipt_state.c
extensions/libipt_statistic.c [new file with mode: 0644]
extensions/libipt_string.c
extensions/libipt_tcp.c
extensions/libipt_tcp.man
extensions/libipt_tcpmss.man
extensions/libipt_time.c [deleted file]
extensions/libipt_time.man [deleted file]
extensions/libipt_u32.c
extensions/libipt_udp.c
extensions/libipt_udp.man
include/ip6tables.h
include/iptables.h
include/iptables_common.h
include/linux/netfilter/nf_conntrack_common.h [new file with mode: 0644]
include/linux/netfilter/nf_conntrack_tuple.h [new file with mode: 0644]
include/linux/netfilter/nf_conntrack_tuple_common.h [new file with mode: 0644]
include/linux/netfilter/nf_nat.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ipt_conntrack.h
include/linux/netfilter_ipv6/ip6t_TCPMSS.h [new file with mode: 0644]
include/linux/netfilter_ipv6/ip6t_multiport.h [new file with mode: 0644]
ip6tables-restore.c
ip6tables-save.c
ip6tables.8.in
ip6tables.c
ipset/ChangeLog
ipset/Makefile
ipset/Makefile.orig [new file with mode: 0644]
ipset/ipset.8
ipset/ipset.c
ipset/ipset.h
ipset/ipset_iphash.c
ipset/ipset_ipmap.c
ipset/ipset_ipporthash.c
ipset/ipset_iptree.c
ipset/ipset_iptreemap.c [new file with mode: 0644]
ipset/ipset_macipmap.c
ipset/ipset_nethash.c
ipset/ipset_portmap.c
iptables-multi.c
iptables-restore.c
iptables-restore.c.orig [new file with mode: 0644]
iptables-save.c
iptables-standalone.c
iptables-xml.c [new file with mode: 0644]
iptables.8.in
iptables.c
iptables.xslt [new file with mode: 0644]
libiptc/Makefile
libiptc/libip4tc.c
libiptc/libip6tc.c
libiptc/libiptc.c

index 558367e..df04d35 100644 (file)
--- a/Makefile
+++ b/Makefile
 TOPLEVEL_INCLUDED=YES
 
 ifndef KERNEL_DIR
-KERNEL_DIR=/usr/src/linux
+KERNEL_DIR="/lib/modules/$(shell uname -r)/build"
 endif
-IPTABLES_VERSION:=1.3.5
-OLD_IPTABLES_VERSION:=1.3.4
+IPTABLES_VERSION:=1.3.8
+OLD_IPTABLES_VERSION:=1.3.7
 
 PREFIX:=/usr/local
 LIBDIR:=$(PREFIX)/lib
@@ -31,6 +31,11 @@ ifeq ($(shell [ -f /usr/include/netinet/ip6.h ] && echo YES), YES)
 DO_IPV6:=1
 endif
 
+# Enable linking to libselinux via enviornment 'DO_SELINUX=1'
+ifndef DO_SELINUX
+DO_SELINUX=0
+endif
+
 COPT_FLAGS:=-O2
 CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -I$(KERNEL_DIR)/include -Iinclude/ -DIPTABLES_VERSION=\"$(IPTABLES_VERSION)\" #-g -DDEBUG #-pg # -DIPTC_DEBUG
 
@@ -43,9 +48,9 @@ EXTRA_INSTALLS+=$(DESTDIR)$(BINDIR)/iptables $(DESTDIR)$(MANDIR)/man8/iptables.8
 
 # No longer experimental.
 ifneq ($(DO_MULTI), 1)
-EXTRAS+=iptables-save iptables-restore
+EXTRAS+=iptables-save iptables-restore iptables-xml
 endif
-EXTRA_INSTALLS+=$(DESTDIR)$(BINDIR)/iptables-save $(DESTDIR)$(BINDIR)/iptables-restore $(DESTDIR)$(MANDIR)/man8/iptables-restore.8 $(DESTDIR)$(MANDIR)/man8/iptables-save.8
+EXTRA_INSTALLS+=$(DESTDIR)$(BINDIR)/iptables-save $(DESTDIR)$(BINDIR)/iptables-restore $(DESTDIR)$(BINDIR)/iptables-xml $(DESTDIR)$(MANDIR)/man8/iptables-restore.8 $(DESTDIR)$(MANDIR)/man8/iptables-save.8
 
 ifeq ($(DO_IPV6), 1)
 EXTRAS+=ip6tables ip6tables.o ip6tables.8
@@ -62,7 +67,7 @@ ifeq ($(shell uname -m),sparc64)
                # The kernel is 64-bit, even though userspace is 32.
                CFLAGS+=-DIPT_MIN_ALIGN=8 -DKERNEL_64_USERSPACE_32
        else
-               EXT_LDFLAGS=-m elf64_sparc
+               EXT_LDFLAGS+=-Wl,-m,elf64_sparc
        endif
 endif
 
@@ -74,7 +79,7 @@ endif
 # Generic test if arch wasn't found above
 ifneq ($(POINTERTEST),1)
        # Try to determine if kernel is 64bit and we are compiling for 32bit
-       ifeq ($(shell [ -a $(KERNEL_DIR)/include/asm ] && echo YES), YES)
+       ifeq ($(shell [ -d $(KERNEL_DIR)/include/asm ] && echo YES), YES)
                64bitkernel := $(shell echo -e "\#include <asm/types.h>\n\#if BITS_PER_LONG == 64\nkernel_is_64bits\n\#endif" | $(CC) $(CFLAGS) -D__KERNEL__ -E - | grep kernel_is_64bits)
                ifdef 64bitkernel
                        32bituser := $(shell echo -e "\#include <stdio.h>\n\#if !defined(__arch64__) && !defined(_LP64)\nuserspace_is_32bit\n\#endif" | $(CC) $(CFLAGS) -E - | grep userspace_is_32bit)
@@ -93,17 +98,24 @@ endif
 
 ifndef NO_SHARED_LIBS
 DEPFILES = $(SHARED_LIBS:%.so=%.d)
+DEPFILES += $(SHARED_SE_LIBS:%.so=%.d)
 SH_CFLAGS:=$(CFLAGS) -fPIC
 STATIC_LIBS  =
 STATIC6_LIBS =
 LDFLAGS      = -rdynamic
-LDLIBS       = -ldl -lnsl
+LDLIBS       = -ldl
+ifeq ($(DO_SELINUX), 1)
+LDLIBS       += -lselinux
+endif
 else
 DEPFILES = $(EXT_OBJS:%.o=%.d)
 STATIC_LIBS  = extensions/libext.a
 STATIC6_LIBS = extensions/libext6.a
 LDFLAGS      = -static
-LDLIBS       =
+LDLIBS      =
+ifeq ($(DO_SELINUX), 1)
+LDLIBS       += -lselinux
+endif
 endif
 
 .PHONY: default
@@ -117,7 +129,7 @@ iptables.o: iptables.c
        $(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" -c -o $@ $<
 
 ifeq ($(DO_MULTI), 1)
-iptables: iptables-multi.c iptables-save.c iptables-restore.c iptables-standalone.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
+iptables: iptables-multi.c iptables-save.c iptables-restore.c iptables-xml.c iptables-standalone.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
        $(CC) $(CFLAGS) -DIPTABLES_MULTI -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
 else
 iptables: iptables-standalone.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
@@ -154,6 +166,19 @@ $(DESTDIR)$(BINDIR)/iptables-restore: iptables-restore
        cp $< $@
 endif
 
+iptables-xml: iptables-xml.c #iptables.o # $(STATIC_LIBS) libiptc/libiptc.a
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+ifeq ($(DO_MULTI), 1)
+$(DESTDIR)$(BINDIR)/iptables-xml: iptables
+       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
+       ln -sf $< $@
+else
+$(DESTDIR)$(BINDIR)/iptables-xml: iptables-xml
+       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
+       cp $< $@
+endif
+
 ip6tables.o: ip6tables.c
        $(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" -c -o $@ $<
 
@@ -224,7 +249,7 @@ distrib: check distclean delrelease $(RELEASE_DIR)/iptables-$(IPTABLES_VERSION).
 # -g -pg -DIPTC_DEBUG
 .PHONY: check
 check:
-       @if echo $(CFLAGS) | egrep -e '-g|-pg|IPTC_DEBUG' >/dev/null; then echo Remove debugging flags; exit 1; else exit 0; fi
+       @if echo $(CFLAGS) | egrep -e '(^|[[:space:]])(-g|-pg|-DIPTC_DEBUG)([[:space:]]|$)' >/dev/null; then echo Remove debugging flags; exit 1; else exit 0; fi
 
 .PHONY: nowhitespace
 nowhitespace:
index c0c5010..17ea017 100644 (file)
@@ -1,12 +1,12 @@
 #! /usr/bin/make
 
-all: $(SHARED_LIBS) $(EXTRAS)
+all: $(SHARED_LIBS) $(SHARED_SE_LIBS) $(EXTRAS)
 
 experimental: $(EXTRAS_EXP)
 
 # Have to handle extensions which no longer exist.
 clean: $(EXTRA_CLEANS)
-       rm -f $(SHARED_LIBS) $(EXTRAS) $(EXTRAS_EXP) $(SHARED_LIBS:%.so=%_sh.o)
+       rm -f $(SHARED_LIBS) $(SHARED_SE_LIBS) $(EXTRAS) $(EXTRAS_EXP) $(SHARED_LIBS:%.so=%_sh.o) $(SHARED_SE_LIBS:%.so=%_sh.o)
        rm -f extensions/initext.c extensions/initext6.c
        @find . -name '*.[ao]' -o -name '*.so' | xargs rm -f
 
@@ -31,7 +31,14 @@ $(SHARED_LIBS:%.so=%.d): %.d: %.c
            sed -e 's@^.*\.o:@$*.d $*_sh.o:@' > $@
 
 $(SHARED_LIBS): %.so : %_sh.o
-       $(LD) -shared $(EXT_LDFLAGS) -o $@ $<
+       $(CC) -shared $(EXT_LDFLAGS) -o $@ $<
+
+$(SHARED_SE_LIBS:%.so=%.d): %.d: %.c
+       @-$(CC) -M -MG $(CFLAGS) $< | \
+               sed -e 's@^.*\.o:@$*.d $*_sh.o:@' > $@
+
+$(SHARED_SE_LIBS): %.so : %_sh.o
+       $(LD) -shared $(EXT_LDFLAGS) -o $@ $< $(LDLIBS)
 
 %_sh.o : %.c
        $(CC) $(SH_CFLAGS) -o $@ -c $<
@@ -42,7 +49,7 @@ $(SHARED_LIBS): %.so : %_sh.o
 
 # This is useful for when dependencies completely screwed
 %.h::
-       @echo Something wrong... deleting dependencies.
+       @echo "Unable to resolve dependency on $@. Try 'make clean'."
        @-rm -f $(DEPFILES) $(EXTRA_DEPENDS) .makefirst
        @[ -d $(KERNEL_DIR)/include/linux/netfilter_ipv4 ] || echo -e '\n\n    Please try `make KERNEL_DIR=path-to-correct-kernel'\'.'\n\n'
        @exit 1
diff --git a/extensions/.BALANCE-test b/extensions/.BALANCE-test
deleted file mode 100755 (executable)
index 3a46d74..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_BALANCE.c ] && echo BALANCE
diff --git a/extensions/.FTOS-test b/extensions/.FTOS-test
deleted file mode 100755 (executable)
index d07fce7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_FTOS.h ] && echo FTOS
diff --git a/extensions/.IPMARK-test b/extensions/.IPMARK-test
deleted file mode 100755 (executable)
index 7996c88..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if IPMARK patch is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_IPMARK.h ] && echo IPMARK
diff --git a/extensions/.NETLINK-test b/extensions/.NETLINK-test
deleted file mode 100755 (executable)
index fe94c0c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_NETLINK.c ] && echo NETLINK
diff --git a/extensions/.NFLOG-test b/extensions/.NFLOG-test
new file mode 100755 (executable)
index 0000000..25f0dee
--- /dev/null
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter/xt_NFLOG.h ] && echo NFLOG
diff --git a/extensions/.NFLOG-test6 b/extensions/.NFLOG-test6
new file mode 100755 (executable)
index 0000000..25f0dee
--- /dev/null
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter/xt_NFLOG.h ] && echo NFLOG
diff --git a/extensions/.ROUTE-test b/extensions/.ROUTE-test
deleted file mode 100755 (executable)
index 8b7b3f0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_ROUTE.c ] && echo ROUTE
diff --git a/extensions/.ROUTE-test6 b/extensions/.ROUTE-test6
deleted file mode 100755 (executable)
index 7994970..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_ROUTE.h ] && echo ROUTE
diff --git a/extensions/.TARPIT-test b/extensions/.TARPIT-test
new file mode 100755 (executable)
index 0000000..150600a
--- /dev/null
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_TARPIT.c ] && echo TARPIT
diff --git a/extensions/.TCPLAG-test b/extensions/.TCPLAG-test
deleted file mode 100755 (executable)
index 248f128..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_TCPLAG.c ] && echo TCPLAG
diff --git a/extensions/.XOR-test b/extensions/.XOR-test
deleted file mode 100755 (executable)
index 92707da..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_XOR.c ] && echo XOR
diff --git a/extensions/.account-test b/extensions/.account-test
deleted file mode 100755 (executable)
index 68aeb16..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if account match patch is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_account.h ] && echo account
diff --git a/extensions/.childlevel-test b/extensions/.childlevel-test
deleted file mode 100755 (executable)
index 9f3b965..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_childlevel.h ] && echo childlevel
index 350140f..61355d0 100755 (executable)
@@ -1,2 +1,2 @@
 #! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_connbytes.c ] && echo connbytes
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_connbytes.h ] && echo connbytes
diff --git a/extensions/.connrate-test b/extensions/.connrate-test
deleted file mode 100755 (executable)
index d110c15..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_connrate.h ] && echo connrate
diff --git a/extensions/.dstlimit-test b/extensions/.dstlimit-test
deleted file mode 100755 (executable)
index b7c8ef9..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_dstlimit.c ] && echo dstlimit
index ff63ca4..7ded945 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_esp.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_esp.h ] && echo esp
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_esp.h ] && echo esp
diff --git a/extensions/.fuzzy-test b/extensions/.fuzzy-test
deleted file mode 100755 (executable)
index f6575a9..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_fuzzy.h ] && echo fuzzy 
diff --git a/extensions/.fuzzy-test6 b/extensions/.fuzzy-test6
deleted file mode 100755 (executable)
index 034263e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_fuzzy.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_fuzzy.h ] && echo fuzzy
diff --git a/extensions/.hashlimit-test6 b/extensions/.hashlimit-test6
new file mode 100755 (executable)
index 0000000..9a2a465
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter/xt_hashlimit.h ] && echo hashlimit
+
diff --git a/extensions/.mh-test6 b/extensions/.mh-test6
new file mode 100755 (executable)
index 0000000..1142096
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_mh.h ] && echo mh
diff --git a/extensions/.mport-test b/extensions/.mport-test
deleted file mode 100755 (executable)
index 411a083..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_mport.c ] && echo mport
diff --git a/extensions/.nth-test b/extensions/.nth-test
deleted file mode 100755 (executable)
index 536da95..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if nth is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_nth.h ] && echo nth
diff --git a/extensions/.nth-test6 b/extensions/.nth-test6
deleted file mode 100755 (executable)
index 7dbe091..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if nth is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_nth.h ] && echo nth
diff --git a/extensions/.osf-test b/extensions/.osf-test
deleted file mode 100755 (executable)
index bc3ad8f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if osf is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_osf.h ] && echo osf
diff --git a/extensions/.psd-test b/extensions/.psd-test
deleted file mode 100755 (executable)
index 9d05088..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if psd is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_psd.h ] && echo psd
index 761bf14..b21058c 100755 (executable)
@@ -1,3 +1,3 @@
 #!/bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_quota.h ] && echo quota
+[ -f $KERNEL_DIR/include/linux/netfilter/xt_quota.h ] && echo quota
 
diff --git a/extensions/.random-test b/extensions/.random-test
deleted file mode 100755 (executable)
index 7626722..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if random is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_random.h ] && echo random
diff --git a/extensions/.random-test6 b/extensions/.random-test6
deleted file mode 100755 (executable)
index 25a431f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if random is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_random.h ] && echo random
diff --git a/extensions/.record-rpc-test b/extensions/.record-rpc-test
deleted file mode 100755 (executable)
index 4ff9fe2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /bin/sh
-# True if record rpc is applied.
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_record_rpc.c ] && echo record_rpc
diff --git a/extensions/.sctp-test6 b/extensions/.sctp-test6
new file mode 100755 (executable)
index 0000000..3cfc7b8
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter/xt_sctp.h ] && echo sctp
+
diff --git a/extensions/.statistic-test b/extensions/.statistic-test
new file mode 100755 (executable)
index 0000000..843cb41
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/net/netfilter/xt_statistic.c -a -f $KERNEL_DIR/include/linux/netfilter/xt_statistic.h ] && echo statistic
diff --git a/extensions/.time-test b/extensions/.time-test
deleted file mode 100755 (executable)
index 7f0390e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if time is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_time.h ] && echo time
index 7164e1d..64ca7a8 100644 (file)
@@ -5,8 +5,13 @@
 # header files are present in the include/linux directory of this iptables
 # package (HW)
 #
-PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac mark multiport owner physdev pkttype policy realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
-PF6_EXT_SLIB:=connmark eui64 hl icmpv6 length limit mac mark multiport owner physdev policy standard state tcp udp CONNMARK HL LOG NFQUEUE MARK TRACE
+PF_EXT_SLIB:=ah addrtype comment connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac mark multiport owner physdev pkttype policy realm sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT TCPMSS TOS TTL ULOG
+PF6_EXT_SLIB:=connmark eui64 hl icmp6 length limit mac mark multiport owner physdev policy standard state tcp udp CONNMARK HL LOG NFQUEUE MARK TCPMSS
+
+ifeq ($(DO_SELINUX), 1)
+PF_EXT_SE_SLIB:=SECMARK CONNSECMARK
+PF6_EXT_SE_SLIB:=SECMARK CONNSECMARK
+endif
 
 # Optionals
 PF_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
@@ -43,26 +48,34 @@ OPTIONALS+=$(patsubst %,IPv6:%,$(PF6_EXT_SLIB_OPTS))
 
 ifndef NO_SHARED_LIBS
 SHARED_LIBS+=$(foreach T,$(PF_EXT_SLIB),extensions/libipt_$(T).so)
+SHARED_SE_LIBS+=$(foreach T,$(PF_EXT_SE_SLIB),extensions/libipt_$(T).so)
 EXTRA_INSTALLS+=$(foreach T, $(PF_EXT_SLIB), $(DESTDIR)$(LIBDIR)/iptables/libipt_$(T).so)
+EXTRA_INSTALLS+=$(foreach T, $(PF_EXT_SE_SLIB), $(DESTDIR)$(LIBDIR)/iptables/libipt_$(T).so)
 
 ifeq ($(DO_IPV6), 1)
 SHARED_LIBS+=$(foreach T,$(PF6_EXT_SLIB),extensions/libip6t_$(T).so)
+SHARED_SE_LIBS+=$(foreach T,$(PF6_EXT_SE_SLIB),extensions/libip6t_$(T).so)
 EXTRA_INSTALLS+=$(foreach T, $(PF6_EXT_SLIB), $(DESTDIR)$(LIBDIR)/iptables/libip6t_$(T).so)
+EXTRA_INSTALLS+=$(foreach T, $(PF6_EXT_SE_SLIB), $(DESTDIR)$(LIBDIR)/iptables/libip6t_$(T).so)
 endif
 else   # NO_SHARED_LIBS
 EXT_OBJS+=$(foreach T,$(PF_EXT_SLIB),extensions/libipt_$(T).o)
+EXT_OBJS+=$(foreach T,$(PF_EXT_SE_SLIB),extensions/libipt_$(T).o)
 EXT_FUNC+=$(foreach T,$(PF_EXT_SLIB),ipt_$(T))
+EXT_FUNC+=$(foreach T,$(PF_EXT_SE_SLIB),ipt_$(T))
 EXT_OBJS+= extensions/initext.o
 ifeq ($(DO_IPV6), 1)
 EXT6_OBJS+=$(foreach T,$(PF6_EXT_SLIB),extensions/libip6t_$(T).o)
+EXT6_OBJS+=$(foreach T,$(PF6_EXT_SE_SLIB),extensions/libip6t_$(T).o)
 EXT6_FUNC+=$(foreach T,$(PF6_EXT_SLIB),ip6t_$(T))
+EXT6_FUNC+=$(foreach T,$(PF6_EXT_SE_SLIB),ip6t_$(T))
 EXT6_OBJS+= extensions/initext6.o
 endif  # DO_IPV6
 endif  # NO_SHARED_LIBS
 
 ifndef TOPLEVEL_INCLUDED
 local:
-       cd .. && $(MAKE) $(SHARED_LIBS)
+       cd .. && $(MAKE) $(SHARED_LIBS) $(SHARED_SE_LIBS)
 endif
 
 ifdef NO_SHARED_LIBS
diff --git a/extensions/libip6t_CONNSECMARK.c b/extensions/libip6t_CONNSECMARK.c
new file mode 100644 (file)
index 0000000..b11ed07
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Shared library add-on to ip6tables to add CONNSECMARK target support.
+ *
+ * Based on the MARK and CONNMARK targets.
+ *
+ * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+
+#define PFX "CONNSECMARK target: "
+
+static void help(void)
+{
+       printf(
+"CONNSECMARK target v%s options:\n"
+"  --save                   Copy security mark from packet to conntrack\n"
+"  --restore                Copy security mark from connection to packet\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "save", 0, 0, '1' },
+       { "restore", 0, 0, '2' },
+       { 0 }
+};
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                 const struct ip6t_entry *entry, struct ip6t_entry_target **target)
+{
+       struct xt_connsecmark_target_info *info =
+               (struct xt_connsecmark_target_info*)(*target)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & CONNSECMARK_SAVE)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Can't specify --save twice");
+               info->mode = CONNSECMARK_SAVE;
+               *flags |= CONNSECMARK_SAVE;
+               break;
+
+       case '2':
+               if (*flags & CONNSECMARK_RESTORE)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Can't specify --restore twice");
+               info->mode = CONNSECMARK_RESTORE;
+               *flags |= CONNSECMARK_RESTORE;
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM, PFX "parameter required");
+
+       if (flags == (CONNSECMARK_SAVE|CONNSECMARK_RESTORE))
+               exit_error(PARAMETER_PROBLEM, PFX "only one flag of --save "
+                          "or --restore is allowed");
+}
+
+static void print_connsecmark(struct xt_connsecmark_target_info *info)
+{
+       switch (info->mode) {
+       case CONNSECMARK_SAVE:
+               printf("save ");
+               break;
+               
+       case CONNSECMARK_RESTORE:
+               printf("restore ");
+               break;
+               
+       default:
+               exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+       }
+}
+
+static void print(const struct ip6t_ip6 *ip,
+                 const struct ip6t_entry_target *target, int numeric)
+{
+       struct xt_connsecmark_target_info *info =
+               (struct xt_connsecmark_target_info*)(target)->data;
+
+       printf("CONNSECMARK ");
+       print_connsecmark(info);
+}
+
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+       struct xt_connsecmark_target_info *info =
+               (struct xt_connsecmark_target_info*)target->data;
+
+       printf("--");
+       print_connsecmark(info);
+}
+
+static struct ip6tables_target connsecmark = {
+       .name           = "CONNSECMARK",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct xt_connsecmark_target_info)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct xt_connsecmark_target_info)),
+       .parse          = &parse,
+       .help           = &help,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target6(&connsecmark);
+}
diff --git a/extensions/libip6t_CONNSECMARK.man b/extensions/libip6t_CONNSECMARK.man
new file mode 100644 (file)
index 0000000..b94353a
--- /dev/null
@@ -0,0 +1,15 @@
+This module copies security markings from packets to connections
+(if unlabeled), and from connections back to packets (also only
+if unlabeled).  Typically used in conjunction with SECMARK, it is
+only valid in the
+.B mangle
+table.
+.TP
+.B --save
+If the packet has a security marking, copy it to the connection
+if the connection is not marked.
+.TP
+.B --restore
+If the packet does not have a security marking, and the connection
+does, copy the security marking from the connection to the packet.
+
index a9c8965..5043b44 100644 (file)
@@ -143,6 +143,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                                   "Maximum prefix length %u for --log-prefix",
                                   (unsigned int)sizeof(loginfo->prefix) - 1);
 
+               if (strlen(optarg) == 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "No prefix specified for --log-prefix");
+
                if (strlen(optarg) != strlen(strtok(optarg, "\n")))
                        exit_error(PARAMETER_PROBLEM,
                                   "Newlines not allowed in --log-prefix");
diff --git a/extensions/libip6t_NFLOG.c b/extensions/libip6t_NFLOG.c
new file mode 100644 (file)
index 0000000..2c0cd3d
--- /dev/null
@@ -0,0 +1,161 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <ip6tables.h>
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/xt_NFLOG.h>
+
+enum {
+       NFLOG_GROUP     = 0x1,
+       NFLOG_PREFIX    = 0x2,
+       NFLOG_RANGE     = 0x4,
+       NFLOG_THRESHOLD = 0x8,
+};
+
+static struct option opts[] = {
+       { "nflog-group",     1, 0, NFLOG_GROUP },
+       { "nflog-prefix",    1, 0, NFLOG_PREFIX },
+       { "nflog-range",     1, 0, NFLOG_RANGE },
+       { "nflog-threshold", 1, 0, NFLOG_THRESHOLD },
+};
+
+static void help(void)
+{
+       printf("NFLOG v%s options:\n"
+              " --nflog-group NUM              NETLINK group used for logging\n"
+              " --nflog-range NUM              Number of byte to copy\n"
+              " --nflog-threshold NUM          Message threshold of in-kernel queue\n"
+              " --nflog-prefix STRING          Prefix string for log messages\n\n",
+              IPTABLES_VERSION);
+}
+
+static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+       struct xt_nflog_info *info = (struct xt_nflog_info *)t->data;
+
+       info->group     = 0;
+       info->threshold = XT_NFLOG_DEFAULT_THRESHOLD;
+}
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                const struct ip6t_entry *entry,
+                struct xt_entry_target **target)
+{
+       struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data;
+       int n;
+
+       switch (c) {
+       case NFLOG_GROUP:
+               if (*flags & NFLOG_GROUP)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-group twice");
+               if (check_inverse(optarg, &invert, NULL, 0))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Unexpected `!' after --nflog-group");
+
+               n = atoi(optarg);
+               if (n < 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "--nflog-group can not be negative");
+               info->group = n;
+               break;
+       case NFLOG_PREFIX:
+               if (*flags & NFLOG_PREFIX)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-prefix twice");
+               if (check_inverse(optarg, &invert, NULL, 0))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Unexpected `!' after --nflog-prefix");
+
+               n = strlen(optarg);
+               if (n == 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "No prefix specified for --nflog-prefix");
+               if (n >= sizeof(info->prefix))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "--nflog-prefix too long, max %Zu characters",
+                                  sizeof(info->prefix) - 1);
+               if (n != strlen(strtok(optarg, "\n")))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Newlines are not allowed in --nflog-prefix");
+               strcpy(info->prefix, optarg);
+               break;
+       case NFLOG_RANGE:
+               if (*flags & NFLOG_RANGE)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-range twice");
+               n = atoi(optarg);
+               if (n < 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid --nflog-range, must be >= 0");
+               info->len = n;
+               break;
+       case NFLOG_THRESHOLD:
+               if (*flags & NFLOG_THRESHOLD)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-threshold twice");
+               n = atoi(optarg);
+               if (n < 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid --nflog-threshold, must be >= 1");
+               info->threshold = n;
+               break;
+       default:
+               return 0;
+       }
+       *flags |= c;
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       return;
+}
+
+static void nflog_print(const struct xt_nflog_info *info, char *prefix)
+{
+       if (info->prefix[0] != '\0')
+               printf("%snflog-prefix \"%s\" ", prefix, info->prefix);
+       if (info->group)
+               printf("%snflog-group %u ", prefix, info->group);
+       if (info->len)
+               printf("%snflog-range %u ", prefix, info->len);
+       if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
+               printf("%snflog-threshold %u ", prefix, info->threshold);
+}
+
+static void print(const struct ip6t_ip6 *ip, const struct xt_entry_target *target,
+                 int numeric)
+{
+       const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
+
+       nflog_print(info, "");
+}
+
+static void save(const struct ip6t_ip6 *ip, const struct xt_entry_target *target)
+{
+       const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
+
+       nflog_print(info, "--");
+}
+
+static struct ip6tables_target nflog = {
+       .name           = "NFLOG",
+       .version        = IPTABLES_VERSION,
+       .size           = XT_ALIGN(sizeof(struct xt_nflog_info)),
+       .userspacesize  = XT_ALIGN(sizeof(struct xt_nflog_info)),
+       .help           = help,
+       .init           = init,
+       .parse          = parse,
+       .final_check    = final_check,
+       .print          = print,
+       .save           = save,
+       .extra_opts     = opts,
+};
+
+void _init(void)
+{
+       register_target6(&nflog);
+}
diff --git a/extensions/libip6t_ROUTE.c b/extensions/libip6t_ROUTE.c
deleted file mode 100644 (file)
index ad83a1d..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/* Shared library add-on to iptables to add ROUTE v6 target support.
- * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
- * v 1.1 2004/11/23
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
-
-/* compile IP6T_ROUTE_TEE support even if kernel headers are unpatched */
-#ifndef IP6T_ROUTE_TEE
-#define IP6T_ROUTE_TEE         0x02
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"ROUTE target v%s options:\n"
-"    --oif   \tifname \t\tRoute the packet through `ifname' network interface\n"
-"    --gw    \tip     \t\tRoute the packet via this gateway\n"
-"    --continue\t     \t\tRoute packet and continue traversing the\n"
-"            \t       \t\trules. Not valid with --iif or --tee.\n"
-"    --tee\t  \t\tDuplicate packet, route the duplicate,\n"
-"            \t       \t\tcontinue traversing with original packet.\n"
-"            \t       \t\tNot valid with --iif or --continue.\n"
-"\n",
-"1.1");
-}
-
-static struct option opts[] = {
-       { "oif", 1, 0, '1' },
-       { "iif", 1, 0, '2' },
-       { "gw", 1, 0, '3' },
-       { "continue", 0, 0, '4' },
-       { "tee", 0, 0, '5' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-       struct ip6t_route_target_info *route_info = 
-               (struct ip6t_route_target_info*)t->data;
-
-       route_info->oif[0] = '\0';
-       route_info->iif[0] = '\0';
-       route_info->gw[0] = 0;
-       route_info->gw[1] = 0;
-       route_info->gw[2] = 0;
-       route_info->gw[3] = 0;
-       route_info->flags = 0;
-}
-
-
-#define IP6T_ROUTE_OPT_OIF      0x01
-#define IP6T_ROUTE_OPT_IIF      0x02
-#define IP6T_ROUTE_OPT_GW       0x04
-#define IP6T_ROUTE_OPT_CONTINUE 0x08
-#define IP6T_ROUTE_OPT_TEE      0x10
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ip6t_entry *entry,
-      struct ip6t_entry_target **target)
-{
-       struct ip6t_route_target_info *route_info = 
-               (struct ip6t_route_target_info*)(*target)->data;
-
-       switch (c) {
-       case '1':
-               if (*flags & IP6T_ROUTE_OPT_OIF)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --oif twice");
-
-               if (check_inverse(optarg, &invert, NULL, 0))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unexpected `!' after --oif");
-
-               if (strlen(optarg) > sizeof(route_info->oif) - 1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Maximum interface name length %u",
-                                  sizeof(route_info->oif) - 1);
-
-               strcpy(route_info->oif, optarg);
-               *flags |= IP6T_ROUTE_OPT_OIF;
-               break;
-
-       case '2':
-               exit_error(PARAMETER_PROBLEM,
-                          "--iif option not implemented");
-               break;
-
-       case '3':
-               if (*flags & IP6T_ROUTE_OPT_GW)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --gw twice");
-
-               if (check_inverse(optarg, &invert, NULL, 0))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unexpected `!' after --gw");
-
-               if (!inet_pton(AF_INET6, optarg, (struct in6_addr*)&route_info->gw)) {
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid IPv6 address %s",
-                                  optarg);
-               }
-
-               *flags |= IP6T_ROUTE_OPT_GW;
-               break;
-
-       case '4':
-               if (*flags & IP6T_ROUTE_OPT_CONTINUE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --continue twice");
-               if (*flags & IP6T_ROUTE_OPT_TEE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --continue AND --tee");
-
-               route_info->flags |= IP6T_ROUTE_CONTINUE;
-               *flags |= IP6T_ROUTE_OPT_CONTINUE;
-
-               break;
-
-       case '5':
-               if (*flags & IP6T_ROUTE_OPT_TEE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --tee twice");
-               if (*flags & IP6T_ROUTE_OPT_CONTINUE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --tee AND --continue");
-
-               route_info->flags |= IP6T_ROUTE_TEE;
-               *flags |= IP6T_ROUTE_OPT_TEE;
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-
-static void
-final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "ROUTE target: oif or gw option required");
-}
-
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
-      const struct ip6t_entry_target *target,
-      int numeric)
-{
-       const struct ip6t_route_target_info *route_info
-               = (const struct ip6t_route_target_info *)target->data;
-
-       printf("ROUTE ");
-
-       if (route_info->oif[0])
-               printf("oif:%s ", route_info->oif);
-
-       if (route_info->gw[0] 
-           || route_info->gw[1] 
-           || route_info->gw[2] 
-           || route_info->gw[3]) {
-               char address[INET6_ADDRSTRLEN];
-               printf("gw:%s ", inet_ntop(AF_INET6, route_info->gw, address, INET6_ADDRSTRLEN));
-       }
-
-       if (route_info->flags & IP6T_ROUTE_CONTINUE)
-               printf("continue");
-
-       if (route_info->flags & IP6T_ROUTE_TEE)
-               printf("tee");
-
-}
-
-
-static void save(const struct ip6t_ip6 *ip, 
-                const struct ip6t_entry_target *target)
-{
-       const struct ip6t_route_target_info *route_info
-               = (const struct ip6t_route_target_info *)target->data;
-
-       if (route_info->oif[0])
-               printf("--oif %s ", route_info->oif);
-
-       if (route_info->gw[0] 
-           || route_info->gw[1] 
-           || route_info->gw[2] 
-           || route_info->gw[3]) {
-               char address[INET6_ADDRSTRLEN];
-               printf("--gw %s ", inet_ntop(AF_INET6, route_info->gw, address, INET6_ADDRSTRLEN));
-       }
-
-       if (route_info->flags & IP6T_ROUTE_CONTINUE)
-               printf("--continue ");
-
-       if (route_info->flags & IP6T_ROUTE_TEE)
-               printf("--tee ");
-}
-
-
-static struct ip6tables_target route = { 
-       .name           = "ROUTE",
-       .version        = IPTABLES_VERSION,
-       .size           = IP6T_ALIGN(sizeof(struct ip6t_route_target_info)),
-       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_route_target_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts,
-};
-
-void _init(void)
-{
-       register_target6(&route);
-}
diff --git a/extensions/libip6t_ROUTE.man b/extensions/libip6t_ROUTE.man
deleted file mode 100644 (file)
index e3ad12b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-This is used to explicitly override the core network stack's routing decision.
-.B mangle
-table.
-.TP
-.BI "--oif " "ifname"
-Route the packet through `ifname' network interface
-.TP
-.BI "--gw " "IPv6_address"
-Route the packet via this gateway
-.TP
-.BI "--continue "
-Behave like a non-terminating target and continue traversing the rules. Not valid in combination with `--tee'
-.TP
-.BI "--tee "
-Make a copy of the packet, and route that copy to the given destination. For the original, uncopied packet, behave like a non-terminating target and continue traversing the rules.  Not valid in combination with `--continue'
diff --git a/extensions/libip6t_SECMARK.c b/extensions/libip6t_SECMARK.c
new file mode 100644 (file)
index 0000000..8fbae05
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Shared library add-on to iptables to add SECMARK target support.
+ *
+ * Based on the MARK target.
+ *
+ * IPv6 version.
+ *
+ * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+#define PFX "SECMARK target: "
+
+static void help(void)
+{
+       printf(
+"SECMARK target v%s options:\n"
+"  --selctx value                     Set the SELinux security context\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "selctx", 1, 0, '1' },
+       { 0 }
+};
+
+/* Initialize the target. */
+static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{ }
+
+/*
+ * Function which parses command options; returns true if it
+ * ate an option.
+ */
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                 const struct ip6t_entry *entry, struct ip6t_entry_target **target)
+{
+       struct xt_secmark_target_info *info =
+               (struct xt_secmark_target_info*)(*target)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & SECMARK_MODE_SEL)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Can't specify --selctx twice");
+               info->mode = SECMARK_MODE_SEL;
+
+               if (strlen(optarg) > SECMARK_SELCTX_MAX-1)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Maximum length %u exceeded by --selctx"
+                                  " parameter (%zu)",
+                                  SECMARK_SELCTX_MAX-1, strlen(optarg));
+
+               strcpy(info->u.sel.selctx, optarg);
+               *flags |= SECMARK_MODE_SEL;
+               break;
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM, PFX "parameter required");
+}
+
+static void print_secmark(struct xt_secmark_target_info *info)
+{
+       switch (info->mode) {
+       case SECMARK_MODE_SEL:
+               printf("selctx %s ", info->u.sel.selctx);\
+               break;
+       
+       default:
+               exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+       }
+}
+
+static void print(const struct ip6t_ip6 *ip,
+                 const struct ip6t_entry_target *target, int numeric)
+{
+       struct xt_secmark_target_info *info =
+               (struct xt_secmark_target_info*)(target)->data;
+
+       printf("SECMARK ");
+       print_secmark(info);
+}
+
+/* Saves the target info in parsable form to stdout. */
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+       struct xt_secmark_target_info *info =
+               (struct xt_secmark_target_info*)target->data;
+
+       printf("--");
+       print_secmark(info);
+}
+
+static struct ip6tables_target secmark = {
+       .name           = "SECMARK",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct xt_secmark_target_info)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct xt_secmark_target_info)),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target6(&secmark);
+}
diff --git a/extensions/libip6t_SECMARK.man b/extensions/libip6t_SECMARK.man
new file mode 100644 (file)
index 0000000..f892de9
--- /dev/null
@@ -0,0 +1,7 @@
+This is used to set the security mark value associated with the
+packet for use by security subsystems such as SELinux.  It is only
+valid in the
+.B mangle
+table.
+.TP
+.BI "--selctx " "security_context"
diff --git a/extensions/libip6t_TCPMSS.c b/extensions/libip6t_TCPMSS.c
new file mode 100644 (file)
index 0000000..7fcccd5
--- /dev/null
@@ -0,0 +1,134 @@
+/* Shared library add-on to iptables to add TCPMSS target support.
+ *
+ * Copyright (c) 2000 Marc Boucher
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_TCPMSS.h>
+
+struct mssinfo {
+       struct ip6t_entry_target t;
+       struct ip6t_tcpmss_info mss;
+};
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+       printf(
+"TCPMSS target v%s mutually-exclusive options:\n"
+"  --set-mss value               explicitly set MSS option to specified value\n"
+"  --clamp-mss-to-pmtu           automatically clamp MSS value to (path_MTU - 60)\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "set-mss", 1, 0, '1' },
+       { "clamp-mss-to-pmtu", 0, 0, '2' },
+       { 0 }
+};
+
+/* Initialize the target. */
+static void
+init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      struct ip6t_entry_target **target)
+{
+       struct ip6t_tcpmss_info *mssinfo
+               = (struct ip6t_tcpmss_info *)(*target)->data;
+
+       switch (c) {
+               unsigned int mssval;
+
+       case '1':
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "TCPMSS target: Only one option may be specified");
+               if (string_to_number(optarg, 0, 65535 - 60, &mssval) == -1)
+                       exit_error(PARAMETER_PROBLEM, "Bad TCPMSS value `%s'", optarg);
+
+               mssinfo->mss = mssval;
+               *flags = 1;
+               break;
+
+       case '2':
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "TCPMSS target: Only one option may be specified");
+               mssinfo->mss = IP6T_TCPMSS_CLAMP_PMTU;
+               *flags = 1;
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM,
+                          "TCPMSS target: At least one parameter is required");
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ip6t_ip6 *ip6,
+      const struct ip6t_entry_target *target,
+      int numeric)
+{
+       const struct ip6t_tcpmss_info *mssinfo =
+               (const struct ip6t_tcpmss_info *)target->data;
+       if(mssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU)
+               printf("TCPMSS clamp to PMTU ");
+       else
+               printf("TCPMSS set %u ", mssinfo->mss);
+}
+
+/* Saves the union ip6t_targinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+       const struct ip6t_tcpmss_info *mssinfo =
+               (const struct ip6t_tcpmss_info *)target->data;
+
+       if(mssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU)
+               printf("--clamp-mss-to-pmtu ");
+       else
+               printf("--set-mss %u ", mssinfo->mss);
+}
+
+static struct ip6tables_target mss = {
+       .next           = NULL,
+       .name           = "TCPMSS",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct ip6t_tcpmss_info)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_tcpmss_info)),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target6(&mss);
+}
diff --git a/extensions/libip6t_TCPMSS.man b/extensions/libip6t_TCPMSS.man
new file mode 100644 (file)
index 0000000..b4c357e
--- /dev/null
@@ -0,0 +1,42 @@
+This target allows to alter the MSS value of TCP SYN packets, to control
+the maximum size for that connection (usually limiting it to your
+outgoing interface's MTU minus 60).  Of course, it can only be used
+in conjunction with
+.BR "-p tcp" .
+It is only valid in the
+.BR mangle
+table.
+.br
+This target is used to overcome criminally braindead ISPs or servers
+which block ICMPv6 Packet Too Big packets or are unable to send them.
+The symptoms of this problem are that everything works fine from your 
+Linux firewall/router, but machines behind it can never exchange large
+packets:
+.PD 0
+.RS 0.1i
+.TP 0.3i
+1)
+Web browsers connect, then hang with no data received.
+.TP
+2)
+Small mail works fine, but large emails hang.
+.TP
+3)
+ssh works fine, but scp hangs after initial handshaking.
+.RE
+.PD
+Workaround: activate this option and add a rule to your firewall
+configuration like:
+.nf
+ ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \\
+             -j TCPMSS --clamp-mss-to-pmtu
+.fi
+.TP
+.BI "--set-mss " "value"
+Explicitly set MSS option to specified value.
+.TP
+.B "--clamp-mss-to-pmtu"
+Automatically clamp MSS value to (path_MTU - 60).
+.TP
+These options are mutually exclusive.
+
diff --git a/extensions/libip6t_TRACE.c b/extensions/libip6t_TRACE.c
deleted file mode 100644 (file)
index 00d8591..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Shared library add-on to iptables to add TRACE target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"TRACE target v%s takes no options\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ip6t_entry *entry,
-      struct ip6t_entry_target **target)
-{
-       return 0;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-static
-struct ip6tables_target trace
-= {    .next = NULL,
-       .name = "TRACE",
-       .version = IPTABLES_VERSION,
-       .size = IP6T_ALIGN(0),
-       .userspacesize = IP6T_ALIGN(0),
-       .help = &help,
-       .init = &init,
-       .parse = &parse,
-       .final_check = &final_check,
-       .print = NULL, /* print */
-       .save = NULL, /* save */
-       .extra_opts = opts
-};
-
-void _init(void)
-{
-       register_target6(&trace);
-}
diff --git a/extensions/libip6t_TRACE.man b/extensions/libip6t_TRACE.man
deleted file mode 100644 (file)
index 549ab33..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-This target has no options.  It just turns on 
-.B packet tracing
-for all packets that match this rule.
index 29e865d..886e09b 100644 (file)
@@ -61,6 +61,9 @@ parse_esp_spis(const char *spistring, u_int32_t *spis)
 
                spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
                spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
+               if (spis[0] > spis[1])
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid ESP spi range: %s", spistring);
        }
        free(buffer);
 }
index d01cb4f..cd80b98 100644 (file)
@@ -1,5 +1,5 @@
 This module matches the EUI-64 part of a stateless autoconfigured IPv6 address.
-It compares the EUI-64 derived from the source MAC address in Ehternet frame
+It compares the EUI-64 derived from the source MAC address in Ethernet frame
 with the lower 64 bits of the IPv6 source address. But "Universal/Local"
 bit is not compared. This module doesn't match other link layer frame, and
 is only valid in the
diff --git a/extensions/libip6t_fuzzy.c b/extensions/libip6t_fuzzy.c
deleted file mode 100644 (file)
index 749ddc8..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-   Shared library add-on to iptables to add match support for the fuzzy match.
-
-   This file is distributed under the terms of the GNU General Public
-   License (GPL). Copies of the GPL can be obtained from:
-   ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-2002-08-07 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
-2003-04-08 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
-2003-06-09 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Bug corrections in
-the save function , thanks to information given by Jean-Francois Patenaude.
-
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
-
-
-static void
-help(void)
-{
-       printf(
-"fuzzy v%s options:\n"
-"                      --lower-limit number (in packets per second)\n"
-"                      --upper-limit number\n"
-,IPTABLES_VERSION);
-};
-
-static struct option opts[] = {
-       { .name = "lower-limit", .has_arg = 1, .flag = 0, .val = '1' },
-       { .name = "upper-limit", .has_arg = 1, .flag = 0, .val = '2' },
-       { .name = 0 }
-};
-
-/* Initialize data structures */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
-       struct ip6t_fuzzy_info *presentinfo = (struct ip6t_fuzzy_info *)(m)->data;
-       /*
-        * Default rates ( I'll improve this very soon with something based
-        * on real statistics of the running machine ) .
-       */
-
-       presentinfo->minimum_rate = 1000;
-       presentinfo->maximum_rate = 2000;
-}
-
-#define IP6T_FUZZY_OPT_MINIMUM 0x01
-#define IP6T_FUZZY_OPT_MAXIMUM 0x02
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ip6t_entry *entry,
-      unsigned int *nfcache,
-      struct ip6t_entry_match **match)
-{
-       struct ip6t_fuzzy_info *fuzzyinfo =
-               (struct ip6t_fuzzy_info *)(*match)->data;
-
-       u_int32_t num;
-
-       switch (c) {
-
-       case '1':
-
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,"Can't specify ! --lower-limit");
-
-       if (*flags & IP6T_FUZZY_OPT_MINIMUM)
-                     exit_error(PARAMETER_PROBLEM,"Can't specify --lower-limit twice");
-
-       if (string_to_number(optarg,1,MAXFUZZYRATE,&num) == -1 || num < 1)
-                       exit_error(PARAMETER_PROBLEM,"BAD --lower-limit");
-
-               fuzzyinfo->minimum_rate = num ;
-
-               *flags |= IP6T_FUZZY_OPT_MINIMUM;
-
-               break;
-
-       case '2':
-
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,"Can't specify ! --upper-limit");
-
-       if (*flags & IP6T_FUZZY_OPT_MAXIMUM)
-          exit_error(PARAMETER_PROBLEM,"Can't specify --upper-limit twice");
-
-       if (string_to_number(optarg,1,MAXFUZZYRATE,&num) == -1 || num < 1)
-               exit_error(PARAMETER_PROBLEM,"BAD --upper-limit");
-
-               fuzzyinfo->maximum_rate = num;
-
-               *flags |= IP6T_FUZZY_OPT_MAXIMUM;
-
-               break ;
-
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-static void final_check(unsigned int flags)
-{
-}
-
-static void
-print(const struct ip6t_ip6 *ipv6,
-      const struct ip6t_entry_match *match,
-      int numeric)
-{
-       const struct ip6t_fuzzy_info *fuzzyinfo
-               = (const struct ip6t_fuzzy_info *)match->data;
-
-       printf(" fuzzy: lower limit = %u pps - upper limit = %u pps ",
-               fuzzyinfo->minimum_rate, fuzzyinfo->maximum_rate);
-}
-
-/* Saves the union ip6t_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ipv6, const struct ip6t_entry_match *match)
-{
-       const struct ip6t_fuzzy_info *fuzzyinfo
-               = (const struct ip6t_fuzzy_info *)match->data;
-
-       printf("--lower-limit %u --upper-limit %u ",
-               fuzzyinfo->minimum_rate, fuzzyinfo->maximum_rate);
-}
-
-struct ip6tables_match fuzzy_match = {
-       .name          = "fuzzy",
-       .version       = IPTABLES_VERSION,
-       .size          = IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)),
-       .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)),
-       .help          = &help,
-       .init          = &init,
-       .parse         = &parse,
-       .final_check   = &final_check,
-       .print         = &print,
-       .save          = &save,
-       .extra_opts    = opts
-};
-
-void _init(void)
-{
-       register_match6(&fuzzy_match);
-}
diff --git a/extensions/libip6t_fuzzy.man b/extensions/libip6t_fuzzy.man
deleted file mode 100644 (file)
index 397727a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-This module matches a rate limit based on a fuzzy logic controller [FLC]
-.TP
-.BI "--lower-limit " "number"
-Specifies the lower limit (in packets per second).
-.TP
-.BI "--upper-limit " "number"
-Specifies the upper limit (in packets per second).
diff --git a/extensions/libip6t_hashlimit.c b/extensions/libip6t_hashlimit.c
new file mode 100644 (file)
index 0000000..70d2ff3
--- /dev/null
@@ -0,0 +1,369 @@
+/* ip6tables match extension for limiting packets per destination
+ *
+ * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
+ *
+ * Development of this code was funded by Astaro AG, http://www.astaro.com/
+ *
+ * Based on ipt_limit.c by
+ * Jérôme de Vivie   <devivie@info.enserb.u-bordeaux.fr>
+ * Hervé Eychenne    <rv@wallfire.org>
+ * 
+ * Error corections by nmalykh@bilim.com (22.01.2005)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <stddef.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/xt_hashlimit.h>
+
+#define XT_HASHLIMIT_BURST     5
+
+/* miliseconds */
+#define XT_HASHLIMIT_GCINTERVAL        1000
+#define XT_HASHLIMIT_EXPIRE    10000
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+       printf(
+"hashlimit v%s options:\n"
+"--hashlimit <avg>             max average match rate\n"
+"                                [Packets per second unless followed by \n"
+"                                /sec /minute /hour /day postfixes]\n"
+"--hashlimit-mode <mode>               mode is a comma-separated list of\n"
+"                                      dstip,srcip,dstport,srcport\n"
+"--hashlimit-name <name>               name for /proc/net/ipt_hashlimit/\n"
+"[--hashlimit-burst <num>]     number to match in a burst, default %u\n"
+"[--hashlimit-htable-size <num>]       number of hashtable buckets\n"
+"[--hashlimit-htable-max <num>]        number of hashtable entries\n"
+"[--hashlimit-htable-gcinterval]       interval between garbage collection runs\n"
+"[--hashlimit-htable-expire]   after which time are idle entries expired?\n"
+"\n", IPTABLES_VERSION, XT_HASHLIMIT_BURST);
+}
+
+static struct option opts[] = {
+       { "hashlimit", 1, 0, '%' },
+       { "hashlimit-burst", 1, 0, '$' },
+       { "hashlimit-htable-size", 1, 0, '&' },
+       { "hashlimit-htable-max", 1, 0, '*' },
+       { "hashlimit-htable-gcinterval", 1, 0, '(' },
+       { "hashlimit-htable-expire", 1, 0, ')' },
+       { "hashlimit-mode", 1, 0, '_' },
+       { "hashlimit-name", 1, 0, '"' },
+       { 0 }
+};
+
+static
+int parse_rate(const char *rate, u_int32_t *val)
+{
+       const char *delim;
+       u_int32_t r;
+       u_int32_t mult = 1;  /* Seconds by default. */
+
+       delim = strchr(rate, '/');
+       if (delim) {
+               if (strlen(delim+1) == 0)
+                       return 0;
+
+               if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
+                       mult = 1;
+               else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
+                       mult = 60;
+               else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
+                       mult = 60*60;
+               else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
+                       mult = 24*60*60;
+               else
+                       return 0;
+       }
+       r = atoi(rate);
+       if (!r)
+               return 0;
+
+       /* This would get mapped to infinite (1/day is minimum they
+           can specify, so we're ok at that end). */
+       if (r / mult > XT_HASHLIMIT_SCALE)
+               exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
+
+       *val = XT_HASHLIMIT_SCALE * mult / r;
+       return 1;
+}
+
+/* Initialize the match. */
+static void
+init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+       struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data;
+
+       r->cfg.burst = XT_HASHLIMIT_BURST;
+       r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+       r->cfg.expire = XT_HASHLIMIT_EXPIRE;
+
+}
+
+
+/* Parse a 'mode' parameter into the required bitmask */
+static int parse_mode(struct xt_hashlimit_info *r, char *optarg)
+{
+       char *tok;
+       char *arg = strdup(optarg);
+
+       if (!arg)
+               return -1;
+
+       r->cfg.mode = 0;
+
+       for (tok = strtok(arg, ",|");
+            tok;
+            tok = strtok(NULL, ",|")) {
+               if (!strcmp(tok, "dstip"))
+                       r->cfg.mode |= XT_HASHLIMIT_HASH_DIP;
+               else if (!strcmp(tok, "srcip"))
+                       r->cfg.mode |= XT_HASHLIMIT_HASH_SIP;
+               else if (!strcmp(tok, "srcport"))
+                       r->cfg.mode |= XT_HASHLIMIT_HASH_SPT;
+               else if (!strcmp(tok, "dstport"))
+                       r->cfg.mode |= XT_HASHLIMIT_HASH_DPT;
+               else {
+                       free(arg);
+                       return -1;
+               }
+       }
+       free(arg);
+       return 0;
+}
+
+#define PARAM_LIMIT            0x00000001
+#define PARAM_BURST            0x00000002
+#define PARAM_MODE             0x00000004
+#define PARAM_NAME             0x00000008
+#define PARAM_SIZE             0x00000010
+#define PARAM_MAX              0x00000020
+#define PARAM_GCINTERVAL       0x00000040
+#define PARAM_EXPIRE           0x00000080
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+       struct xt_hashlimit_info *r = 
+                       (struct xt_hashlimit_info *)(*match)->data;
+       unsigned int num;
+
+       switch(c) {
+       case '%':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (!parse_rate(optarg, &r->cfg.avg))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "bad rate `%s'", optarg);
+               *flags |= PARAM_LIMIT;
+               break;
+
+       case '$':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (string_to_number(optarg, 0, 10000, &num) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "bad --hashlimit-burst `%s'", optarg);
+               r->cfg.burst = num;
+               *flags |= PARAM_BURST;
+               break;
+       case '&':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                               "bad --hashlimit-htable-size: `%s'", optarg);
+               r->cfg.size = num;
+               *flags |= PARAM_SIZE;
+               break;
+       case '*':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                               "bad --hashlimit-htable-max: `%s'", optarg);
+               r->cfg.max = num;
+               *flags |= PARAM_MAX;
+               break;
+       case '(':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                               "bad --hashlimit-htable-gcinterval: `%s'", 
+                               optarg);
+               /* FIXME: not HZ dependent!! */
+               r->cfg.gc_interval = num;
+               *flags |= PARAM_GCINTERVAL;
+               break;
+       case ')':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                               "bad --hashlimit-htable-expire: `%s'", optarg);
+               /* FIXME: not HZ dependent */
+               r->cfg.expire = num;
+               *flags |= PARAM_EXPIRE;
+               break;
+       case '_':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (parse_mode(r, optarg) < 0)
+                       exit_error(PARAMETER_PROBLEM, 
+                                  "bad --hashlimit-mode: `%s'\n", optarg);
+               *flags |= PARAM_MODE;
+               break;
+       case '"':
+               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
+               if (strlen(optarg) == 0)
+                       exit_error(PARAMETER_PROBLEM, "Zero-length name?");
+               strncpy(r->name, optarg, sizeof(r->name));
+               *flags |= PARAM_NAME;
+               break;
+       default:
+               return 0;
+       }
+
+       if (invert)
+               exit_error(PARAMETER_PROBLEM,
+                          "hashlimit does not support invert");
+
+       return 1;
+}
+
+/* Final check; nothing. */
+static void final_check(unsigned int flags)
+{
+       if (!(flags & PARAM_LIMIT))
+               exit_error(PARAMETER_PROBLEM,
+                               "You have to specify --hashlimit");
+       if (!(flags & PARAM_MODE))
+               exit_error(PARAMETER_PROBLEM,
+                               "You have to specify --hashlimit-mode");
+       if (!(flags & PARAM_NAME))
+               exit_error(PARAMETER_PROBLEM,
+                               "You have to specify --hashlimit-name");
+}
+
+static struct rates
+{
+       const char *name;
+       u_int32_t mult;
+} rates[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
+             { "hour", XT_HASHLIMIT_SCALE*60*60 },
+             { "min", XT_HASHLIMIT_SCALE*60 },
+             { "sec", XT_HASHLIMIT_SCALE } };
+
+static void print_rate(u_int32_t period)
+{
+       unsigned int i;
+
+       for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
+               if (period > rates[i].mult
+            || rates[i].mult/period < rates[i].mult%period)
+                       break;
+       }
+
+       printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
+}
+
+static void print_mode(const struct xt_hashlimit_info *r, char separator)
+{
+       int prevmode = 0;
+
+       if (r->cfg.mode & XT_HASHLIMIT_HASH_SIP) {
+               if (prevmode)
+                       putchar(separator);
+               fputs("srcip", stdout);
+               prevmode = 1;
+       }
+       if (r->cfg.mode & XT_HASHLIMIT_HASH_SPT) {
+               if (prevmode)
+                       putchar(separator);
+               fputs("srcport", stdout);
+               prevmode = 1;
+       }
+       if (r->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
+               if (prevmode)
+                       putchar(separator);
+               fputs("dstip", stdout);
+               prevmode = 1;
+       }
+       if (r->cfg.mode & XT_HASHLIMIT_HASH_DPT) {
+               if (prevmode)
+                       putchar(separator);
+               fputs("dstport", stdout);
+       }
+       putchar(' ');
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match,
+      int numeric)
+{
+       struct xt_hashlimit_info *r = 
+               (struct xt_hashlimit_info *)match->data;
+       fputs("limit: avg ", stdout); print_rate(r->cfg.avg);
+       printf("burst %u ", r->cfg.burst);
+       fputs("mode ", stdout);
+       print_mode(r, '-');
+       if (r->cfg.size)
+               printf("htable-size %u ", r->cfg.size);
+       if (r->cfg.max)
+               printf("htable-max %u ", r->cfg.max);
+       if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+               printf("htable-gcinterval %u ", r->cfg.gc_interval);
+       if (r->cfg.expire != XT_HASHLIMIT_EXPIRE)
+               printf("htable-expire %u ", r->cfg.expire);
+}
+
+/* FIXME: Make minimalist: only print rate if not default --RR */
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+       struct xt_hashlimit_info *r = 
+               (struct xt_hashlimit_info *)match->data;
+
+       fputs("--hashlimit ", stdout); print_rate(r->cfg.avg);
+       if (r->cfg.burst != XT_HASHLIMIT_BURST)
+               printf("--hashlimit-burst %u ", r->cfg.burst);
+
+       fputs("--hashlimit-mode ", stdout);
+       print_mode(r, ',');
+       
+       printf("--hashlimit-name %s ", r->name);
+
+       if (r->cfg.size)
+               printf("--hashlimit-htable-size %u ", r->cfg.size);
+       if (r->cfg.max)
+               printf("--hashlimit-htable-max %u ", r->cfg.max);
+       if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+               printf("--hashlimit-htable-gcinterval %u", r->cfg.gc_interval);
+       if (r->cfg.expire != XT_HASHLIMIT_EXPIRE)
+               printf("--hashlimit-htable-expire %u ", r->cfg.expire);
+}
+
+static struct ip6tables_match hashlimit = { NULL,
+       .name           = "hashlimit",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct xt_hashlimit_info)),
+       .userspacesize  = offsetof(struct xt_hashlimit_info, hinfo),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_match6(&hashlimit);
+}
similarity index 96%
rename from extensions/libip6t_icmpv6.c
rename to extensions/libip6t_icmp6.c
index a29bb38..6940d0e 100644 (file)
@@ -164,11 +164,15 @@ parse(int c, char **argv, int invert, unsigned int *flags,
 
        switch (c) {
        case '1':
+               if (*flags == 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "icmpv6 match: only use --icmpv6-type once!");
                check_inverse(optarg, &invert, &optind, 0);
                parse_icmpv6(argv[optind-1], &icmpv6info->type, 
                             icmpv6info->code);
                if (invert)
                        icmpv6info->invflags |= IP6T_ICMP_INV;
+               *flags = 1;
                break;
 
        default:
@@ -247,9 +251,11 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
        printf(" ");
 }
 
-/* Final check; we don't care. */
 static void final_check(unsigned int flags)
 {
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM,
+                          "icmpv6 match: You must specify `--icmpv6-type'");
 }
 
 static struct ip6tables_match icmpv6 = {
similarity index 79%
rename from extensions/libip6t_icmpv6.man
rename to extensions/libip6t_icmp6.man
index 2047180..c755fbf 100644 (file)
@@ -1,4 +1,4 @@
-This extension is loaded if `--protocol ipv6-icmp' or `--protocol icmpv6' is
+This extension can be used if `--protocol ipv6-icmp' or `--protocol icmpv6' is
 specified. It provides the following option:
 .TP
 .BR "--icmpv6-type " "[!] \fItype\fP[/\fIcode\fP]|\fItypename\fP"
diff --git a/extensions/libip6t_mh.c b/extensions/libip6t_mh.c
new file mode 100644 (file)
index 0000000..2475b4d
--- /dev/null
@@ -0,0 +1,252 @@
+/* Shared library add-on to ip6tables to add mobility header support. */
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Author:
+ *     Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
+ *
+ * Based on libip6t_{icmpv6,udp}.c
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_mh.h>
+
+struct mh_name {
+       const char *name;
+       u_int8_t type;
+};
+
+static const struct mh_name mh_names[] = {
+       { "binding-refresh-request", 0, },
+       /* Alias */ { "brr", 0, },
+       { "home-test-init", 1, },
+       /* Alias */ { "hoti", 1, },
+       { "careof-test-init", 2, },
+       /* Alias */ { "coti", 2, },
+       { "home-test", 3, },
+       /* Alias */ { "hot", 3, },
+       { "careof-test", 4, },
+       /* Alias */ { "cot", 4, },
+       { "binding-update", 5, },
+       /* Alias */ { "bu", 5, },
+       { "binding-acknowledgement", 6, },
+       /* Alias */ { "ba", 6, },
+       { "binding-error", 7, },
+       /* Alias */ { "be", 7, },
+};
+
+static void print_types_all(void)
+{
+       unsigned int i;
+       printf("Valid MH types:");
+
+       for (i = 0; i < sizeof(mh_names)/sizeof(struct mh_name); i++) {
+               if (i && mh_names[i].type == mh_names[i-1].type)
+                       printf(" (%s)", mh_names[i].name);
+               else
+                       printf("\n%s", mh_names[i].name);
+       }
+       printf("\n");
+}
+
+static void help(void)
+{
+       printf(
+"MH v%s options:\n"
+" --mh-type [!] type[:type]    match mh type\n",
+IPTABLES_VERSION);
+       print_types_all();
+}
+
+static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+       struct ip6t_mh *mhinfo = (struct ip6t_mh *)m->data;
+
+       mhinfo->types[1] = 0xFF;
+}
+
+static unsigned int name_to_type(const char *name)
+{
+       int namelen = strlen(name);
+       unsigned int limit = sizeof(mh_names)/sizeof(struct mh_name);
+       unsigned int match = limit;
+       unsigned int i;
+
+       for (i = 0; i < limit; i++) {
+               if (strncasecmp(mh_names[i].name, name, namelen) == 0) {
+                       int len = strlen(mh_names[i].name);
+                       if (match == limit || len == namelen)
+                               match = i;
+               }
+       }
+
+       if (match != limit) {
+               return mh_names[match].type;
+       } else {
+               unsigned int number;
+
+               if (string_to_number(name, 0, 255, &number) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid MH type `%s'\n", name);
+               return number;
+       }
+}
+
+static void parse_mh_types(const char *mhtype, u_int8_t *types)
+{
+       char *buffer;
+       char *cp;
+
+       buffer = strdup(mhtype);
+       if ((cp = strchr(buffer, ':')) == NULL)
+               types[0] = types[1] = name_to_type(buffer);
+       else {
+               *cp = '\0';
+               cp++;
+
+               types[0] = buffer[0] ? name_to_type(buffer) : 0;
+               types[1] = cp[0] ? name_to_type(cp) : 0xFF;
+
+               if (types[0] > types[1])
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid MH type range (min > max)");
+       }
+       free(buffer);
+}
+
+#define MH_TYPES 0x01
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                const struct ip6t_entry *entry,
+                unsigned int *nfcache,
+                struct ip6t_entry_match **match)
+{
+       struct ip6t_mh *mhinfo = (struct ip6t_mh *)(*match)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & MH_TYPES)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--mh-type' allowed");
+               check_inverse(optarg, &invert, &optind, 0);
+               parse_mh_types(argv[optind-1], mhinfo->types);
+               if (invert)
+                       mhinfo->invflags |= IP6T_MH_INV_TYPE;
+               *flags |= MH_TYPES;
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/* Final check; we don't care. */
+static void final_check(unsigned int flags)
+{
+}
+
+static const char *type_to_name(u_int8_t type)
+{
+       unsigned int i;
+
+       for (i = 0; i < sizeof(mh_names)/sizeof(struct mh_name); i++) {
+               if (mh_names[i].type == type)
+                       return mh_names[i].name;
+       }
+
+       return NULL;
+}
+
+static void print_type(u_int8_t type, int numeric)
+{
+       const char *name;
+       if (numeric || !(name = type_to_name(type)))
+               printf("%u", type);
+       else
+               printf("%s", name);
+}
+
+static void print_types(u_int8_t min, u_int8_t max, int invert, int numeric)
+{
+       const char *inv = invert ? "!" : "";
+
+       if (min != 0 || max != 0xFF || invert) {
+               if (min == max) {
+                       printf("%s", inv);
+                       print_type(min, numeric);
+               } else {
+                       printf("%s", inv);
+                       print_type(min, numeric);
+                       printf(":");
+                       print_type(max, numeric);
+               }
+               printf(" ");
+       }
+}
+
+static void print(const struct ip6t_ip6 *ip,
+                 const struct ip6t_entry_match *match,
+                 int numeric)
+{
+       const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+       printf("mh ");
+       print_types(mhinfo->types[0], mhinfo->types[1],
+                   mhinfo->invflags & IP6T_MH_INV_TYPE,
+                   numeric);
+       if (mhinfo->invflags & ~IP6T_MH_INV_MASK)
+               printf("Unknown invflags: 0x%X ",
+                      mhinfo->invflags & ~IP6T_MH_INV_MASK);
+}
+
+static void save(const struct ip6t_ip6 *ip,
+                const struct ip6t_entry_match *match)
+{
+       const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+       if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xFF)
+               return;
+
+       if (mhinfo->invflags & IP6T_MH_INV_TYPE)
+               printf("! ");
+
+       if (mhinfo->types[0] != mhinfo->types[1])
+               printf("--mh-type %u:%u ", mhinfo->types[0], mhinfo->types[1]);
+       else
+               printf("--mh-type %u ", mhinfo->types[0]);
+}
+
+static struct option opts[] = {
+       { "mh-type", 1, 0, '1' },
+       {0}
+};
+
+static struct ip6tables_match mh = {
+       .name           = "mh",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct ip6t_mh)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_mh)),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts,
+};
+
+void _init(void)
+{
+       register_match6(&mh);
+}
diff --git a/extensions/libip6t_mh.man b/extensions/libip6t_mh.man
new file mode 100644 (file)
index 0000000..14f1c64
--- /dev/null
@@ -0,0 +1,12 @@
+This extension is loaded if `--protocol ipv6-mh' or `--protocol mh' is
+specified. It provides the following option:
+.TP
+.BR "--mh-type " "[!] \fItype\fP[:\fItype\fP]"
+This allows specification of the Mobility Header(MH) type, which can be
+a numeric MH
+.IR type ,
+.IR type
+or one of the MH type names shown by the command
+.nf
+ ip6tables -p ipv6-mh -h
+.fi
index 013241b..166abce 100644 (file)
@@ -5,7 +5,8 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
+/* To ensure that iptables compiles with an old kernel */
+#include "../include/linux/netfilter_ipv6/ip6t_multiport.h"
 
 /* Function which prints out usage message. */
 static void
@@ -20,6 +21,23 @@ help(void)
 " --dports ...\n"
 "                              match destination port(s)\n"
 " --ports port[,port,port]\n"
+"                              match both source and destination port(s)\n"
+" NOTE: this kernel does not support port ranges in multiport.\n",
+IPTABLES_VERSION);
+}
+
+static void
+help_v1(void)
+{
+       printf(
+"multiport v%s options:\n"
+" --source-ports [!] port[,port:port,port...]\n"
+" --sports ...\n"
+"                              match source port(s)\n"
+" --destination-ports [!] port[,port:port,port...]\n"
+" --dports ...\n"
+"                              match destination port(s)\n"
+" --ports [!] port[,port:port,port]\n"
 "                              match both source and destination port(s)\n",
 IPTABLES_VERSION);
 }
@@ -33,28 +51,21 @@ static struct option opts[] = {
        {0}
 };
 
-static int
-service_to_port(const char *name, const char *proto)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, proto)) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-               return -1;
-}
-
-static u_int16_t
-parse_port(const char *port, const char *proto)
+static char *
+proto_to_name(u_int8_t proto)
 {
-       unsigned int portnum;
-
-       if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
-           (portnum = service_to_port(port, proto)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid port/service `%s' specified", port);
+       switch (proto) {
+       case IPPROTO_TCP:
+               return "tcp";
+       case IPPROTO_UDP:
+               return "udp";
+       case IPPROTO_SCTP:
+               return "sctp";
+       case IPPROTO_DCCP:
+               return "dccp";
+       default:
+               return NULL;
+       }
 }
 
 static unsigned int
@@ -77,6 +88,46 @@ parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
        return i;
 }
 
+static void
+parse_multi_ports_v1(const char *portstring, 
+                    struct ip6t_multiport_v1 *multiinfo,
+                    const char *proto)
+{
+       char *buffer, *cp, *next, *range;
+       unsigned int i;
+       u_int16_t m;
+
+       buffer = strdup(portstring);
+       if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
+
+       for (i=0; i<IP6T_MULTI_PORTS; i++)
+               multiinfo->pflags[i] = 0;
+       for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next, i++) {
+               next=strchr(cp, ',');
+               if (next) *next++='\0';
+               range = strchr(cp, ':');
+               if (range) {
+                       if (i == IP6T_MULTI_PORTS-1)
+                               exit_error(PARAMETER_PROBLEM,
+                                          "too many ports specified");
+                       *range++ = '\0';
+               }
+               multiinfo->ports[i] = parse_port(cp, proto);
+               if (range) {
+                       multiinfo->pflags[i] = 1;
+                       multiinfo->ports[++i] = parse_port(range, proto);
+                       if (multiinfo->ports[i-1] >= multiinfo->ports[i])
+                               exit_error(PARAMETER_PROBLEM,
+                                          "invalid portrange specified");
+                       m <<= 1;
+               }
+       }
+       multiinfo->count = i;
+       if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
+       free(buffer);
+}
+
 /* Initialize the match. */
 static void
 init(struct ip6t_entry_match *m, unsigned int *nfcache)
@@ -86,16 +137,16 @@ init(struct ip6t_entry_match *m, unsigned int *nfcache)
 static const char *
 check_proto(const struct ip6t_entry *entry)
 {
-       if (entry->ipv6.proto == IPPROTO_TCP)
-               return "tcp";
-       else if (entry->ipv6.proto == IPPROTO_UDP)
-               return "udp";
+       char *proto;
+
+       if ((proto = proto_to_name(entry->ipv6.proto)) != NULL)
+               return proto;
        else if (!entry->ipv6.proto)
                exit_error(PARAMETER_PROBLEM,
-                          "multiport needs `-p tcp' or `-p udp'");
+                          "multiport needs `-p tcp', `-p udp', `-p sctp' or `-p dccp'");
        else
                exit_error(PARAMETER_PROBLEM,
-                          "multiport only works with TCP or UDP");
+                          "multiport only works with TCP, UDP, SCTP and DCCP");
 }
 
 /* Function which parses command options; returns true if it
@@ -150,6 +201,52 @@ parse(int c, char **argv, int invert, unsigned int *flags,
        return 1;
 }
 
+static int
+parse_v1(int c, char **argv, int invert, unsigned int *flags,
+        const struct ip6t_entry *entry,
+        unsigned int *nfcache,
+        struct ip6t_entry_match **match)
+{
+       const char *proto;
+       struct ip6t_multiport_v1 *multiinfo
+               = (struct ip6t_multiport_v1 *)(*match)->data;
+
+       switch (c) {
+       case '1':
+               check_inverse(argv[optind-1], &invert, &optind, 0);
+               proto = check_proto(entry);
+               parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
+               multiinfo->flags = IP6T_MULTIPORT_SOURCE;
+               break;
+
+       case '2':
+               check_inverse(argv[optind-1], &invert, &optind, 0);
+               proto = check_proto(entry);
+               parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
+               multiinfo->flags = IP6T_MULTIPORT_DESTINATION;
+               break;
+
+       case '3':
+               check_inverse(argv[optind-1], &invert, &optind, 0);
+               proto = check_proto(entry);
+               parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
+               multiinfo->flags = IP6T_MULTIPORT_EITHER;
+               break;
+
+       default:
+               return 0;
+       }
+
+       if (invert)
+               multiinfo->invert = 1;
+
+       if (*flags)
+               exit_error(PARAMETER_PROBLEM,
+                          "multiport can only have one option");
+       *flags = 1;
+       return 1;
+}
+
 /* Final check; must specify something. */
 static void
 final_check(unsigned int flags)
@@ -163,8 +260,7 @@ port_to_service(int port, u_int8_t proto)
 {
        struct servent *service;
 
-       if ((service = getservbyport(htons(port),
-                                    proto == IPPROTO_TCP ? "tcp" : "udp")))
+       if ((service = getservbyport(htons(port), proto_to_name(proto))))
                return service->s_name;
 
        return NULL;
@@ -218,6 +314,49 @@ print(const struct ip6t_ip6 *ip,
        printf(" ");
 }
 
+static void
+print_v1(const struct ip6t_ip6 *ip,
+        const struct ip6t_entry_match *match,
+        int numeric)
+{
+       const struct ip6t_multiport_v1 *multiinfo
+               = (const struct ip6t_multiport_v1 *)match->data;
+       unsigned int i;
+
+       printf("multiport ");
+
+       switch (multiinfo->flags) {
+       case IP6T_MULTIPORT_SOURCE:
+               printf("sports ");
+               break;
+
+       case IP6T_MULTIPORT_DESTINATION:
+               printf("dports ");
+               break;
+
+       case IP6T_MULTIPORT_EITHER:
+               printf("ports ");
+               break;
+
+       default:
+               printf("ERROR ");
+               break;
+       }
+
+       if (multiinfo->invert)
+               printf("! ");
+
+       for (i=0; i < multiinfo->count; i++) {
+               printf("%s", i ? "," : "");
+               print_port(multiinfo->ports[i], ip->proto, numeric);
+               if (multiinfo->pflags[i]) {
+                       printf(":");
+                       print_port(multiinfo->ports[++i], ip->proto, numeric);
+               }
+       }
+       printf(" ");
+}
+
 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
 {
@@ -246,6 +385,41 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
        printf(" ");
 }
 
+static void save_v1(const struct ip6t_ip6 *ip, 
+                   const struct ip6t_entry_match *match)
+{
+       const struct ip6t_multiport_v1 *multiinfo
+               = (const struct ip6t_multiport_v1 *)match->data;
+       unsigned int i;
+
+       switch (multiinfo->flags) {
+       case IP6T_MULTIPORT_SOURCE:
+               printf("--sports ");
+               break;
+
+       case IP6T_MULTIPORT_DESTINATION:
+               printf("--dports ");
+               break;
+
+       case IP6T_MULTIPORT_EITHER:
+               printf("--ports ");
+               break;
+       }
+
+       if (multiinfo->invert)
+               printf("! ");
+
+       for (i=0; i < multiinfo->count; i++) {
+               printf("%s", i ? "," : "");
+               print_port(multiinfo->ports[i], ip->proto, 1);
+               if (multiinfo->pflags[i]) {
+                       printf(":");
+                       print_port(multiinfo->ports[++i], ip->proto, 1);
+               }
+       }
+       printf(" ");
+}
+
 static struct ip6tables_match multiport = {
        .name           = "multiport",
        .version        = IPTABLES_VERSION,
@@ -260,8 +434,25 @@ static struct ip6tables_match multiport = {
        .extra_opts     = opts,
 };
 
+static struct ip6tables_match multiport_v1 = { 
+       .next           = NULL,
+       .name           = "multiport",
+       .revision       = 1,
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct ip6t_multiport_v1)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_multiport_v1)),
+       .help           = &help_v1,
+       .init           = &init,
+       .parse          = &parse_v1,
+       .final_check    = &final_check,
+       .print          = &print_v1,
+       .save           = &save_v1,
+       .extra_opts     = opts
+};
+
 void
 _init(void)
 {
        register_match6(&multiport);
+       register_match6(&multiport_v1);
 }
index 159cc6d..6f75a6e 100644 (file)
@@ -1,21 +1,20 @@
 This module matches a set of source or destination ports.  Up to 15
-ports can be specified.  A port range (port:port) counts as two
-ports, but range isn't supported now. It can only be used in conjunction
+ports can be specified.  It can only be used in conjunction
 with
 .B "-p tcp"
 or
 .BR "-p udp" .
 .TP
-.BR "--source-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport:port\fP...]]"
+.BR "--source-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport\fP...]]"
 Match if the source port is one of the given ports.  The flag
 .B --sports
 is a convenient alias for this option.
 .TP
-.BR "--destination-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport:port\fP...]]"
+.BR "--destination-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport\fP...]]"
 Match if the destination port is one of the given ports.  The flag
 .B --dports
 is a convenient alias for this option.
 .TP
-.BR "--ports " "\fI[!] port\fP[,\fIport\fP[,\fIport:port\fP...]]"
+.BR "--ports " "\fI[!] port\fP[,\fIport\fP[,\fIport\fP...]]"
 Match if the both the source and destination ports are equal to each
 other and to one of the given ports.
diff --git a/extensions/libip6t_nth.c b/extensions/libip6t_nth.c
deleted file mode 100644 (file)
index 19b13f7..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/* 
-   Shared library add-on to iptables to add match support for every Nth packet
-   
-   This file is distributed under the terms of the GNU General Public
-   License (GPL). Copies of the GPL can be obtained from:
-   ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-   2001-07-17 Fabrice MARIE <fabrice@netfilter.org> : initial development.
-   2001-09-20 Richard Wagner (rwagner@cloudnet.com)
-        * added support for multiple counters
-        * added support for matching on individual packets
-          in the counter cycle
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_nth.h>
-
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"nth v%s options:\n"
-"   --every     Nth              Match every Nth packet\n"
-"  [--counter]  num              Use counter 0-%u (default:0)\n"
-"  [--start]    num              Initialize the counter at the number 'num'\n"
-"                                instead of 0. Must be between 0 and Nth-1\n"
-"  [--packet]   num              Match on 'num' packet. Must be between 0\n"
-"                                and Nth-1.\n\n"
-"                                If --packet is used for a counter than\n"
-"                                there must be Nth number of --packet\n"
-"                                rules, covering all values between 0 and\n"
-"                                Nth-1 inclusively.\n",
-IPTABLES_VERSION, IP6T_NTH_NUM_COUNTERS-1);
-}
-
-static struct option opts[] = {
-       { "every", 1, 0, '1' },
-       { "start", 1, 0, '2' },
-        { "counter", 1, 0, '3' },
-        { "packet", 1, 0, '4' },
-       { 0 }
-};
-
-#define IP6T_NTH_OPT_EVERY     0x01
-#define IP6T_NTH_OPT_NOT_EVERY 0x02
-#define IP6T_NTH_OPT_START     0x04
-#define IP6T_NTH_OPT_COUNTER     0x08
-#define IP6T_NTH_OPT_PACKET      0x10
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ip6t_entry *entry,
-      unsigned int *nfcache,
-      struct ip6t_entry_match **match)
-{
-       struct ip6t_nth_info *nthinfo = (struct ip6t_nth_info *)(*match)->data;
-       unsigned int num;
-
-       switch (c) {
-       case '1':
-               /* check for common mistakes... */
-               if ((!invert) && (*flags & IP6T_NTH_OPT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --every twice");
-               if (invert && (*flags & IP6T_NTH_OPT_NOT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify ! --every twice");
-               if ((!invert) && (*flags & IP6T_NTH_OPT_NOT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --every with ! --every");
-               if (invert && (*flags & IP6T_NTH_OPT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify ! --every with --every");
-
-               /* Remember, this function will interpret a leading 0 to be 
-                  Octal, a leading 0x to be hexdecimal... */
-                if (string_to_number(optarg, 2, 100, &num) == -1 || num < 2)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --every `%s', must be between 2 and 100", optarg);
-
-               /* assign the values */
-               nthinfo->every = num-1;
-               nthinfo->startat = 0;
-                nthinfo->packet = 0xFF;
-                if(!(*flags & IP6T_NTH_OPT_EVERY))
-                {
-                        nthinfo->counter = 0;
-                }
-               if (invert)
-               {
-                       *flags |= IP6T_NTH_OPT_NOT_EVERY;
-                       nthinfo->not = 1;
-               }
-               else
-               {
-                       *flags |= IP6T_NTH_OPT_EVERY;
-                       nthinfo->not = 0;
-               }
-               break;
-       case '2':
-               /* check for common mistakes... */
-               if (!((*flags & IP6T_NTH_OPT_EVERY) ||
-                     (*flags & IP6T_NTH_OPT_NOT_EVERY)))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --start before --every");
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify with ! --start");
-               if (*flags & IP6T_NTH_OPT_START)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --start twice");
-               if (string_to_number(optarg, 0, nthinfo->every, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --start `%s', must between 0 and %u", optarg, nthinfo->every);
-               *flags |= IP6T_NTH_OPT_START;
-               nthinfo->startat = num;
-               break;
-        case '3':
-                /* check for common mistakes... */
-                if (invert)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify with ! --counter");
-                if (*flags & IP6T_NTH_OPT_COUNTER)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --counter twice");
-                if (string_to_number(optarg, 0, IP6T_NTH_NUM_COUNTERS-1, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --counter `%s', must between 0 and %u", optarg, IP6T_NTH_NUM_COUNTERS-1);
-                /* assign the values */
-                *flags |= IP6T_NTH_OPT_COUNTER;
-                nthinfo->counter = num;
-                break;
-        case '4':
-                /* check for common mistakes... */
-                if (!((*flags & IP6T_NTH_OPT_EVERY) ||
-                      (*flags & IP6T_NTH_OPT_NOT_EVERY)))
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --packet before --every");
-                if ((*flags & IP6T_NTH_OPT_NOT_EVERY))
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --packet with ! --every");
-                if (invert)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify with ! --packet");
-                if (*flags & IP6T_NTH_OPT_PACKET)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --packet twice");
-                if (string_to_number(optarg, 0, nthinfo->every, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --packet `%s', must between 0 and %u", optarg, nthinfo->every);
-                *flags |= IP6T_NTH_OPT_PACKET;
-                nthinfo->packet = num;
-                break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
-      const struct ip6t_entry_match *match,
-      int numeric)
-{
-       const struct ip6t_nth_info *nthinfo
-               = (const struct ip6t_nth_info *)match->data;
-
-       if (nthinfo->not == 1)
-               printf(" !");
-       printf("every %uth ", (nthinfo->every +1));
-       if (nthinfo->counter != 0) 
-               printf("counter #%u ", (nthinfo->counter));
-        if (nthinfo->packet != 0xFF)
-                printf("packet #%u ", nthinfo->packet);
-       if (nthinfo->startat != 0)
-               printf("start at %u ", nthinfo->startat);
-}
-
-/* Saves the union ip6t_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
-       const struct ip6t_nth_info *nthinfo
-               = (const struct ip6t_nth_info *)match->data;
-
-       if (nthinfo->not == 1)
-               printf("! ");
-       printf("--every %u ", (nthinfo->every +1));
-       printf("--counter %u ", (nthinfo->counter));
-       if (nthinfo->startat != 0)
-               printf("--start %u ", nthinfo->startat );
-        if (nthinfo->packet != 0xFF)
-                printf("--packet %u ", nthinfo->packet );
-}
-
-struct ip6tables_match nth = {
-       .name           = "nth",
-       .version        = IPTABLES_VERSION,
-       .size           = IP6T_ALIGN(sizeof(struct ip6t_nth_info)),
-       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_nth_info)),
-       .help           = &help,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts,
-};
-
-void _init(void)
-{
-       register_match6(&nth);
-}
diff --git a/extensions/libip6t_nth.man b/extensions/libip6t_nth.man
deleted file mode 100644 (file)
index d215fd5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-This module matches every `n'th packet
-.TP
-.BI "--every " "value"
-Match every `value' packet
-.TP
-.BI "[" "--counter " "num" "]"
-Use internal counter number `num'.  Default is `0'.
-.TP
-.BI "[" "--start " "num" "]"
-Initialize the counter at the number `num' insetad of `0'.  Most between `0'
-and `value'-1.
-.TP
-.BI "[" "--packet " "num" "]"
-Match on `num' packet.  Most be between `0' and `value'-1.
diff --git a/extensions/libip6t_random.c b/extensions/libip6t_random.c
deleted file mode 100644 (file)
index d34a230..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* 
-   Shared library add-on to iptables to add match support for random match.
-   
-   This file is distributed under the terms of the GNU General Public
-   License (GPL). Copies of the GPL can be obtained from:
-   ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-   2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial development.
-   2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 port.
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_random.h>
-
-/**
- * The kernel random routing returns numbers between 0 and 255.
- * To ease the task of the user in choosing the probability
- * of matching, we want him to be able to use percentages.
- * Therefore we have to accept numbers in percentage here,
- * turn them into number between 0 and 255 for the kernel module,
- * and turn them back to percentages when we print/save
- * the rule.
- */
-
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"random v%s options:\n"
-"  [--average]     percent      The probability in percentage of the match\n"
-"                               If ommited, a probability of 50%% percent is set.\n"
-"                               Percentage must be within : 1 <= percent <= 99.\n\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "average", 1, 0, '1' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
-       struct ip6t_rand_info *randinfo = (struct ip6t_rand_info *)(m)->data;
-
-       /* We assign the average to be 50 which is our default value */
-       /* 50 * 2.55 = 128 */
-       randinfo->average = 128;
-}
-
-#define IP6T_RAND_OPT_AVERAGE  0x01
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ip6t_entry *entry,
-      unsigned int *nfcache,
-      struct ip6t_entry_match **match)
-{
-       struct ip6t_rand_info *randinfo = (struct ip6t_rand_info *)(*match)->data;
-       unsigned int num;
-
-       switch (c) {
-       case '1':
-               /* check for common mistakes... */
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify ! --average");
-               if (*flags & IP6T_RAND_OPT_AVERAGE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --average twice");
-
-               /* Remember, this function will interpret a leading 0 to be 
-                  Octal, a leading 0x to be hexdecimal... */
-                if (string_to_number(optarg, 1, 99, &num) == -1 || num < 1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --average `%s', must be between 1 and 99", optarg);
-
-               /* assign the values */
-               randinfo->average = (int)(num * 2.55);
-               *flags |= IP6T_RAND_OPT_AVERAGE;
-               break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
-      const struct ip6t_entry_match *match,
-      int numeric)
-{
-       const struct ip6t_rand_info *randinfo
-               = (const struct ip6t_rand_info *)match->data;
-       div_t result = div((randinfo->average*100), 255);
-       if (result.rem > 127)  /* round up... */
-               ++result.quot;
-
-       printf(" random %u%% ", result.quot);
-}
-
-/* Saves the union ip6t_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
-       const struct ip6t_rand_info *randinfo
-               = (const struct ip6t_rand_info *)match->data;
-       div_t result = div((randinfo->average *100), 255);
-       if (result.rem > 127)  /* round up... */
-               ++result.quot;
-
-       printf("--average %u ", result.quot);
-}
-
-struct ip6tables_match rand_match = {
-       .name           = "random",
-       .version        = IPTABLES_VERSION,
-       .size           = IP6T_ALIGN(sizeof(struct ip6t_rand_info)),
-       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_rand_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts,
-};
-
-void _init(void)
-{
-       register_match6(&rand_match);
-}
diff --git a/extensions/libip6t_random.man b/extensions/libip6t_random.man
deleted file mode 100644 (file)
index f808a77..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-This module randomly matches a certain percentage of all packets.
-.TP
-.BI "--average " "percent"
-Matches the given percentage.  If omitted, a probability of 50% is set. 
diff --git a/extensions/libip6t_sctp.c b/extensions/libip6t_sctp.c
new file mode 100644 (file)
index 0000000..aee7072
--- /dev/null
@@ -0,0 +1,550 @@
+/* Shared library add-on to iptables for SCTP matching
+ *
+ * (C) 2003 by Harald Welte <laforge@gnumonks.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ * libipt_ecn.c borrowed heavily from libipt_dscp.c
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <ctype.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#include <linux/netfilter/xt_sctp.h>
+
+/* Some ZS!#@:$%*#$! has replaced the ELEMCOUNT macro in ipt_sctp.h with
+ * ARRAY_SIZE without noticing that this file is used from userserspace,
+ * and userspace doesn't have ARRAY_SIZE */
+
+#ifndef ELEMCOUNT
+#define ELEMCOUNT ARRAY_SIZE
+#endif
+
+#if 0
+#define DEBUGP(format, first...) printf(format, ##first)
+#define static
+#else
+#define DEBUGP(format, fist...) 
+#endif
+
+static void
+print_chunk(u_int32_t chunknum, int numeric);
+
+/* Initialize the match. */
+static void
+init(struct ip6t_entry_match *m, 
+     unsigned int *nfcache)
+{
+       int i;
+       struct xt_sctp_info *einfo = (struct xt_sctp_info *)m->data;
+
+       memset(einfo, 0, sizeof(struct xt_sctp_info));
+
+       for (i = 0; i < XT_NUM_SCTP_FLAGS; i++) {
+               einfo->flag_info[i].chunktype = -1;
+       }
+}
+
+static void help(void)
+{
+       printf(
+"SCTP match v%s options\n"
+" --source-port [!] port[:port]                          match source port(s)\n"
+" --sport ...\n"
+" --destination-port [!] port[:port]                     match destination port(s)\n"
+" --dport ...\n" 
+" --chunk-types [!] (all|any|none) (chunktype[:flags])+        match if all, any or none of\n"
+"                                                      chunktypes are present\n"
+"chunktypes - DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK ALL NONE\n",
+       IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { .name = "source-port", .has_arg = 1, .flag = 0, .val = '1' },
+       { .name = "sport", .has_arg = 1, .flag = 0, .val = '1' },
+       { .name = "destination-port", .has_arg = 1, .flag = 0, .val = '2' },
+       { .name = "dport", .has_arg = 1, .flag = 0, .val = '2' },
+       { .name = "chunk-types", .has_arg = 1, .flag = 0, .val = '3' },
+       { .name = 0 }
+};
+
+static void
+parse_sctp_ports(const char *portstring, 
+                u_int16_t *ports)
+{
+       char *buffer;
+       char *cp;
+
+       buffer = strdup(portstring);
+       DEBUGP("%s\n", portstring);
+       if ((cp = strchr(buffer, ':')) == NULL) {
+               ports[0] = ports[1] = parse_port(buffer, "sctp");
+       }
+       else {
+               *cp = '\0';
+               cp++;
+
+               ports[0] = buffer[0] ? parse_port(buffer, "sctp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "sctp") : 0xFFFF;
+
+               if (ports[0] > ports[1])
+                       exit_error(PARAMETER_PROBLEM,
+                                  "invalid portrange (min > max)");
+       }
+       free(buffer);
+}
+
+struct sctp_chunk_names {
+       const char *name;
+       unsigned int chunk_type;
+       const char *valid_flags;
+};
+
+/*'ALL' and 'NONE' will be treated specially. */
+static struct sctp_chunk_names sctp_chunk_names[]
+= { { .name = "DATA",          .chunk_type = 0,   .valid_flags = "-----UBE"},
+    { .name = "INIT",          .chunk_type = 1,   .valid_flags = "--------"},
+    { .name = "INIT_ACK",      .chunk_type = 2,   .valid_flags = "--------"},
+    { .name = "SACK",          .chunk_type = 3,   .valid_flags = "--------"},
+    { .name = "HEARTBEAT",     .chunk_type = 4,   .valid_flags = "--------"},
+    { .name = "HEARTBEAT_ACK", .chunk_type = 5,   .valid_flags = "--------"},
+    { .name = "ABORT",         .chunk_type = 6,   .valid_flags = "-------T"},
+    { .name = "SHUTDOWN",      .chunk_type = 7,   .valid_flags = "--------"},
+    { .name = "SHUTDOWN_ACK",  .chunk_type = 8,   .valid_flags = "--------"},
+    { .name = "ERROR",         .chunk_type = 9,   .valid_flags = "--------"},
+    { .name = "COOKIE_ECHO",   .chunk_type = 10,  .valid_flags = "--------"},
+    { .name = "COOKIE_ACK",    .chunk_type = 11,  .valid_flags = "--------"},
+    { .name = "ECN_ECNE",      .chunk_type = 12,  .valid_flags = "--------"},
+    { .name = "ECN_CWR",       .chunk_type = 13,  .valid_flags = "--------"},
+    { .name = "SHUTDOWN_COMPLETE", .chunk_type = 14,  .valid_flags = "-------T"},
+    { .name = "ASCONF",                .chunk_type = 31,  .valid_flags = "--------"},
+    { .name = "ASCONF_ACK",    .chunk_type = 30,  .valid_flags = "--------"},
+};
+
+static void
+save_chunk_flag_info(struct xt_sctp_flag_info *flag_info,
+                    int *flag_count,
+                    int chunktype, 
+                    int bit, 
+                    int set)
+{
+       int i;
+
+       for (i = 0; i < *flag_count; i++) {
+               if (flag_info[i].chunktype == chunktype) {
+                       DEBUGP("Previous match found\n");
+                       flag_info[i].chunktype = chunktype;
+                       flag_info[i].flag_mask |= (1 << bit);
+                       if (set) {
+                               flag_info[i].flag |= (1 << bit);
+                       }
+
+                       return;
+               }
+       }
+       
+       if (*flag_count == XT_NUM_SCTP_FLAGS) {
+               exit_error (PARAMETER_PROBLEM,
+                       "Number of chunk types with flags exceeds currently allowed limit."
+                       "Increasing this limit involves changing XT_NUM_SCTP_FLAGS and"
+                       "recompiling both the kernel space and user space modules\n");
+       }
+
+       flag_info[*flag_count].chunktype = chunktype;
+       flag_info[*flag_count].flag_mask |= (1 << bit);
+       if (set) {
+               flag_info[*flag_count].flag |= (1 << bit);
+       }
+       (*flag_count)++;
+}
+
+static void
+parse_sctp_chunk(struct xt_sctp_info *einfo, 
+                const char *chunks)
+{
+       char *ptr;
+       char *buffer;
+       unsigned int i, j;
+       int found = 0;
+       char *chunk_flags;
+
+       buffer = strdup(chunks);
+       DEBUGP("Buffer: %s\n", buffer);
+
+       SCTP_CHUNKMAP_RESET(einfo->chunkmap);
+
+       if (!strcasecmp(buffer, "ALL")) {
+               SCTP_CHUNKMAP_SET_ALL(einfo->chunkmap);
+               goto out;
+       }
+       
+       if (!strcasecmp(buffer, "NONE")) {
+               SCTP_CHUNKMAP_RESET(einfo->chunkmap);
+               goto out;
+       }
+
+       for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
+               found = 0;
+               DEBUGP("Next Chunk type %s\n", ptr);
+               
+               if ((chunk_flags = strchr(ptr, ':')) != NULL) {
+                       *chunk_flags++ = 0;
+               }
+               
+               for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
+                       if (strcasecmp(sctp_chunk_names[i].name, ptr) == 0) {
+                               DEBUGP("Chunk num %d\n", sctp_chunk_names[i].chunk_type);
+                               SCTP_CHUNKMAP_SET(einfo->chunkmap, 
+                                       sctp_chunk_names[i].chunk_type);
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Unknown sctp chunk `%s'", ptr);
+
+               if (chunk_flags) {
+                       DEBUGP("Chunk flags %s\n", chunk_flags);
+                       for (j = 0; j < strlen(chunk_flags); j++) {
+                               char *p;
+                               int bit;
+
+                               if ((p = strchr(sctp_chunk_names[i].valid_flags, 
+                                               toupper(chunk_flags[j]))) != NULL) {
+                                       bit = p - sctp_chunk_names[i].valid_flags;
+                                       bit = 7 - bit;
+
+                                       save_chunk_flag_info(einfo->flag_info, 
+                                               &(einfo->flag_count), i, bit, 
+                                               isupper(chunk_flags[j]));
+                               } else {
+                                       exit_error(PARAMETER_PROBLEM, 
+                                               "Invalid flags for chunk type %d\n", i);
+                               }
+                       }
+               }
+       }
+out:
+       free(buffer);
+}
+
+static void
+parse_sctp_chunks(struct xt_sctp_info *einfo,
+                 const char *match_type,
+                 const char *chunks)
+{
+       DEBUGP("Match type: %s Chunks: %s\n", match_type, chunks);
+       if (!strcasecmp(match_type, "ANY")) {
+               einfo->chunk_match_type = SCTP_CHUNK_MATCH_ANY;
+       } else  if (!strcasecmp(match_type, "ALL")) {
+               einfo->chunk_match_type = SCTP_CHUNK_MATCH_ALL;
+       } else  if (!strcasecmp(match_type, "ONLY")) {
+               einfo->chunk_match_type = SCTP_CHUNK_MATCH_ONLY;
+       } else {
+               exit_error (PARAMETER_PROBLEM, 
+                       "Match type has to be one of \"ALL\", \"ANY\" or \"ONLY\"");
+       }
+
+       SCTP_CHUNKMAP_RESET(einfo->chunkmap);
+       parse_sctp_chunk(einfo, chunks);
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+       struct xt_sctp_info *einfo
+               = (struct xt_sctp_info *)(*match)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & XT_SCTP_SRC_PORTS)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--source-port' allowed");
+               einfo->flags |= XT_SCTP_SRC_PORTS;
+               check_inverse(optarg, &invert, &optind, 0);
+               parse_sctp_ports(argv[optind-1], einfo->spts);
+               if (invert)
+                       einfo->invflags |= XT_SCTP_SRC_PORTS;
+               *flags |= XT_SCTP_SRC_PORTS;
+               break;
+
+       case '2':
+               if (*flags & XT_SCTP_DEST_PORTS)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--destination-port' allowed");
+               einfo->flags |= XT_SCTP_DEST_PORTS;
+               check_inverse(optarg, &invert, &optind, 0);
+               parse_sctp_ports(argv[optind-1], einfo->dpts);
+               if (invert)
+                       einfo->invflags |= XT_SCTP_DEST_PORTS;
+               *flags |= XT_SCTP_DEST_PORTS;
+               break;
+
+       case '3':
+               if (*flags & XT_SCTP_CHUNK_TYPES)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--chunk-types' allowed");
+               check_inverse(optarg, &invert, &optind, 0);
+
+               if (!argv[optind] 
+                   || argv[optind][0] == '-' || argv[optind][0] == '!')
+                       exit_error(PARAMETER_PROBLEM,
+                                  "--chunk-types requires two args");
+
+               einfo->flags |= XT_SCTP_CHUNK_TYPES;
+               parse_sctp_chunks(einfo, argv[optind-1], argv[optind]);
+               if (invert)
+                       einfo->invflags |= XT_SCTP_CHUNK_TYPES;
+               optind++;
+               *flags |= XT_SCTP_CHUNK_TYPES;
+               break;
+
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+static char *
+port_to_service(int port)
+{
+       struct servent *service;
+
+       if ((service = getservbyport(htons(port), "sctp")))
+               return service->s_name;
+
+       return NULL;
+}
+
+static void
+print_port(u_int16_t port, int numeric)
+{
+       char *service;
+
+       if (numeric || (service = port_to_service(port)) == NULL)
+               printf("%u", port);
+       else
+               printf("%s", service);
+}
+
+static void
+print_ports(const char *name, u_int16_t min, u_int16_t max,
+           int invert, int numeric)
+{
+       const char *inv = invert ? "!" : "";
+
+       if (min != 0 || max != 0xFFFF || invert) {
+               printf("%s", name);
+               if (min == max) {
+                       printf(":%s", inv);
+                       print_port(min, numeric);
+               } else {
+                       printf("s:%s", inv);
+                       print_port(min, numeric);
+                       printf(":");
+                       print_port(max, numeric);
+               }
+               printf(" ");
+       }
+}
+
+static void
+print_chunk_flags(u_int32_t chunknum, u_int8_t chunk_flags, u_int8_t chunk_flags_mask)
+{
+       int i;
+
+       DEBUGP("type: %d\tflags: %x\tflag mask: %x\n", chunknum, chunk_flags, 
+                       chunk_flags_mask);
+
+       if (chunk_flags_mask) {
+               printf(":");
+       }
+
+       for (i = 7; i >= 0; i--) {
+               if (chunk_flags_mask & (1 << i)) {
+                       if (chunk_flags & (1 << i)) {
+                               printf("%c", sctp_chunk_names[chunknum].valid_flags[7-i]);
+                       } else {
+                               printf("%c", tolower(sctp_chunk_names[chunknum].valid_flags[7-i]));
+                       }
+               }
+       }
+}
+
+static void
+print_chunk(u_int32_t chunknum, int numeric)
+{
+       if (numeric) {
+               printf("0x%04X", chunknum);
+       }
+       else {
+               int i;
+
+               for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
+                       if (sctp_chunk_names[i].chunk_type == chunknum)
+                               printf("%s", sctp_chunk_names[chunknum].name);
+               }
+       }
+}
+
+static void
+print_chunks(u_int32_t chunk_match_type, 
+            const u_int32_t *chunkmap, 
+            const struct xt_sctp_flag_info *flag_info,
+            int flag_count,
+            int numeric)
+{
+       int i, j;
+       int flag;
+
+       switch (chunk_match_type) {
+               case SCTP_CHUNK_MATCH_ANY:      printf("any "); break;
+               case SCTP_CHUNK_MATCH_ALL:      printf("all "); break;
+               case SCTP_CHUNK_MATCH_ONLY:     printf("only "); break;
+               default:        printf("Never reach herer\n"); break;
+       }
+
+       if (SCTP_CHUNKMAP_IS_CLEAR(chunkmap)) {
+               printf("NONE ");
+               goto out;
+       }
+       
+       if (SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)) {
+               printf("ALL ");
+               goto out;
+       }
+       
+       flag = 0;
+       for (i = 0; i < 256; i++) {
+               if (SCTP_CHUNKMAP_IS_SET(chunkmap, i)) {
+                       if (flag)
+                               printf(",");
+                       flag = 1;
+                       print_chunk(i, numeric);
+                       for (j = 0; j < flag_count; j++) {
+                               if (flag_info[j].chunktype == i) {
+                                       print_chunk_flags(i, flag_info[j].flag,
+                                               flag_info[j].flag_mask);
+                               }
+                       }
+               }
+       }
+
+       if (flag)
+               printf(" ");
+out:
+       return;
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match,
+      int numeric)
+{
+       const struct xt_sctp_info *einfo =
+               (const struct xt_sctp_info *)match->data;
+
+       printf("sctp ");
+
+       if (einfo->flags & XT_SCTP_SRC_PORTS) {
+               print_ports("spt", einfo->spts[0], einfo->spts[1],
+                       einfo->invflags & XT_SCTP_SRC_PORTS,
+                       numeric);
+       }
+
+       if (einfo->flags & XT_SCTP_DEST_PORTS) {
+               print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
+                       einfo->invflags & XT_SCTP_DEST_PORTS,
+                       numeric);
+       }
+
+       if (einfo->flags & XT_SCTP_CHUNK_TYPES) {
+               /* FIXME: print_chunks() is used in save() where the printing of '!'
+               s taken care of, so we need to do that here as well */
+               if (einfo->invflags & XT_SCTP_CHUNK_TYPES) {
+                       printf("! ");
+               }
+               print_chunks(einfo->chunk_match_type, einfo->chunkmap,
+                       einfo->flag_info, einfo->flag_count, numeric);
+       }
+}
+
+/* Saves the union xt_matchinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, 
+     const struct ip6t_entry_match *match)
+{
+       const struct xt_sctp_info *einfo =
+               (const struct xt_sctp_info *)match->data;
+
+       if (einfo->flags & XT_SCTP_SRC_PORTS) {
+               if (einfo->invflags & XT_SCTP_SRC_PORTS)
+                       printf("! ");
+               if (einfo->spts[0] != einfo->spts[1])
+                       printf("--sport %u:%u ", 
+                              einfo->spts[0], einfo->spts[1]);
+               else
+                       printf("--sport %u ", einfo->spts[0]);
+       }
+
+       if (einfo->flags & XT_SCTP_DEST_PORTS) {
+               if (einfo->invflags & XT_SCTP_DEST_PORTS)
+                       printf("! ");
+               if (einfo->dpts[0] != einfo->dpts[1])
+                       printf("--dport %u:%u ",
+                              einfo->dpts[0], einfo->dpts[1]);
+               else
+                       printf("--dport %u ", einfo->dpts[0]);
+       }
+
+       if (einfo->flags & XT_SCTP_CHUNK_TYPES) {
+               if (einfo->invflags & XT_SCTP_CHUNK_TYPES)
+                       printf("! ");
+               printf("--chunk-types ");
+
+               print_chunks(einfo->chunk_match_type, einfo->chunkmap, 
+                       einfo->flag_info, einfo->flag_count, 0);
+       }
+}
+
+static
+struct ip6tables_match sctp
+= { .name          = "sctp",
+    .version       = IPTABLES_VERSION,
+    .size          = IP6T_ALIGN(sizeof(struct xt_sctp_info)),
+    .userspacesize = IP6T_ALIGN(sizeof(struct xt_sctp_info)),
+    .help          = &help,
+    .init          = &init,
+    .parse         = &parse,
+    .final_check   = &final_check,
+    .print         = &print,
+    .save          = &save,
+    .extra_opts    = opts
+};
+
+void _init(void)
+{
+       register_match6(&sctp);
+}
+
index 84fd1a4..a4477ce 100644 (file)
@@ -5,7 +5,7 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <ip6tables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
 #include <linux/netfilter_ipv4/ipt_state.h>
 
 #ifndef IPT_STATE_UNTRACKED
index a049128..734387c 100644 (file)
@@ -38,30 +38,6 @@ static struct option opts[] = {
        {0}
 };
 
-static int
-service_to_port(const char *name)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, "tcp")) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-       return -1;
-}
-
-static u_int16_t
-parse_tcp_port(const char *port)
-{
-       unsigned int portnum;
-
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid TCP port/service `%s' specified", port);
-}
-
 static void
 parse_tcp_ports(const char *portstring, u_int16_t *ports)
 {
@@ -70,13 +46,13 @@ parse_tcp_ports(const char *portstring, u_int16_t *ports)
 
        buffer = strdup(portstring);
        if ((cp = strchr(buffer, ':')) == NULL)
-               ports[0] = ports[1] = parse_tcp_port(buffer);
+               ports[0] = ports[1] = parse_port(buffer, "tcp");
        else {
                *cp = '\0';
                cp++;
 
-               ports[0] = buffer[0] ? parse_tcp_port(buffer) : 0;
-               ports[1] = cp[0] ? parse_tcp_port(cp) : 0xFFFF;
+               ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
                
                if (ports[0] > ports[1])
                        exit_error(PARAMETER_PROBLEM, 
index 75d172e..e94566c 100644 (file)
@@ -1,4 +1,4 @@
-These extensions are loaded if `--protocol tcp' is specified. It
+These extensions can be used if `--protocol tcp' is specified. It
 provides the following options:
 .TP
 .BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
index 842581d..cd3c3d4 100644 (file)
@@ -30,30 +30,6 @@ static struct option opts[] = {
        {0}
 };
 
-static int
-service_to_port(const char *name)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, "udp")) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-               return -1;
-}
-
-static u_int16_t
-parse_udp_port(const char *port)
-{
-       unsigned int portnum;
-
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port)) != -1)
-               return (u_int16_t)portnum;
-
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid UDP port/service `%s' specified", port);
-       }
-
 static void
 parse_udp_ports(const char *portstring, u_int16_t *ports)
 {
@@ -62,13 +38,13 @@ parse_udp_ports(const char *portstring, u_int16_t *ports)
 
        buffer = strdup(portstring);
        if ((cp = strchr(buffer, ':')) == NULL)
-               ports[0] = ports[1] = parse_udp_port(buffer);
+               ports[0] = ports[1] = parse_port(buffer, "udp");
        else {
                *cp = '\0';
                cp++;
 
-               ports[0] = buffer[0] ? parse_udp_port(buffer) : 0;
-               ports[1] = cp[0] ? parse_udp_port(cp) : 0xFFFF;
+               ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF;
 
                if (ports[0] > ports[1])
                        exit_error(PARAMETER_PROBLEM,
index 0408479..1d5e590 100644 (file)
@@ -1,4 +1,4 @@
-These extensions are loaded if `--protocol udp' is specified.  It
+These extensions can be used if `--protocol udp' is specified.  It
 provides the following options:
 .TP
 .BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
diff --git a/extensions/libipt_BALANCE.c b/extensions/libipt_BALANCE.c
deleted file mode 100644 (file)
index 6d6392f..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Shared library add-on to iptables to add simple load-balance support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
-
-#define BREAKUP_IP(x) (x)>>24, ((x)>>16) & 0xFF, ((x)>>8) & 0xFF, (x) & 0xFF
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"BALANCE v%s options:\n"
-" --to-destination <ipaddr>-<ipaddr>\n"
-"                              Addresses to map destination to.\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "to-destination", 1, 0, '1' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-       struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *)t->data;
-
-       /* Actually, it's 0, but it's ignored at the moment. */
-       mr->rangesize = 1;
-
-}
-
-/* Parses range of IPs */
-static void
-parse_to(char *arg, struct ip_nat_range *range)
-{
-       char *dash;
-       struct in_addr *ip;
-
-       range->flags |= IP_NAT_RANGE_MAP_IPS;
-       dash = strchr(arg, '-');
-       if (dash)
-               *dash = '\0';
-       else
-               exit_error(PARAMETER_PROBLEM, "Bad IP range `%s'\n", arg);
-
-       ip = dotted_to_addr(arg);
-       if (!ip)
-               exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
-                          arg);
-       range->min_ip = ip->s_addr;
-       ip = dotted_to_addr(dash+1);
-       if (!ip)
-               exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
-                          dash+1);
-       range->max_ip = ip->s_addr;
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      struct ipt_entry_target **target)
-{
-       struct ip_nat_multi_range *mr
-               = (struct ip_nat_multi_range *)(*target)->data;
-
-       switch (c) {
-       case '1':
-               if (check_inverse(optarg, &invert, NULL, 0))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unexpected `!' after --to-destination");
-
-               parse_to(optarg, &mr->range[0]);
-               *flags = 1;
-               return 1;
-
-       default:
-               return 0;
-       }
-}
-
-/* Final check; need --to-dest. */
-static void final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "BALANCE needs --to-destination");
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_target *target,
-      int numeric)
-{
-       struct ip_nat_multi_range *mr
-               = (struct ip_nat_multi_range *)target->data;
-       struct ip_nat_range *r = &mr->range[0];
-       struct in_addr a;
-
-       a.s_addr = r->min_ip;
-
-       printf("balance %s", addr_to_dotted(&a));
-       a.s_addr = r->max_ip;
-       printf("-%s ", addr_to_dotted(&a));
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
-       struct ip_nat_multi_range *mr
-               = (struct ip_nat_multi_range *)target->data;
-       struct ip_nat_range *r = &mr->range[0];
-       struct in_addr a;
-
-       a.s_addr = r->min_ip;
-       printf("--to-destination %s", addr_to_dotted(&a));
-       a.s_addr = r->max_ip;
-       printf("-%s ", addr_to_dotted(&a));
-}
-
-static struct iptables_target balance = { 
-       .next           = NULL,
-       .name           = "BALANCE",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_target(&balance);
-}
diff --git a/extensions/libipt_BALANCE.man b/extensions/libipt_BALANCE.man
deleted file mode 100644 (file)
index 0eb09d0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-This allows you to DNAT connections in a round-robin way over a given range of destination addresses.
-.TP
-.BI "--to-destination " "ipaddr-ipaddr"
-Address range to round-robin over.
diff --git a/extensions/libipt_CONNSECMARK.c b/extensions/libipt_CONNSECMARK.c
new file mode 100644 (file)
index 0000000..237a41f
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Shared library add-on to iptables to add CONNSECMARK target support.
+ *
+ * Based on the MARK and CONNMARK targets.
+ *
+ * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <iptables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+
+#define PFX "CONNSECMARK target: "
+
+static void help(void)
+{
+       printf(
+"CONNSECMARK target v%s options:\n"
+"  --save                   Copy security mark from packet to conntrack\n"
+"  --restore                Copy security mark from connection to packet\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "save", 0, 0, '1' },
+       { "restore", 0, 0, '2' },
+       { 0 }
+};
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                 const struct ipt_entry *entry, struct ipt_entry_target **target)
+{
+       struct xt_connsecmark_target_info *info =
+               (struct xt_connsecmark_target_info*)(*target)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & CONNSECMARK_SAVE)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Can't specify --save twice");
+               info->mode = CONNSECMARK_SAVE;
+               *flags |= CONNSECMARK_SAVE;
+               break;
+
+       case '2':
+               if (*flags & CONNSECMARK_RESTORE)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Can't specify --restore twice");
+               info->mode = CONNSECMARK_RESTORE;
+               *flags |= CONNSECMARK_RESTORE;
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM, PFX "parameter required");
+
+       if (flags == (CONNSECMARK_SAVE|CONNSECMARK_RESTORE))
+               exit_error(PARAMETER_PROBLEM, PFX "only one flag of --save "
+                          "or --restore is allowed");
+}
+
+static void print_connsecmark(struct xt_connsecmark_target_info *info)
+{
+       switch (info->mode) {
+       case CONNSECMARK_SAVE:
+               printf("save ");
+               break;
+               
+       case CONNSECMARK_RESTORE:
+               printf("restore ");
+               break;
+               
+       default:
+               exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+       }
+}
+
+static void print(const struct ipt_ip *ip,
+                 const struct ipt_entry_target *target, int numeric)
+{
+       struct xt_connsecmark_target_info *info =
+               (struct xt_connsecmark_target_info*)(target)->data;
+
+       printf("CONNSECMARK ");
+       print_connsecmark(info);
+}
+
+static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+       struct xt_connsecmark_target_info *info =
+               (struct xt_connsecmark_target_info*)target->data;
+
+       printf("--");
+       print_connsecmark(info);
+}
+
+static struct iptables_target connsecmark = {
+       .next           = NULL,
+       .name           = "CONNSECMARK",
+       .version        = IPTABLES_VERSION,
+       .revision       = 0,
+       .size           = IPT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
+       .userspacesize  = IPT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
+       .parse          = &parse,
+       .help           = &help,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target(&connsecmark);
+}
diff --git a/extensions/libipt_CONNSECMARK.man b/extensions/libipt_CONNSECMARK.man
new file mode 100644 (file)
index 0000000..b94353a
--- /dev/null
@@ -0,0 +1,15 @@
+This module copies security markings from packets to connections
+(if unlabeled), and from connections back to packets (also only
+if unlabeled).  Typically used in conjunction with SECMARK, it is
+only valid in the
+.B mangle
+table.
+.TP
+.B --save
+If the packet has a security marking, copy it to the connection
+if the connection is not marked.
+.TP
+.B --restore
+If the packet does not have a security marking, and the connection
+does, copy the security marking from the connection to the packet.
+
index bdc15eb..b0def31 100644 (file)
@@ -6,7 +6,10 @@
 #include <getopt.h>
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter/nf_nat.h>
+
+#define IPT_DNAT_OPT_DEST 0x1
+#define IPT_DNAT_OPT_RANDOM 0x2
 
 /* Dest NAT data consists of a multi-range, indicating where to map
    to. */
@@ -24,12 +27,14 @@ help(void)
 "DNAT v%s options:\n"
 " --to-destination <ipaddr>[-<ipaddr>][:port-port]\n"
 "                              Address to map destination to.\n"
-"                              (You can use this more than once)\n\n",
+"[--random]\n"
+"\n",
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
        { "to-destination", 1, 0, '1' },
+       { "random", 0, 0, '2' },
        { 0 }
 };
 
@@ -163,9 +168,18 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                                           "Multiple --to-destination not supported");
                }
                *target = parse_to(optarg, portok, info);
-               *flags = 1;
+               /* WTF do we need this for?? */
+               if (*flags & IPT_DNAT_OPT_RANDOM)
+                       info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+               *flags |= IPT_DNAT_OPT_DEST;
                return 1;
 
+       case '2':
+               if (*flags & IPT_DNAT_OPT_DEST) {
+                       info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+                       *flags |= IPT_DNAT_OPT_RANDOM;
+               } else
+                       *flags |= IPT_DNAT_OPT_RANDOM;
        default:
                return 0;
        }
@@ -212,6 +226,8 @@ print(const struct ipt_ip *ip,
        for (i = 0; i < info->mr.rangesize; i++) {
                print_range(&info->mr.range[i]);
                printf(" ");
+               if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+                       printf("random ");
        }
 }
 
@@ -226,6 +242,8 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
                printf("--to-destination ");
                print_range(&info->mr.range[i]);
                printf(" ");
+               if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+                       printf("--random ");
        }
 }
 
index b14c6da..f11f4e2 100644 (file)
@@ -10,7 +10,7 @@ should be modified (and all future packets in this connection will
 also be mangled), and rules should cease being examined.  It takes one
 type of option:
 .TP
-.BR "--to-destination " "\fIipaddr\fP[-\fIipaddr\fP][:\fIport\fP-\fIport\fP]"
+.BR "--to-destination " "[\fIipaddr\fP][-\fIipaddr\fP][:\fIport\fP-\fIport\fP]"
 which can specify a single new destination IP address, an inclusive
 range of IP addresses, and optionally, a port range (which is only
 valid if the rule also specifies
@@ -18,13 +18,19 @@ valid if the rule also specifies
 or
 .BR "-p udp" ).
 If no port range is specified, then the destination port will never be
-modified.
-.RS
-.PP
+modified. If no IP address is specified then only the destination port
+will be modified.
+
 In Kernels up to 2.6.10 you can add several --to-destination options.  For
 those kernels, if you specify more than one destination address, either via an
 address range or multiple --to-destination options, a simple round-robin (one
 after another in cycle) load balancing takes place between these addresses.
 Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
 anymore.
-
+.TP
+.BR "--random"
+If option
+.B "--random"
+is used then port mapping will be randomized (kernel >= 2.6.22).
+.RS
+.PP
diff --git a/extensions/libipt_FTOS.c b/extensions/libipt_FTOS.c
deleted file mode 100644 (file)
index 62df4cd..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* Shared library add-on to iptables for FTOS
- *
- * (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- * libipt_FTOS.c borrowed heavily from libipt_TOS.c  11/09/2000
- *
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_FTOS.h>
-
-struct finfo {
-       struct ipt_entry_target t;
-       u_int8_t ftos;
-};
-
-static void init(struct ipt_entry_target *t, unsigned int *nfcache) 
-{
-}
-
-static void help(void) 
-{
-       printf(
-"FTOS target options\n"
-"  --set-ftos value            Set TOS field in packet header to value\n"
-"                              This value can be in decimal (ex: 32)\n"
-"                              or in hex (ex: 0x20)\n"
-);
-}
-
-static struct option opts[] = {
-       { "set-ftos", 1, 0, 'F' },
-       { 0 }
-};
-
-static void
-parse_ftos(const unsigned char *s, struct ipt_FTOS_info *finfo)
-{
-       unsigned int ftos;
-       
-       if (string_to_number(s, 0, 255, &ftos) == -1)
-               exit_error(PARAMETER_PROBLEM,
-                          "Invalid ftos `%s'\n", s);
-       finfo->ftos = (u_int8_t )ftos;
-       return;
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      struct ipt_entry_target **target)
-{
-       struct ipt_FTOS_info *finfo
-               = (struct ipt_FTOS_info *)(*target)->data;
-
-       switch (c) {
-       case 'F':
-               if (*flags)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "FTOS target: Only use --set-ftos ONCE!");
-               parse_ftos(optarg, finfo);
-               *flags = 1;
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "FTOS target: Parameter --set-ftos is required");
-}
-
-static void
-print_ftos(u_int8_t ftos, int numeric)
-{
-       printf("0x%02x ", ftos);
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_target *target,
-      int numeric)
-{
-       const struct ipt_FTOS_info *finfo =
-               (const struct ipt_FTOS_info *)target->data;
-       printf("TOS set ");
-       print_ftos(finfo->ftos, numeric);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
-       const struct ipt_FTOS_info *finfo =
-               (const struct ipt_FTOS_info *)target->data;
-
-       printf("--set-ftos 0x%02x ", finfo->ftos);
-}
-
-static struct iptables_target ftos = {
-       .next           = NULL,
-       .name           = "FTOS",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_FTOS_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_FTOS_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_target(&ftos);
-}
diff --git a/extensions/libipt_IPMARK.c b/extensions/libipt_IPMARK.c
deleted file mode 100644 (file)
index 3e0942d..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Shared library add-on to iptables to add IPMARK target support.
- * (C) 2003 by Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>
- *
- * based on original MARK target
- * 
- * This program is distributed under the terms of GNU GPL
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_IPMARK.h>
-
-#define IPT_ADDR_USED        1
-#define IPT_AND_MASK_USED    2
-#define IPT_OR_MASK_USED     4
-
-struct ipmarkinfo {
-       struct ipt_entry_target t;
-       struct ipt_ipmark_target_info ipmark;
-};
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"IPMARK target v%s options:\n"
-"  --addr src/dst         use source or destination ip address\n"
-"  --and-mask value       logical AND ip address with this value becomes MARK\n"
-"  --or-mask value        logical OR ip address with this value becomes MARK\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "addr", 1, 0, '1' },
-       { "and-mask", 1, 0, '2' },
-       { "or-mask", 1, 0, '3' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-       struct ipt_ipmark_target_info *ipmarkinfo =
-               (struct ipt_ipmark_target_info *)t->data;
-
-       ipmarkinfo->andmask=0xffffffff;
-       ipmarkinfo->ormask=0;
-
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      struct ipt_entry_target **target)
-{
-       struct ipt_ipmark_target_info *ipmarkinfo
-               = (struct ipt_ipmark_target_info *)(*target)->data;
-
-       switch (c) {
-               char *end;
-       case '1':
-               if(!strcmp(optarg, "src")) ipmarkinfo->addr=IPT_IPMARK_SRC;
-                 else if(!strcmp(optarg, "dst")) ipmarkinfo->addr=IPT_IPMARK_DST;
-                   else exit_error(PARAMETER_PROBLEM, "Bad addr value `%s' - should be `src' or `dst'", optarg);
-               if (*flags & IPT_ADDR_USED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "IPMARK target: Can't specify --addr twice");
-               *flags |= IPT_ADDR_USED;
-               break;
-       
-       case '2':
-               ipmarkinfo->andmask = strtoul(optarg, &end, 0);
-               if (*end != '\0' || end == optarg)
-                       exit_error(PARAMETER_PROBLEM, "Bad and-mask value `%s'", optarg);
-               if (*flags & IPT_AND_MASK_USED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "IPMARK target: Can't specify --and-mask twice");
-               *flags |= IPT_AND_MASK_USED;
-               break;
-       case '3':
-               ipmarkinfo->ormask = strtoul(optarg, &end, 0);
-               if (*end != '\0' || end == optarg)
-                       exit_error(PARAMETER_PROBLEM, "Bad or-mask value `%s'", optarg);
-               if (*flags & IPT_OR_MASK_USED)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "IPMARK target: Can't specify --or-mask twice");
-               *flags |= IPT_OR_MASK_USED;
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-       if (!(flags & IPT_ADDR_USED))
-               exit_error(PARAMETER_PROBLEM,
-                          "IPMARK target: Parameter --addr is required");
-       if (!(flags & (IPT_AND_MASK_USED | IPT_OR_MASK_USED)))
-               exit_error(PARAMETER_PROBLEM,
-                          "IPMARK target: Parameter --and-mask or --or-mask is required");
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_target *target,
-      int numeric)
-{
-       const struct ipt_ipmark_target_info *ipmarkinfo =
-               (const struct ipt_ipmark_target_info *)target->data;
-
-       if(ipmarkinfo->addr == IPT_IPMARK_SRC)
-         printf("IPMARK src");
-       else
-         printf("IPMARK dst");
-       printf(" ip and 0x%lx or 0x%lx", ipmarkinfo->andmask, ipmarkinfo->ormask);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
-       const struct ipt_ipmark_target_info *ipmarkinfo =
-               (const struct ipt_ipmark_target_info *)target->data;
-
-       if(ipmarkinfo->addr == IPT_IPMARK_SRC)
-         printf("--addr=src ");
-       else
-         printf("--addr=dst ");
-       if(ipmarkinfo->andmask != 0xffffffff)
-         printf("--and-mask 0x%lx ", ipmarkinfo->andmask);
-       if(ipmarkinfo->ormask != 0)
-         printf("--or-mask 0x%lx ", ipmarkinfo->ormask);
-}
-
-static struct iptables_target ipmark = { 
-       .next           = NULL,
-       .name           = "IPMARK",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_target(&ipmark);
-}
diff --git a/extensions/libipt_IPMARK.man b/extensions/libipt_IPMARK.man
deleted file mode 100644 (file)
index e4659b0..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-Allows you to mark a received packet basing on its IP address. This
-can replace many mangle/mark entries with only one, if you use
-firewall based classifier.
-
-This target is to be used inside the mangle table, in the PREROUTING,
-POSTROUTING or FORWARD hooks.
-.TP
-.BI "--addr " "src/dst"
-Use source or destination IP address.
-.TP
-.BI "--and-mask " "mask"
-Perform bitwise `and' on the IP address and this mask.
-.TP
-.BI "--or-mask " "mask"
-Perform bitwise `or' on the IP address and this mask.
-.P
-The order of IP address bytes is reversed to meet "human order of bytes":
-192.168.0.1 is 0xc0a80001. At first the `and' operation is performed, then
-`or'.
-
-Examples:
-
-We create a queue for each user, the queue number is adequate
-to the IP address of the user, e.g.: all packets going to/from 192.168.5.2
-are directed to 1:0502 queue, 192.168.5.12 -> 1:050c etc.
-
-We have one classifier rule:
-.IP
-tc filter add dev eth3 parent 1:0 protocol ip fw
-.P
-Earlier we had many rules just like below:
-.IP
-iptables -t mangle -A POSTROUTING -o eth3 -d 192.168.5.2 -j MARK
---set-mark 0x10502
-.IP
-iptables -t mangle -A POSTROUTING -o eth3 -d 192.168.5.3 -j MARK
---set-mark 0x10503
-.P
-Using IPMARK target we can replace all the mangle/mark rules with only one:
-.IP
-iptables -t mangle -A POSTROUTING -o eth3 -j IPMARK --addr=dst
---and-mask=0xffff --or-mask=0x10000
-.P
-On the routers with hundreds of users there should be significant load
-decrease (e.g. twice).
index 5e5d3fd..96cc701 100644 (file)
@@ -143,6 +143,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                                   "Maximum prefix length %u for --log-prefix",
                                   (unsigned int)sizeof(loginfo->prefix) - 1);
 
+               if (strlen(optarg) == 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "No prefix specified for --log-prefix");
+
                if (strlen(optarg) != strlen(strtok(optarg, "\n")))
                        exit_error(PARAMETER_PROBLEM,
                                   "Newlines not allowed in --log-prefix");
index 1c47e97..7ddf23e 100644 (file)
@@ -3,4 +3,11 @@ packet.  It is only valid in the
 .B mangle
 table.  It can for example be used in conjunction with iproute2.
 .TP
-.BI "--set-mark " "mark"
+.BI "--set-mark " "value"
+Set nfmark value
+.TP
+.BI "--and-mark " "value"
+Binary AND the nfmark with value
+.TP
+.BI "--or-mark " "value"
+Binary OR  the nfmark with value
index 7eddcc0..c24bb32 100644 (file)
@@ -6,7 +6,7 @@
 #include <getopt.h>
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter/nf_nat.h>
 
 /* Function which prints out usage message. */
 static void
@@ -15,12 +15,17 @@ help(void)
        printf(
 "MASQUERADE v%s options:\n"
 " --to-ports <port>[-<port>]\n"
-"                              Port (range) to map to.\n\n",
+"                              Port (range) to map to.\n"
+" --random\n"
+"                              Randomize source port.\n"
+"\n"
+,
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
        { "to-ports", 1, 0, '1' },
+       { "random", 0, 0, '2' },
        { 0 }
 };
 
@@ -100,6 +105,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                parse_ports(optarg, mr);
                return 1;
 
+       case '2':
+               mr->range[0].flags |=  IP_NAT_RANGE_PROTO_RANDOM;
+               return 1;
+
        default:
                return 0;
        }
@@ -127,6 +136,9 @@ print(const struct ipt_ip *ip,
                        printf("-%hu", ntohs(r->max.tcp.port));
                printf(" ");
        }
+
+       if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+               printf("random ");
 }
 
 /* Saves the union ipt_targinfo in parsable form to stdout. */
@@ -143,6 +155,9 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
                        printf("-%hu", ntohs(r->max.tcp.port));
                printf(" ");
        }
+
+       if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+               printf("--random ");
 }
 
 static struct iptables_target masq = { NULL,
index e82063c..ea3c8de 100644 (file)
@@ -20,3 +20,11 @@ if the rule also specifies
 .B "-p tcp"
 or
 .BR "-p udp" .
+.TP
+.BR "--random"
+Randomize source port mapping
+If option
+.B "--random"
+is used then port mapping will be randomized (kernel >= 2.6.21).
+.RS
+.PP
diff --git a/extensions/libipt_NETLINK.c b/extensions/libipt_NETLINK.c
deleted file mode 100644 (file)
index 403c413..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Provides a NETLINK target, identical to that of the ipchains -o flag */
-/* AUTHOR: Gianni Tedesco <gianni@ecsc.co.uk> */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_NETLINK.h>
-
-static void help(void)
-{
-       printf("NETLINK v%s options:\n"
-               " --nldrop              Drop the packet too\n"
-               " --nlmark <number>     Mark the packet\n"
-               " --nlsize <bytes>      Limit packet size\n",
-              IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       {"nldrop", 0, 0, 'd'},
-       {"nlmark", 1, 0, 'm'},
-       {"nlsize", 1, 0, 's'},
-       {0}
-};
-
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-       struct ipt_nldata *nld = (struct ipt_nldata *) t->data;
-       
-       nld->flags=0;
-       
-}
-
-/* Parse command options */
-static int parse(int c, char **argv, int invert, unsigned int *flags,
-                const struct ipt_entry *entry,
-                struct ipt_entry_target **target)
-{
-       struct ipt_nldata *nld=(struct ipt_nldata *)(*target)->data;
-
-       switch (c) {
-               case 'd':
-                       if (MASK(*flags, USE_DROP))
-                               exit_error(PARAMETER_PROBLEM,
-                               "Can't specify --nldrop twice");
-
-                       if ( check_inverse(optarg, &invert, NULL, 0) ) {
-                               MASK_UNSET(nld->flags, USE_DROP);
-                       } else {
-                               MASK_SET(nld->flags, USE_DROP);
-                       }
-
-                       MASK_SET(*flags, USE_DROP);                     
-
-                       break;
-               case 'm':
-                       if (MASK(*flags, USE_MARK))
-                               exit_error(PARAMETER_PROBLEM,
-                               "Can't specify --nlmark twice");
-
-                       if (check_inverse(optarg, &invert, NULL, 0)) {
-                               MASK_UNSET(nld->flags, USE_MARK);
-                       }else{
-                               MASK_SET(nld->flags, USE_MARK);
-                               nld->mark=atoi(optarg);
-                       }
-
-                       MASK_SET(*flags, USE_MARK);
-                       break;
-               case 's':
-                       if (MASK(*flags, USE_SIZE))
-                               exit_error(PARAMETER_PROBLEM,
-                               "Can't specify --nlsize twice");
-
-                       if ( atoi(optarg) <= 0 )
-                               exit_error(PARAMETER_PROBLEM,
-                               "--nlsize must be larger than zero");
-                       
-
-                       if (check_inverse(optarg, &invert, NULL, 0)) {
-                               MASK_UNSET(nld->flags, USE_SIZE);
-                       }else{
-                               MASK_SET(nld->flags, USE_SIZE);
-                               nld->size=atoi(optarg);
-                       }
-                       MASK_SET(*flags, USE_SIZE);
-                       break;
-
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static void final_check(unsigned int flags)
-{
-       /* ?? */
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip,
-                const struct ipt_entry_target *target)
-{
-       const struct ipt_nldata *nld
-           = (const struct ipt_nldata *) target->data;
-
-       if ( MASK(nld->flags, USE_DROP) )
-               printf("--nldrop ");
-
-       if ( MASK(nld->flags, USE_MARK) )
-               printf("--nlmark %i ", nld->mark);
-
-       if ( MASK(nld->flags, USE_SIZE) )
-               printf("--nlsize %i ", nld->size);              
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_target *target, int numeric)
-{
-       const struct ipt_nldata *nld
-           = (const struct ipt_nldata *) target->data;
-
-       if ( MASK(nld->flags, USE_DROP) )
-               printf("nldrop ");
-
-       if ( MASK(nld->flags, USE_MARK) )
-               printf("nlmark %i ", nld->mark);
-
-       if ( MASK(nld->flags, USE_SIZE) )
-               printf("nlsize %i ", nld->size);
-}
-
-static struct iptables_target netlink = {
-       .next           = NULL,
-       .name           = "NETLINK",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_nldata)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_nldata)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_target(&netlink);
-}
-
index a39c731..4b4b14d 100644 (file)
@@ -9,7 +9,7 @@
 #include <getopt.h>
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter/nf_nat.h>
 
 #define MODULENAME "NETMAP"
 
@@ -86,7 +86,7 @@ parse_to(char *arg, struct ip_nat_range *range)
        range->min_ip = ip->s_addr;
        if (slash) {
                if (strchr(slash+1, '.')) {
-                       ip = dotted_to_addr(slash+1);
+                       ip = dotted_to_mask(slash+1);
                        if (!ip)
                                exit_error(PARAMETER_PROBLEM, "Bad netmask `%s'\n",
                                           slash+1);
diff --git a/extensions/libipt_NFLOG.c b/extensions/libipt_NFLOG.c
new file mode 100644 (file)
index 0000000..ae5c62a
--- /dev/null
@@ -0,0 +1,161 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <iptables.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/xt_NFLOG.h>
+
+enum {
+       NFLOG_GROUP     = 0x1,
+       NFLOG_PREFIX    = 0x2,
+       NFLOG_RANGE     = 0x4,
+       NFLOG_THRESHOLD = 0x8,
+};
+
+static struct option opts[] = {
+       { "nflog-group",     1, 0, NFLOG_GROUP },
+       { "nflog-prefix",    1, 0, NFLOG_PREFIX },
+       { "nflog-range",     1, 0, NFLOG_RANGE },
+       { "nflog-threshold", 1, 0, NFLOG_THRESHOLD },
+};
+
+static void help(void)
+{
+       printf("NFLOG v%s options:\n"
+              " --nflog-group NUM              NETLINK group used for logging\n"
+              " --nflog-range NUM              Number of byte to copy\n"
+              " --nflog-threshold NUM          Message threshold of in-kernel queue\n"
+              " --nflog-prefix STRING          Prefix string for log messages\n\n",
+              IPTABLES_VERSION);
+}
+
+static void init(struct xt_entry_target *t, unsigned int *nfcache)
+{
+       struct xt_nflog_info *info = (struct xt_nflog_info *)t->data;
+
+       info->group     = 0;
+       info->threshold = XT_NFLOG_DEFAULT_THRESHOLD;
+}
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                const struct ipt_entry *entry,
+                struct xt_entry_target **target)
+{
+       struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data;
+       int n;
+
+       switch (c) {
+       case NFLOG_GROUP:
+               if (*flags & NFLOG_GROUP)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-group twice");
+               if (check_inverse(optarg, &invert, NULL, 0))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Unexpected `!' after --nflog-group");
+
+               n = atoi(optarg);
+               if (n < 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "--nflog-group can not be negative");
+               info->group = n;
+               break;
+       case NFLOG_PREFIX:
+               if (*flags & NFLOG_PREFIX)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-prefix twice");
+               if (check_inverse(optarg, &invert, NULL, 0))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Unexpected `!' after --nflog-prefix");
+
+               n = strlen(optarg);
+               if (n == 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "No prefix specified for --nflog-prefix");
+               if (n >= sizeof(info->prefix))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "--nflog-prefix too long, max %Zu characters",
+                                  sizeof(info->prefix) - 1);
+               if (n != strlen(strtok(optarg, "\n")))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Newlines are not allowed in --nflog-prefix");
+               strcpy(info->prefix, optarg);
+               break;
+       case NFLOG_RANGE:
+               if (*flags & NFLOG_RANGE)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-range twice");
+               n = atoi(optarg);
+               if (n < 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid --nflog-range, must be >= 0");
+               info->len = n;
+               break;
+       case NFLOG_THRESHOLD:
+               if (*flags & NFLOG_THRESHOLD)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Can't specify --nflog-threshold twice");
+               n = atoi(optarg);
+               if (n < 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid --nflog-threshold, must be >= 1");
+               info->threshold = n;
+               break;
+       default:
+               return 0;
+       }
+       *flags |= c;
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       return;
+}
+
+static void nflog_print(const struct xt_nflog_info *info, char *prefix)
+{
+       if (info->prefix[0] != '\0')
+               printf("%snflog-prefix \"%s\" ", prefix, info->prefix);
+       if (info->group)
+               printf("%snflog-group %u ", prefix, info->group);
+       if (info->len)
+               printf("%snflog-range %u ", prefix, info->len);
+       if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
+               printf("%snflog-threshold %u ", prefix, info->threshold);
+}
+
+static void print(const struct ipt_ip *ip, const struct xt_entry_target *target,
+                 int numeric)
+{
+       const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
+
+       nflog_print(info, "");
+}
+
+static void save(const struct ipt_ip *ip, const struct xt_entry_target *target)
+{
+       const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
+
+       nflog_print(info, "--");
+}
+
+static struct iptables_target nflog = {
+       .name           = "NFLOG",
+       .version        = IPTABLES_VERSION,
+       .size           = XT_ALIGN(sizeof(struct xt_nflog_info)),
+       .userspacesize  = XT_ALIGN(sizeof(struct xt_nflog_info)),
+       .help           = help,
+       .init           = init,
+       .parse          = parse,
+       .final_check    = final_check,
+       .print          = print,
+       .save           = save,
+       .extra_opts     = opts,
+};
+
+void _init(void)
+{
+       register_target(&nflog);
+}
index e29bf2f..6b38716 100644 (file)
@@ -6,7 +6,10 @@
 #include <getopt.h>
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter/nf_nat.h>
+
+#define IPT_REDIRECT_OPT_DEST  0x01
+#define IPT_REDIRECT_OPT_RANDOM        0x02
 
 /* Function which prints out usage message. */
 static void
@@ -21,6 +24,7 @@ IPTABLES_VERSION);
 
 static struct option opts[] = {
        { "to-ports", 1, 0, '1' },
+       { "random", 1, 0, '2' },
        { 0 }
 };
 
@@ -44,6 +48,9 @@ parse_ports(const char *arg, struct ip_nat_multi_range *mr)
 
        mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 
+       if (strchr(arg, '.'))
+               exit_error(PARAMETER_PROBLEM, "IP address not permitted\n");
+
        port = atoi(arg);
        if (port == 0 || port > 65535)
                exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", arg);
@@ -98,6 +105,17 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                                   "Unexpected `!' after --to-ports");
 
                parse_ports(optarg, mr);
+               if (*flags & IPT_REDIRECT_OPT_RANDOM)
+                       mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+               *flags |= IPT_REDIRECT_OPT_DEST;
+               return 1;
+
+       case '2':
+               if (*flags & IPT_REDIRECT_OPT_DEST) {
+                       mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+                       *flags |= IPT_REDIRECT_OPT_RANDOM;
+               } else
+                       *flags |= IPT_REDIRECT_OPT_RANDOM;
                return 1;
 
        default:
@@ -126,6 +144,8 @@ print(const struct ipt_ip *ip,
                if (r->max.tcp.port != r->min.tcp.port)
                        printf("-%hu", ntohs(r->max.tcp.port));
                printf(" ");
+               if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+                       printf("random ");
        }
 }
 
@@ -143,6 +163,8 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
                if (r->max.tcp.port != r->min.tcp.port)
                        printf("-%hu", ntohs(r->max.tcp.port));
                printf(" ");
+               if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+                       printf("--random ");
        }
 }
 
index aeca3cb..93e2982 100644 (file)
@@ -17,3 +17,10 @@ if the rule also specifies
 .B "-p tcp"
 or
 .BR "-p udp" .
+.TP
+.BR "--random"
+If option
+.B "--random"
+is used then port mapping will be randomized (kernel >= 2.6.22).
+.RS
+.PP
diff --git a/extensions/libipt_ROUTE.c b/extensions/libipt_ROUTE.c
deleted file mode 100644 (file)
index 360f983..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/* Shared library add-on to iptables to add ROUTE target support.
- * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
- * v 1.11 2004/11/23
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <net/if.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_ROUTE.h>
-
-/* compile IPT_ROUTE_TEE support even if kernel headers are unpatched */
-#ifndef IPT_ROUTE_TEE
-#define IPT_ROUTE_TEE          0x02
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"ROUTE target v%s options:\n"
-"    --oif   \tifname \t\tRoute packet through `ifname' network interface\n"
-"    --iif   \tifname \t\tChange packet's incoming interface to `ifname'\n"
-"    --gw    \tip     \t\tRoute packet via this gateway `ip'\n"
-"    --continue\t     \t\tRoute packet and continue traversing the\n"
-"            \t       \t\trules. Not valid with --iif or --tee.\n"
-"    --tee\t  \t\tDuplicate packet, route the duplicate,\n"
-"            \t       \t\tcontinue traversing with original packet.\n"
-"            \t       \t\tNot valid with --iif or --continue.\n"
-"\n",
-"1.11");
-}
-
-static struct option opts[] = {
-       { "oif", 1, 0, '1' },
-       { "iif", 1, 0, '2' },
-       { "gw", 1, 0, '3' },
-       { "continue", 0, 0, '4' },
-       { "tee", 0, 0, '5' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-       struct ipt_route_target_info *route_info = 
-               (struct ipt_route_target_info*)t->data;
-
-       route_info->oif[0] = '\0';
-       route_info->iif[0] = '\0';
-       route_info->gw = 0;
-       route_info->flags = 0;
-}
-
-
-#define IPT_ROUTE_OPT_OIF      0x01
-#define IPT_ROUTE_OPT_IIF      0x02
-#define IPT_ROUTE_OPT_GW       0x04
-#define IPT_ROUTE_OPT_CONTINUE 0x08
-#define IPT_ROUTE_OPT_TEE      0x10
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      struct ipt_entry_target **target)
-{
-       struct ipt_route_target_info *route_info = 
-               (struct ipt_route_target_info*)(*target)->data;
-
-       switch (c) {
-       case '1':
-               if (*flags & IPT_ROUTE_OPT_OIF)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --oif twice");
-
-               if (*flags & IPT_ROUTE_OPT_IIF)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't use --oif and --iif together");
-
-               if (check_inverse(optarg, &invert, NULL, 0))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unexpected `!' after --oif");
-
-               if (strlen(optarg) > sizeof(route_info->oif) - 1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Maximum interface name length %u",
-                                  sizeof(route_info->oif) - 1);
-
-               strcpy(route_info->oif, optarg);
-               *flags |= IPT_ROUTE_OPT_OIF;
-               break;
-
-       case '2':
-               if (*flags & IPT_ROUTE_OPT_IIF)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --iif twice");
-
-               if (*flags & IPT_ROUTE_OPT_OIF)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't use --iif and --oif together");
-
-               if (check_inverse(optarg, &invert, NULL, 0))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unexpected `!' after --iif");
-
-               if (strlen(optarg) > sizeof(route_info->iif) - 1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Maximum interface name length %u",
-                                  sizeof(route_info->iif) - 1);
-
-               strcpy(route_info->iif, optarg);
-               *flags |= IPT_ROUTE_OPT_IIF;
-               break;
-
-       case '3':
-               if (*flags & IPT_ROUTE_OPT_GW)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --gw twice");
-
-               if (check_inverse(optarg, &invert, NULL, 0))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Unexpected `!' after --gw");
-
-               if (!inet_aton(optarg, (struct in_addr*)&route_info->gw)) {
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Invalid IP address %s",
-                                  optarg);
-               }
-
-               *flags |= IPT_ROUTE_OPT_GW;
-               break;
-
-       case '4':
-               if (*flags & IPT_ROUTE_OPT_CONTINUE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --continue twice");
-               if (*flags & IPT_ROUTE_OPT_TEE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --continue AND --tee");
-
-               route_info->flags |= IPT_ROUTE_CONTINUE;
-               *flags |= IPT_ROUTE_OPT_CONTINUE;
-
-               break;
-
-       case '5':
-               if (*flags & IPT_ROUTE_OPT_TEE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --tee twice");
-               if (*flags & IPT_ROUTE_OPT_CONTINUE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --tee AND --continue");
-
-               route_info->flags |= IPT_ROUTE_TEE;
-               *flags |= IPT_ROUTE_OPT_TEE;
-
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-
-static void
-final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "ROUTE target: oif, iif or gw option required");
-
-       if ((flags & (IPT_ROUTE_OPT_CONTINUE|IPT_ROUTE_OPT_TEE)) && (flags & IPT_ROUTE_OPT_IIF))
-               exit_error(PARAMETER_PROBLEM,
-                          "ROUTE target: can't continue traversing the rules with iif option");
-}
-
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_target *target,
-      int numeric)
-{
-       const struct ipt_route_target_info *route_info
-               = (const struct ipt_route_target_info *)target->data;
-
-       printf("ROUTE ");
-
-       if (route_info->oif[0])
-               printf("oif:%s ", route_info->oif);
-
-       if (route_info->iif[0])
-               printf("iif:%s ", route_info->iif);
-
-       if (route_info->gw) {
-               struct in_addr ip = { route_info->gw };
-               printf("gw:%s ", inet_ntoa(ip));
-       }
-
-       if (route_info->flags & IPT_ROUTE_CONTINUE)
-               printf("continue");
-
-       if (route_info->flags & IPT_ROUTE_TEE)
-               printf("tee");
-
-}
-
-
-static void save(const struct ipt_ip *ip, 
-                const struct ipt_entry_target *target)
-{
-       const struct ipt_route_target_info *route_info
-               = (const struct ipt_route_target_info *)target->data;
-
-       if (route_info->oif[0])
-               printf("--oif %s ", route_info->oif);
-
-       if (route_info->iif[0])
-               printf("--iif %s ", route_info->iif);
-
-       if (route_info->gw) {
-               struct in_addr ip = { route_info->gw };
-               printf("--gw %s ", inet_ntoa(ip));
-       }
-
-       if (route_info->flags & IPT_ROUTE_CONTINUE)
-               printf("--continue ");
-
-       if (route_info->flags & IPT_ROUTE_TEE)
-               printf("--tee ");
-}
-
-
-static struct iptables_target route = { 
-       .next           = NULL,
-       .name           = "ROUTE",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_route_target_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_route_target_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_target(&route);
-}
diff --git a/extensions/libipt_ROUTE.man b/extensions/libipt_ROUTE.man
deleted file mode 100644 (file)
index 8a36e8e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-This is used to explicitly override the core network stack's routing decision.
-.B mangle
-table.
-.TP
-.BI "--oif " "ifname"
-Route the packet through `ifname' network interface
-.TP
-.BI "--iif " "ifname"
-Change the packet's incoming interface to `ifname'
-.TP
-.BI "--gw " "IP_address"
-Route the packet via this gateway
-.TP
-.BI "--continue "
-Behave like a non-terminating target and continue traversing the rules.  Not valid in combination with `--iif' or `--tee'
-.TP
-.BI "--tee "
-Make a copy of the packet, and route that copy to the given destination. For the original, uncopied packet, behave like a non-terminating target and continue traversing the rules.  Not valid in combination with `--iif' or `--continue'
index 4eda223..7211f60 100644 (file)
@@ -6,7 +6,7 @@
 #include <getopt.h>
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter/nf_nat.h>
 /* For 64bit kernel / 32bit userspace */
 #include "../include/linux/netfilter_ipv4/ipt_SAME.h"
 
@@ -22,13 +22,17 @@ help(void)
 "                                once for multiple ranges.\n"
 " --nodst\n"
 "                              Don't use destination-ip in\n"
-"                                         source selection\n",
+"                                         source selection\n"
+" --random\n"
+"                              Randomize source port\n"
+,
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
        { "to", 1, 0, '1' },
        { "nodst", 0, 0, '2'},
+       { "random", 0, 0, '3' },
        { 0 }
 };
 
@@ -79,6 +83,7 @@ parse_to(char *arg, struct ip_nat_range *range)
 
 #define IPT_SAME_OPT_TO                        0x01
 #define IPT_SAME_OPT_NODST             0x02
+#define IPT_SAME_OPT_RANDOM            0x04
 
 /* Function which parses command options; returns true if it
    ate an option */
@@ -89,6 +94,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
 {
        struct ipt_same_info *mr
                = (struct ipt_same_info *)(*target)->data;
+       int count;
 
        switch (c) {
        case '1':
@@ -102,6 +108,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                                   "Unexpected `!' after --to");
 
                parse_to(optarg, &mr->range[mr->rangesize]);
+               /* WTF do we need this for? */
+               if (*flags & IPT_SAME_OPT_RANDOM)
+                       mr->range[mr->rangesize].flags 
+                               |= IP_NAT_RANGE_PROTO_RANDOM;
                mr->rangesize++;
                *flags |= IPT_SAME_OPT_TO;
                break;
@@ -114,7 +124,13 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                mr->info |= IPT_SAME_NODST;
                *flags |= IPT_SAME_OPT_NODST;
                break;
-               
+
+       case '3':       
+               *flags |= IPT_SAME_OPT_RANDOM;
+               for (count=0; count < mr->rangesize; count++)
+                       mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+               break;
+
        default:
                return 0;
        }
@@ -139,6 +155,7 @@ print(const struct ipt_ip *ip,
        int count;
        struct ipt_same_info *mr
                = (struct ipt_same_info *)target->data;
+       int random = 0;
        
        printf("same:");
        
@@ -155,10 +172,15 @@ print(const struct ipt_ip *ip,
                        printf(" ");
                else
                        printf("-%s ", addr_to_dotted(&a));
+               if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 
+                       random = 1;
        }
        
        if (mr->info & IPT_SAME_NODST)
                printf("nodst ");
+
+       if (random)
+               printf("random ");
 }
 
 /* Saves the union ipt_targinfo in parsable form to stdout. */
@@ -168,6 +190,7 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
        int count;
        struct ipt_same_info *mr
                = (struct ipt_same_info *)target->data;
+       int random = 0;
 
        for (count = 0; count < mr->rangesize; count++) {
                struct ip_nat_range *r = &mr->range[count];
@@ -181,10 +204,15 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
                        printf(" ");
                else
                        printf("-%s ", addr_to_dotted(&a));
+               if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 
+                       random = 1;
        }
        
        if (mr->info & IPT_SAME_NODST)
                printf("--nodst ");
+
+       if (random)
+               printf("--random ");
 }
 
 static struct iptables_target same = {
index 817c200..4e88d48 100644 (file)
@@ -9,3 +9,7 @@ multiple ranges.
 .B "--nodst"
 Don't use the destination-ip in the calculations when selecting the
 new source-ip
+.TP
+.B "--random"
+Port mapping will be forcely randomized to avoid attacks based on 
+port prediction (kernel >= 2.6.21).
diff --git a/extensions/libipt_SECMARK.c b/extensions/libipt_SECMARK.c
new file mode 100644 (file)
index 0000000..89a2b2a
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Shared library add-on to iptables to add SECMARK target support.
+ *
+ * Based on the MARK target.
+ *
+ * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <iptables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+#define PFX "SECMARK target: "
+
+static void help(void)
+{
+       printf(
+"SECMARK target v%s options:\n"
+"  --selctx value                     Set the SELinux security context\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "selctx", 1, 0, '1' },
+       { 0 }
+};
+
+/* Initialize the target. */
+static void init(struct ipt_entry_target *t, unsigned int *nfcache)
+{ }
+
+/*
+ * Function which parses command options; returns true if it
+ * ate an option.
+ */
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                 const struct ipt_entry *entry, struct ipt_entry_target **target)
+{
+       struct xt_secmark_target_info *info =
+               (struct xt_secmark_target_info*)(*target)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & SECMARK_MODE_SEL)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Can't specify --selctx twice");
+               info->mode = SECMARK_MODE_SEL;
+
+               if (strlen(optarg) > SECMARK_SELCTX_MAX-1)
+                       exit_error(PARAMETER_PROBLEM, PFX
+                                  "Maximum length %u exceeded by --selctx"
+                                  " parameter (%zu)",
+                                  SECMARK_SELCTX_MAX-1, strlen(optarg));
+
+               strcpy(info->u.sel.selctx, optarg);
+               *flags |= SECMARK_MODE_SEL;
+               break;
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM, PFX "parameter required");
+}
+
+static void print_secmark(struct xt_secmark_target_info *info)
+{
+       switch (info->mode) {
+       case SECMARK_MODE_SEL:
+               printf("selctx %s ", info->u.sel.selctx);\
+               break;
+       
+       default:
+               exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+       }
+}
+
+static void print(const struct ipt_ip *ip,
+                 const struct ipt_entry_target *target, int numeric)
+{
+       struct xt_secmark_target_info *info =
+               (struct xt_secmark_target_info*)(target)->data;
+
+       printf("SECMARK ");
+       print_secmark(info);
+}
+
+/* Saves the target info in parsable form to stdout. */
+static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+       struct xt_secmark_target_info *info =
+               (struct xt_secmark_target_info*)target->data;
+
+       printf("--");
+       print_secmark(info);
+}
+
+static struct iptables_target secmark = {
+       .next           = NULL,
+       .name           = "SECMARK",
+       .version        = IPTABLES_VERSION,
+       .revision       = 0,
+       .size           = IPT_ALIGN(sizeof(struct xt_secmark_target_info)),
+       .userspacesize  = IPT_ALIGN(sizeof(struct xt_secmark_target_info)),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target(&secmark);
+}
diff --git a/extensions/libipt_SECMARK.man b/extensions/libipt_SECMARK.man
new file mode 100644 (file)
index 0000000..f892de9
--- /dev/null
@@ -0,0 +1,7 @@
+This is used to set the security mark value associated with the
+packet for use by security subsystems such as SELinux.  It is only
+valid in the
+.B mangle
+table.
+.TP
+.BI "--selctx " "security_context"
index d11a9f0..1d8ace6 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_set.h>
 #include <linux/netfilter_ipv4/ipt_set.h>
 #include "libipt_set.h"
index 867c9d0..0a665a0 100644 (file)
@@ -6,7 +6,10 @@
 #include <getopt.h>
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter/nf_nat.h>
+
+#define IPT_SNAT_OPT_SOURCE 0x01
+#define IPT_SNAT_OPT_RANDOM 0x02
 
 /* Source NAT data consists of a multi-range, indicating where to map
    to. */
@@ -24,12 +27,14 @@ help(void)
 "SNAT v%s options:\n"
 " --to-source <ipaddr>[-<ipaddr>][:port-port]\n"
 "                              Address to map source to.\n"
-"                              (You can use this more than once)\n\n",
+"[--random]\n"
+"\n",
 IPTABLES_VERSION);
 }
 
 static struct option opts[] = {
        { "to-source", 1, 0, '1' },
+       { "random", 0, 0, '2' },
        { 0 }
 };
 
@@ -155,7 +160,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                        exit_error(PARAMETER_PROBLEM,
                                   "Unexpected `!' after --to-source");
 
-               if (*flags) {
+               if (*flags & IPT_SNAT_OPT_SOURCE) {
                        if (!kernel_version)
                                get_kernel_version();
                        if (kernel_version > LINUX_VERSION(2, 6, 10))
@@ -163,7 +168,18 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                                           "Multiple --to-source not supported");
                }
                *target = parse_to(optarg, portok, info);
-               *flags = 1;
+               /* WTF do we need this for?? */
+               if (*flags & IPT_SNAT_OPT_RANDOM)
+                       info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+               *flags |= IPT_SNAT_OPT_SOURCE;
+               return 1;
+
+       case '2':
+               if (*flags & IPT_SNAT_OPT_SOURCE) {
+                       info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+                       *flags |= IPT_SNAT_OPT_RANDOM;
+               } else
+                       *flags |= IPT_SNAT_OPT_RANDOM;
                return 1;
 
        default:
@@ -174,7 +190,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
 /* Final check; must have specfied --to-source. */
 static void final_check(unsigned int flags)
 {
-       if (!flags)
+       if (!(flags & IPT_SNAT_OPT_SOURCE))
                exit_error(PARAMETER_PROBLEM,
                           "You must specify --to-source");
 }
@@ -212,6 +228,8 @@ print(const struct ipt_ip *ip,
        for (i = 0; i < info->mr.rangesize; i++) {
                print_range(&info->mr.range[i]);
                printf(" ");
+               if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+                       printf("random ");
        }
 }
 
@@ -226,6 +244,8 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
                printf("--to-source ");
                print_range(&info->mr.range[i]);
                printf(" ");
+               if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+                       printf("--random ");
        }
 }
 
index 2d9427f..7b34799 100644 (file)
@@ -17,12 +17,18 @@ or
 If no port range is specified, then source ports below 512 will be
 mapped to other ports below 512: those between 512 and 1023 inclusive
 will be mapped to ports below 1024, and other ports will be mapped to
-1024 or above. Where possible, no port alteration will occur.
-.RS
-.PP
+1024 or above. Where possible, no port alteration will
+
 In Kernels up to 2.6.10, you can add several --to-source options.  For those
 kernels, if you specify more than one source address, either via an address
 range or multiple --to-source options, a simple round-robin (one after another
 in cycle) takes place between these addresses.
 Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
 anymore.
+.TP
+.BR "--random"
+If option
+.B "--random"
+is used then port mapping will be randomized (kernel >= 2.6.21).
+.RS
+.PP
diff --git a/extensions/libipt_TCPLAG.c b/extensions/libipt_TCPLAG.c
deleted file mode 100644 (file)
index 3042d73..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* libipt_TCPLAG.c -- module for iptables to interface with TCPLAG target
- * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Shared library add-on to iptables for TCPLAG target control
- *
- * This allows installation and removal of the TCPLAG target
- * Note that there is a lot more commentary in this file than
- * the average libipt target (i.e. more than none) but these
- * are just my deductions based on examination of the source
- * and 
- */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
-
-/*
- * This merely dumps out text for the user
- * (saves keeping the manpage up to date)
- */
-static void help( void )
-{
-       printf( "TCPLAG options:\n"
-                       " --log-level=n    Set the syslog level to n (integer 0 to 7)\n\n"
-                       " --log-prefix=xx  Prefix log messages with xx\n" );
-}
-
-/*
- * See "man getopt_long" for an explanation of this structure
- *
- * If one of our options DOES happen to come up then we get
- * a callback into parse(), our vals must not overlap with any
- * normal iptables short options (I think) because there is only
- * one actual options handler and it can't tell whose options it
- * is really looking at unless they are all distinct.
- *
- * These are exactly the same as the LOG target options
- * and have the same purpose.
- */
-static const struct option opts[] =
-{
-       { "log-level",     1, 0, '!' },
-       { "log-prefix",    1, 0, '#' },
-       { 0 }
-};
-
-/*
- * This gives us a chance to install some initial values in
- * our own private data structure (which is at t->data).
- * Probably we could fiddle with t->tflags too but there is
- * no great advantage in doing so.
- */
-static void init( struct ipt_entry_target *t, unsigned int *nfcache )
-{
-       struct ipt_tcplag *el = (struct ipt_tcplag *)t->data;
-       memset( el, 0, sizeof( struct ipt_tcplag ));
-       el->level = 4; /* Default to warning level */
-       strcpy( el->prefix, "TCPLAG:" ); /* Give a reasonable default prefix */
-}
-
-/*
- * It doesn't take much thought to see how little thought has gone into
- * this particular API. However, to add to that I'd just like to say that
- * it can be made to work and small miracles are still miracles.
- *
- * The input parameters are as follows:
- * 
- *  c      --  the 'val' from opts[] above, could possibly be something
- *             we cannot recognise in which case return(0).
- *             If we do recognise it then return(1).
- *
- *  argv   --  in case we want to take parameters from the command line,
- *             not sure how to safely ensure that the parameter that
- *             we want to take will really exist, presumably getopt_long()
- *             will have already checked such things (what about optional
- *             parameters huh?).
- *
- *  invert --  if the option parameter had '!' in front of it, usually this
- *             would inversion of the matching sense but I don't think it
- *             is useful in the case of targets.
- *
- *  flags  --  always (*target)->tflags for those who feel it is better
- *             to access this field indirectly <shrug> starts of
- *             zero for a fresh target, gets fed into final_check().
- *
- *  entry  --  apparently useless
- *
- *  target --  the record that holds data about this target,
- *             most importantly, our private data is (*target)->data
- *             (this has already been malloced for us).
- */
-static int parse( int c, char **argv, int invert, unsigned int *flags,
-                                 const struct ipt_entry *entry, struct ipt_entry_target **target )
-{
-       struct ipt_tcplag *el = (struct ipt_tcplag *)( *target )->data;
-/*
- * Yeah, we could complain about options being issued twice but
- * is it really worth the trouble? Will it make the world a better place?
- */
-       switch( c )
-       {
-/*
- * I really can't be bothered with the syslog naming convention,
- * it isn't terribly useful anyhow.
- */
-               case '!':
-                       el->level = strtol( optarg, 0, 10 );
-                       return( 1 );
-/*
- * 15 chars should be plenty
- */
-               case '#':
-                       strncpy( el->prefix, optarg, 15 );
-                       el->prefix[ 14 ] = 0; /* Force termination */
-                       return( 1 );
-       }
-       return( 0 );
-}
-
-/*
- * This gets given the (*target)->tflags value from
- * the parse() above and it gets called after all the
- * parsing of options is completed. Thus if one option
- * requires another option you can test the flags and
- * decide whether everything is in order.
- *
- * If there is a problem then do something like:
- *             exit_error( PARAMETER_PROBLEM, "foobar parameters detected in TCPLAG target");
- *
- * In this case, no errors are possible
- */
-static void final_check( unsigned int flags ) { }
-/*
- * This print is for the purpose of user-readable display
- * such as what "iptables -L" would give. The notes in
- * iptables.h say that target could possibly be a null pointer
- * but coding of the various libipt_XX.c modules suggests
- * that it is safe to presume target is correctly initialised.
- */
-static void print(const struct ipt_ip *ip, const struct ipt_entry_target *target, int numeric)
-{
-       const struct ipt_tcplag *el = (const struct ipt_tcplag *)target->data;
-       printf("TCPLAG <%d>", el->level );
-       if( el->prefix[ 0 ])
-       {
-               printf( "%s", el->prefix );
-       }
-}
-
-/*
- * As above but command-line style printout
- * (machine-readable for restoring table)
- */
-static void save( const struct ipt_ip *ip, const struct ipt_entry_target *target )
-{
-       const struct ipt_tcplag *el = (const struct ipt_tcplag *)target->data;
-       printf("TCPLAG --log-level=%d", el->level );
-       if( el->prefix[ 0 ])
-       {
-/*
- * FIXME: Should have smarter quoting
- */
-               printf( " --log-prefix='%s'", el->prefix );
-       }
-}
-
-/*
- * The version must match the iptables version exactly
- * which is a big pain, could use `iptables -V` in makefile
- * but we can't guarantee compatibility with all iptables
- * so we are stuck with only supporting one particular version.
- */
-static struct iptables_target targ =
-{
-next:            0,
-name:             "TCPLAG",
-version:          IPTABLES_VERSION,
-size:             IPT_ALIGN( sizeof( struct ipt_tcplag )),
-userspacesize:    IPT_ALIGN( sizeof( struct ipt_tcplag )),
-help:             &help,
-init:             &init,
-parse:            &parse,
-final_check:      &final_check,
-print:            &print,
-save:             &save,
-extra_opts:       opts
-};
-
-/*
- * Always nervous trusting _init() but oh well that is the standard
- * so have to go ahead and use it. This registers your target into
- * the list of available targets so that your options become available.
- */
-void _init( void ) { register_target( &targ ); }
diff --git a/extensions/libipt_TRACE.c b/extensions/libipt_TRACE.c
deleted file mode 100644 (file)
index 7217999..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Shared library add-on to iptables to add TRACE target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"TRACE target v%s takes no options\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      struct ipt_entry_target **target)
-{
-       return 0;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-static
-struct iptables_target trace
-= {    .next = NULL,
-       .name = "TRACE",
-       .version = IPTABLES_VERSION,
-       .size = IPT_ALIGN(0),
-       .userspacesize = IPT_ALIGN(0),
-       .help = &help,
-       .init = &init,
-       .parse = &parse,
-       .final_check = &final_check,
-       .print = NULL, /* print */
-       .save = NULL, /* save */
-       .extra_opts = opts
-};
-
-void _init(void)
-{
-       register_target(&trace);
-}
diff --git a/extensions/libipt_TRACE.man b/extensions/libipt_TRACE.man
deleted file mode 100644 (file)
index 549ab33..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-This target has no options.  It just turns on 
-.B packet tracing
-for all packets that match this rule.
index f4b7a14..a73b685 100644 (file)
@@ -110,6 +110,14 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
                                   "Maximum prefix length %u for --ulog-prefix",
                                   (unsigned int)sizeof(loginfo->prefix) - 1);
 
+               if (strlen(optarg) == 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "No prefix specified for --ulog-prefix");
+
+               if (strlen(optarg) != strlen(strtok(optarg, "\n")))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Newlines not allowed in --ulog-prefix");
+
                strcpy(loginfo->prefix, optarg);
                *flags |= IPT_LOG_OPT_PREFIX;
                break;
diff --git a/extensions/libipt_XOR.c b/extensions/libipt_XOR.c
deleted file mode 100644 (file)
index 2397916..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Shared library add-on to iptables for the XOR target
- * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
- * Based on libipt_TTL.c
- *
- * Version 1.0
- *
- * This program is distributed under the terms of GNU GPL
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_XOR.h>
-
-#define        IPT_KEY_SET             1
-#define IPT_BLOCKSIZE_SET      2
-
-static void init(struct ipt_entry_target *t, unsigned int *nfcache) 
-{
-}
-
-static void help(void) 
-{
-       printf(
-               "XOR target v%s options\n"
-               "  --key string           Set key to \"string\"\n"
-               "  --block-size           Set block size\n",
-               IPTABLES_VERSION);
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
-               const struct ipt_entry *entry, 
-               struct ipt_entry_target **target)
-{
-       struct ipt_XOR_info *info = (struct ipt_XOR_info *) (*target)->data;
-       
-       if (!optarg)
-               exit_error(PARAMETER_PROBLEM, "XOR: too few arguments");
-       
-       if (check_inverse(optarg, &invert, NULL, 0))
-               exit_error(PARAMETER_PROBLEM, "XOR: unexpected '!'");
-
-       switch (c) {    
-               case '1':
-                       strncpy(info->key, optarg, 30);
-                       info->key[29] = '\0';
-                       *flags |= IPT_KEY_SET;
-                       break;
-               case '2':
-                       info->block_size = atoi(optarg);
-                       *flags |= IPT_BLOCKSIZE_SET;
-                       break;
-               default:
-                       return 0;
-       }
-       
-       return 1;
-}
-
-static void final_check(unsigned int flags)
-{
-       if (!(flags & IPT_KEY_SET))
-               exit_error(PARAMETER_PROBLEM, "XOR: You must specify a key");
-       if (!(flags & IPT_BLOCKSIZE_SET))
-               exit_error(PARAMETER_PROBLEM, "XOR: You must specify a block-size");
-}
-
-static void save (const struct ipt_ip *ip,
-               const struct ipt_entry_target *target)
-{
-       const struct ipt_XOR_info *info = (struct ipt_XOR_info *) target->data;
-
-       printf("--key %s ", info->key);
-       printf("--block-size %u ", info->block_size);
-}
-
-static void print (const struct ipt_ip *ip,
-       const struct ipt_entry_target *target, int numeric)
-{
-       const struct ipt_XOR_info *info = (struct ipt_XOR_info *) target->data;
-
-       printf("key: %s ", info->key);
-       printf("block-size: %u ", info->block_size);
-}
-
-static struct option opts[] = {
-       { "key", 1, 0, '1' },
-       { "block-size", 1, 0, '2' },
-       { 0 }
-};
-
-static struct iptables_target XOR = {
-       .next           = NULL, 
-       .name           = "XOR",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_XOR_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_XOR_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts 
-};
-
-void _init(void)
-{
-       register_target(&XOR);
-}
diff --git a/extensions/libipt_XOR.man b/extensions/libipt_XOR.man
deleted file mode 100644 (file)
index 712b472..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Encrypt TCP and UDP traffic using a simple XOR encryption
-.TP
-.BI "--key " "string"
-Set key to "string"
-.TP
-.BI "--block-size"
-Set block size
diff --git a/extensions/libipt_account.c b/extensions/libipt_account.c
deleted file mode 100644 (file)
index d049a03..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/* 
- * accounting match helper (libipt_account.c)
- * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
- *
- * Version: 0.1.6
- *
- * This software is distributed under the terms of GNU GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <iptables.h>
-#include <string.h>
-#include <getopt.h>
-
-#include <linux/netfilter_ipv4/ipt_account.h>
-
-#ifndef HIPQUAD
-#define HIPQUAD(addr) \
-       ((unsigned char *)&addr)[3], \
-       ((unsigned char *)&addr)[2], \
-       ((unsigned char *)&addr)[1], \
-       ((unsigned char *)&addr)[0]
-#endif
-                               
-static void help(void) {
-       printf(
-                       "account v%s options:\n"
-                       "--aaddr network/netmask\n"
-                       "       defines network/netmask for which make statistics.\n"
-                       "--aname name\n"
-                       "       defines name of list where statistics will be kept. If no is\n"
-                       "       specified DEFAULT will be used.\n"
-                       "--ashort\n"
-                       "       table will colect only short statistics (only total counters\n"
-                       "       without splitting it into protocols.\n"
-       , 
-       IPTABLES_VERSION);
-};
-
-static struct option opts[] = {
-       { .name = "aaddr",  .has_arg = 1, .flag = NULL, .val = 201 },
-       { .name = "aname",  .has_arg = 1, .flag = NULL, .val = 202 },
-       { .name = "ashort", .has_arg = 0, .flag = NULL, .val = 203 },
-       { .name = 0, .has_arg = 0, .flag = 0, .val = 0 }
-};
-
-/* Helper functions for parse_network */
-int parseip(const char *parameter, u_int32_t *ip) {
-       
-       char buffer[16], *bufferptr, *dot;
-       unsigned int i, shift, part;
-
-       if (strlen(parameter) > 15)
-               return 0;
-
-       strncpy(buffer, parameter, 15);
-       buffer[15] = 0;
-
-       bufferptr = buffer;
-
-       for (i = 0, shift = 24, *ip = 0; i < 3; i++, shift -= 8) {
-               /* no dot */
-               if ((dot = strchr(bufferptr, '.')) == NULL)
-                       return 0;
-               /* not a number */
-               if ((part = strtol(bufferptr, (char**)NULL, 10)) < 0) 
-                       return 0;       
-               /* to big number */
-               if (part > 255)
-                       return 0;
-               *ip |= part << shift;           
-               bufferptr = dot + 1;
-       }
-       /* not a number */
-       if ((part = strtol(bufferptr, (char**)NULL, 10)) < 0) 
-               return 0;
-       /* to big number */
-       if (part > 255)
-               return 0;
-       *ip |= part;
-       return 1;
-}
-
-static void parsenetwork(const char *parameter, u_int32_t *network) {
-       if (!parseip(parameter, network))
-               exit_error(PARAMETER_PROBLEM, "account: wrong ip in network");
-}
-
-static void parsenetmaskasbits(const char *parameter, u_int32_t *netmask) {
-       
-       u_int32_t bits;
-       
-       if ((bits = strtol(parameter, (char **)NULL, 10)) < 0 || bits > 32)
-               exit_error(PARAMETER_PROBLEM, "account: wrong netmask");
-
-       *netmask = 0xffffffff << (32 - bits);
-}
-
-static void parsenetmaskasip(const char *parameter, u_int32_t *netmask) {
-       if (!parseip(parameter, netmask))
-               exit_error(PARAMETER_PROBLEM, "account: wrong ip in netmask");
-}
-
-static void parsenetmask(const char *parameter, u_int32_t *netmask) 
-{
-       if (strchr(parameter, '.') != NULL)
-               parsenetmaskasip(parameter, netmask);
-       else
-               parsenetmaskasbits(parameter, netmask);
-}
-
-static void parsenetworkandnetmask(const char *parameter, u_int32_t *network, u_int32_t *netmask) 
-{
-       
-       char buffer[32], *slash;
-
-       if (strlen(parameter) > 31)
-               /* text is to long, even for 255.255.255.255/255.255.255.255 */
-               exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
-
-       strncpy(buffer, parameter, 31);
-       buffer[31] = 0;
-
-       /* check whether netmask is given */
-       if ((slash = strchr(buffer, '/')) != NULL) {
-               parsenetmask(slash + 1, netmask);
-               *slash = 0;
-       } else
-               *netmask = 0xffffffff;
-       parsenetwork(buffer, network);
-
-       if ((*network & *netmask) != *network)
-               exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
-}
-
-
-/* Function gets network & netmask from argument after --aaddr */
-static void parse_network(const char *parameter, struct t_ipt_account_info *info) {
-
-       parsenetworkandnetmask(parameter, &info->network, &info->netmask);
-       
-}
-
-/* validate netmask */
-inline int valid_netmask(u_int32_t netmask) {
-       while (netmask & 0x80000000)
-               netmask <<= 1;
-       if (netmask != 0)
-               return 0;
-        return 1;
-}
-
-/* validate network/netmask pair */
-inline int valid_network_and_netmask(struct t_ipt_account_info *info) {
-       if (!valid_netmask(info->netmask))
-               return 0;
-       if ((info->network & info->netmask) != info->network)
-               return 0;
-       return 1;
-}
-
-
-
-/* Function initializes match */
-static void init(struct ipt_entry_match *match, 
-                unsigned int *nfcache) {
-       
-       struct t_ipt_account_info *info = (struct t_ipt_account_info *)(match)->data;
-
-
-       /* set default table name to DEFAULT */
-       strncpy(info->name, "DEFAULT", IPT_ACCOUNT_NAME_LEN);
-       info->shortlisting = 0;
-       
-}
-
-/* Function parses match's arguments */
-static int parse(int c, char **argv, 
-                 int invert, 
-                 unsigned int *flags,
-                  const struct ipt_entry *entry,
-                  unsigned int *nfcache,
-                  struct ipt_entry_match **match) {
-       
-       struct t_ipt_account_info *info = (struct t_ipt_account_info *)(*match)->data;
-
-       switch (c) {
-               
-               /* --aaddr */
-               case 201:
-                       parse_network(optarg, info);
-                       if (!valid_network_and_netmask(info))
-                               exit_error(PARAMETER_PROBLEM, "account: wrong network/netmask");
-                       *flags = 1;
-                       break;
-                       
-               /* --aname */
-               case 202:
-                       if (strlen(optarg) < IPT_ACCOUNT_NAME_LEN)
-                               strncpy(info->name, optarg, IPT_ACCOUNT_NAME_LEN);
-                       else
-                               exit_error(PARAMETER_PROBLEM, "account: Too long table name");                  
-                       break;  
-               /* --ashort */
-               case 203:
-                       info->shortlisting = 1;
-                       break;
-               default:
-                       return 0;                       
-       }
-       return 1;       
-}
-
-/* Final check whether network/netmask was specified */
-static void final_check(unsigned int flags) {
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM, "account: You need specify '--aaddr' parameter");
-}
-
-/* Function used for printing rule with account match for iptables -L */
-static void print(const struct ipt_ip *ip,
-                  const struct ipt_entry_match *match, 
-                 int numeric) {
-       
-       struct t_ipt_account_info *info = (struct t_ipt_account_info *)match->data;
-       
-       printf("account: ");
-       printf("network/netmask: ");
-       printf("%u.%u.%u.%u/%u.%u.%u.%u ",
-                       HIPQUAD(info->network),
-                       HIPQUAD(info->netmask)
-             );
-       
-       printf("name: %s ", info->name);
-       if (info->shortlisting)
-               printf("short-listing ");
-}
-
-/* Function used for saving rule containing account match */
-static void save(const struct ipt_ip *ip, 
-                const struct ipt_entry_match *match) {
-
-       struct t_ipt_account_info *info = (struct t_ipt_account_info *)match->data;
-       
-       printf("--aaddr ");
-       printf("%u.%u.%u.%u/%u.%u.%u.%u ",
-                        HIPQUAD(info->network),
-                        HIPQUAD(info->netmask)
-              );
-       
-       printf("--aname %s ", info->name);
-       if (info->shortlisting)
-               printf("--ashort ");
-}
-       
-static struct iptables_match account = {
-       .next = NULL,
-       .name = "account",
-       .version = IPTABLES_VERSION,
-       .size = IPT_ALIGN(sizeof(struct t_ipt_account_info)),
-       .userspacesize = IPT_ALIGN(sizeof(struct t_ipt_account_info)),
-       .help = &help,
-       .init = &init,
-       .parse = &parse,
-       .final_check = &final_check,
-       .print = &print,
-       .save = &save,
-       .extra_opts = opts
-};
-
-/* Function which registers match */
-void _init(void)
-{
-       register_match(&account);
-}
-       
diff --git a/extensions/libipt_account.man b/extensions/libipt_account.man
deleted file mode 100644 (file)
index fcbb179..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Account traffic for all hosts in defined network/netmask.
-
-Features:
-
-- long (one counter per protocol TCP/UDP/IMCP/Other) and short statistics
-
-- one iptables rule for all hosts in network/netmask
-
-- loading/saving counters (by reading/writting to procfs entries)
-
-.TP
-.BI "--aaddr " "network/netmask"
-defines network/netmask for which make statistics.
-.TP
-.BI "--aname " "name"
-defines name of list where statistics will be kept. If no is
-specified DEFAULT will be used.
-.TP
-.B "--ashort"
-table will colect only short statistics (only total counters
-without splitting it into protocols.
-.P
-Example usage:
-
-account traffic for/to 192.168.0.0/24 network into table mynetwork:
-
-# iptables -A FORWARD -m account --aname mynetwork --aaddr 192.168.0.0/24
-
-account traffic for/to WWW serwer for 192.168.0.0/24 network into table mywwwserver:
-
-# iptables -A INPUT -p tcp --dport 80
-  -m account --aname mywwwserver --aaddr 192.168.0.0/24 --ashort
-
-# iptables -A OUTPUT -p tcp --sport 80
-  -m account --aname mywwwserver --aaddr 192.168.0.0/24 --ashort
-
-read counters:
-
-# cat /proc/net/ipt_account/mynetwork
-# cat /proc/net/ipt_account/mywwwserver
-
-set counters:
-
-# echo "ip = 192.168.0.1 packets_src = 0" > /proc/net/ipt_account/mywwserver
-
-Webpage:
-  http://www.barbara.eu.org/~quaker/ipt_account/
diff --git a/extensions/libipt_childlevel.c b/extensions/libipt_childlevel.c
deleted file mode 100644 (file)
index 1018c9e..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 
-   Shared library add-on to iptables to add layer 7 matching support. 
-
-   http://l7-filter.sf.net
-  
-   By Matthew Strait <quadong@users.sf.net>, Dec 2003.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   as published by the Free Software Foundation; either version
-   2 of the License, or (at your option) any later version.
-   http://www.gnu.org/licenses/gpl.txt
-*/
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <dirent.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_childlevel.h>
-
-/* Function which prints out usage message. */
-static void help(void)
-{
-       printf(
-       "CHILDLEVEL match v%s options:\n"
-       "--level <n>  : Match childlevel n (0 == master)\n",
-       IPTABLES_VERSION);
-       fputc('\n', stdout);
-}
-
-static struct option opts[] = {
-       { .name = "level", .has_arg = 1, .flag = 0, .val = '1' },
-       { .name = 0 }
-};
-
-/* Function which parses command options; returns true if it ate an option */
-static int parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry, unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_childlevel_info *childlevelinfo = 
-               (struct ipt_childlevel_info *)(*match)->data;
-
-       switch (c) {
-       case '1':
-               check_inverse(optarg, &invert, &optind, 0);
-               childlevelinfo->childlevel = atoi(argv[optind-1]);
-               if (invert)
-                       childlevelinfo->invert = 1;
-               *flags = 1;
-               break;
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; must have specified --level. */
-static void final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "CHILDLEVEL match: You must specify `--level'");
-}
-
-static void print_protocol(int n, int invert, int numeric)
-{
-       fputs("childlevel ", stdout);
-       if (invert) fputc('!', stdout);
-       printf("%d ", n);
-}
-
-/* Prints out the matchinfo. */
-static void print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       printf("CHILDLEVEL ");
-
-       print_protocol(((struct ipt_childlevel_info *)match->data)->childlevel,
-                 ((struct ipt_childlevel_info *)match->data)->invert, numeric);
-}
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-        const struct ipt_childlevel_info *info =
-            (const struct ipt_childlevel_info*) match->data;
-
-        printf("--childlevel %s%d ", (info->invert) ? "! ": "", info->childlevel);
-}
-
-static struct iptables_match childlevel = { 
-       .name           = "childlevel",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_childlevel_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_childlevel_info)),
-       .help           = &help,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&childlevel);
-}
diff --git a/extensions/libipt_childlevel.man b/extensions/libipt_childlevel.man
deleted file mode 100644 (file)
index 3d9b355..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-This is an experimental module.  It matches on whether the 
-packet is part of a master connection or one of its children (or grandchildren,
-etc).  For instance, most packets are level 0.  FTP data transfer is level 1.
-.TP
-.BR "--childlevel " "[!] \fIlevel\fP"
index 42e1ab5..f6439c2 100644 (file)
@@ -5,7 +5,7 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
 #include <linux/netfilter_ipv4/ipt_connbytes.h>
 
 /* Function which prints out usage message. */
diff --git a/extensions/libipt_connlimit.c b/extensions/libipt_connlimit.c
deleted file mode 100644 (file)
index 17b4d13..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/* Shared library add-on to iptables to add connection limit support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ipt_connlimit.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"connlimit v%s options:\n"
-"[!] --connlimit-above n               match if the number of existing tcp connections is (not) above n\n"
-" --connlimit-mask n           group hosts using mask\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "connlimit-above", 1, 0, '1' },
-       { "connlimit-mask",  1, 0, '2' },
-       {0}
-};
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)(*match)->data;
-       int i;
-
-       if (0 == (*flags & 2)) {
-               /* set default mask unless we've already seen a mask option */
-               info->mask = htonl(0xFFFFFFFF);
-       }
-
-       switch (c) {
-       case '1':
-               check_inverse(optarg, &invert, &optind, 0);
-               info->limit = atoi(argv[optind-1]);
-               info->inverse = invert;
-               *flags |= 1;
-               break;
-
-       case '2':
-               i = atoi(argv[optind-1]);
-               if ((i < 0) || (i > 32))
-                       exit_error(PARAMETER_PROBLEM,
-                               "--connlimit-mask must be between 0 and 32");
-
-               if (i == 0)
-                       info->mask = 0;
-               else
-                       info->mask = htonl(0xFFFFFFFF << (32 - i));
-               *flags |= 2;
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check */
-static void final_check(unsigned int flags)
-{
-       if (!flags & 1)
-               exit_error(PARAMETER_PROBLEM, "You must specify `--connlimit-above'");
-}
-
-static int
-count_bits(u_int32_t mask)
-{
-       int i, bits;
-
-       for (bits = 0, i = 31; i >= 0; i--) {
-               if (mask & htonl((u_int32_t)1 << i)) {
-                       bits++;
-                       continue;
-               }
-               break;
-       }
-       return bits;
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)match->data;
-
-       printf("#conn/%d %s %d ", count_bits(info->mask),
-              info->inverse ? "<" : ">", info->limit);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       struct ipt_connlimit_info *info = (struct ipt_connlimit_info*)match->data;
-
-       printf("%s--connlimit-above %d ",info->inverse ? "! " : "",info->limit);
-       printf("--connlimit-mask %d ",count_bits(info->mask));
-}
-
-static struct iptables_match connlimit = {
-       .name           = "connlimit",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_connlimit_info)),
-       .userspacesize  = offsetof(struct ipt_connlimit_info,data),
-       .help           = help,
-       .parse          = parse,
-       .final_check    = final_check,
-       .print          = print,
-       .save           = save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&connlimit);
-}
diff --git a/extensions/libipt_connlimit.man b/extensions/libipt_connlimit.man
deleted file mode 100644 (file)
index 404ee32..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Allows you to restrict the number of parallel TCP connections to a
-server per client IP address (or address block).
-.TP
-[\fB!\fR] \fB--connlimit-above \fIn\fR
-match if the number of existing tcp connections is (not) above n
-.TP
-.BI "--connlimit-mask " "bits"
-group hosts using mask
-.P
-Examples:
-.TP
-# allow 2 telnet connections per client host
-iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
-.TP
-# you can also match the other way around:
-iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
-.TP
-# limit the nr of parallel http requests to 16 per class C sized \
-network (24 bit netmask)
-iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16
---connlimit-mask 24 -j REJECT
index 47c5fcb..5abe3c4 100644 (file)
@@ -13,7 +13,7 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
 #include <linux/netfilter_ipv4/ipt_connrate.h>
 
 /* Function which prints out usage message. */
index cdb86c4..2b62a8c 100644 (file)
@@ -9,8 +9,7 @@
 #include <getopt.h>
 #include <ctype.h>
 #include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter/nf_conntrack_common.h>
 /* For 64bit kernel / 32bit userspace */
 #include "../include/linux/netfilter_ipv4/ipt_conntrack.h"
 
index af1d20e..e5782a8 100644 (file)
@@ -56,31 +56,6 @@ static struct option opts[] = {
        { .name = 0 }
 };
 
-static int
-service_to_port(const char *name)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, "dccp")) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-       return -1;
-}
-
-static u_int16_t
-parse_dccp_port(const char *port)
-{
-       unsigned int portnum;
-
-       DEBUGP("%s\n", port);
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid DCCP port/service `%s' specified", port);
-}
-
 static void
 parse_dccp_ports(const char *portstring, 
                 u_int16_t *ports)
@@ -91,14 +66,14 @@ parse_dccp_ports(const char *portstring,
        buffer = strdup(portstring);
        DEBUGP("%s\n", portstring);
        if ((cp = strchr(buffer, ':')) == NULL) {
-               ports[0] = ports[1] = parse_dccp_port(buffer);
+               ports[0] = ports[1] = parse_port(buffer, "dccp");
        }
        else {
                *cp = '\0';
                cp++;
 
-               ports[0] = buffer[0] ? parse_dccp_port(buffer) : 0;
-               ports[1] = cp[0] ? parse_dccp_port(cp) : 0xFFFF;
+               ports[0] = buffer[0] ? parse_port(buffer, "dccp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "dccp") : 0xFFFF;
 
                if (ports[0] > ports[1])
                        exit_error(PARAMETER_PROBLEM,
index 0279670..31adb6c 100644 (file)
@@ -63,7 +63,7 @@ class_to_dscp(const char *name)
 }
 
 
-
+#if 0
 static const char *
 dscp_to_name(unsigned int dscp)
 {
@@ -78,5 +78,5 @@ dscp_to_name(unsigned int dscp)
        exit_error(PARAMETER_PROBLEM,
                        "Invalid DSCP value `%d'\n", dscp);
 }
-
+#endif
 
diff --git a/extensions/libipt_dstlimit.c b/extensions/libipt_dstlimit.c
deleted file mode 100644 (file)
index 3f3b633..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/* iptables match extension for limiting packets per destination
- *
- * (C) 2003 by Harald Welte <laforge@netfilter.org>
- *
- * Development of this code was funded by Astaro AG, http://www.astaro.com/
- *
- * Based on ipt_limit.c by
- * Jérôme de Vivie   <devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne    <rv@wallfire.org>
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <stddef.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_dstlimit.h>
-
-#define IPT_DSTLIMIT_BURST     5
-
-/* miliseconds */
-#define IPT_DSTLIMIT_GCINTERVAL        1000
-#define IPT_DSTLIMIT_EXPIRE    10000
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"dstlimit v%s options:\n"
-"--dstlimit <avg>              max average match rate\n"
-"                                [Packets per second unless followed by \n"
-"                                /sec /minute /hour /day postfixes]\n"
-"--dstlimit-mode <mode>                mode\n"
-"                                      dstip\n"
-"                                      dstip-dstport\n"
-"                                      srcip-dstip\n"
-"                                      srcip-dstip-dstport\n"
-"--dstlimit-name <name>                name for /proc/net/ipt_dstlimit/\n"
-"[--dstlimit-burst <num>]      number to match in a burst, default %u\n"
-"[--dstlimit-htable-size <num>]        number of hashtable buckets\n"
-"[--dstlimit-htable-max <num>] number of hashtable entries\n"
-"[--dstlimit-htable-gcinterval]        interval between garbage collection runs\n"
-"[--dstlimit-htable-expire]    after which time are idle entries expired?\n"
-"\n", IPTABLES_VERSION, IPT_DSTLIMIT_BURST);
-}
-
-static struct option opts[] = {
-       { "dstlimit", 1, 0, '%' },
-       { "dstlimit-burst", 1, 0, '$' },
-       { "dstlimit-htable-size", 1, 0, '&' },
-       { "dstlimit-htable-max", 1, 0, '*' },
-       { "dstlimit-htable-gcinterval", 1, 0, '(' },
-       { "dstlimit-htable-expire", 1, 0, ')' },
-       { "dstlimit-mode", 1, 0, '_' },
-       { "dstlimit-name", 1, 0, '"' },
-       { 0 }
-};
-
-static
-int parse_rate(const char *rate, u_int32_t *val)
-{
-       const char *delim;
-       u_int32_t r;
-       u_int32_t mult = 1;  /* Seconds by default. */
-
-       delim = strchr(rate, '/');
-       if (delim) {
-               if (strlen(delim+1) == 0)
-                       return 0;
-
-               if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
-                       mult = 1;
-               else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
-                       mult = 60;
-               else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
-                       mult = 60*60;
-               else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
-                       mult = 24*60*60;
-               else
-                       return 0;
-       }
-       r = atoi(rate);
-       if (!r)
-               return 0;
-
-       /* This would get mapped to infinite (1/day is minimum they
-           can specify, so we're ok at that end). */
-       if (r / mult > IPT_DSTLIMIT_SCALE)
-               exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
-
-       *val = IPT_DSTLIMIT_SCALE * mult / r;
-       return 1;
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *)m->data;
-
-       r->cfg.burst = IPT_DSTLIMIT_BURST;
-       r->cfg.gc_interval = IPT_DSTLIMIT_GCINTERVAL;
-       r->cfg.expire = IPT_DSTLIMIT_EXPIRE;
-
-}
-
-#define PARAM_LIMIT            0x00000001
-#define PARAM_BURST            0x00000002
-#define PARAM_MODE             0x00000004
-#define PARAM_NAME             0x00000008
-#define PARAM_SIZE             0x00000010
-#define PARAM_MAX              0x00000020
-#define PARAM_GCINTERVAL       0x00000040
-#define PARAM_EXPIRE           0x00000080
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_dstlimit_info *r = 
-                       (struct ipt_dstlimit_info *)(*match)->data;
-       unsigned int num;
-
-       switch(c) {
-       case '%':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (!parse_rate(optarg, &r->cfg.avg))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "bad rate `%s'", optarg);
-               *flags |= PARAM_LIMIT;
-               break;
-
-       case '$':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (string_to_number(optarg, 0, 10000, &num) == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "bad --dstlimit-burst `%s'", optarg);
-               r->cfg.burst = num;
-               *flags |= PARAM_BURST;
-               break;
-       case '&':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                               "bad --dstlimit-htable-size: `%s'", optarg);
-               r->cfg.size = num;
-               *flags |= PARAM_SIZE;
-               break;
-       case '*':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                               "bad --dstlimit-htable-max: `%s'", optarg);
-               r->cfg.max = num;
-               *flags |= PARAM_MAX;
-               break;
-       case '(':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                               "bad --dstlimit-htable-gcinterval: `%s'", 
-                               optarg);
-               /* FIXME: not HZ dependent!! */
-               r->cfg.gc_interval = num;
-               *flags |= PARAM_GCINTERVAL;
-               break;
-       case ')':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
-                       exit_error(PARAMETER_PROBLEM,
-                               "bad --dstlimit-htable-expire: `%s'", optarg);
-               /* FIXME: not HZ dependent */
-               r->cfg.expire = num;
-               *flags |= PARAM_EXPIRE;
-               break;
-       case '_':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (!strcmp(optarg, "dstip"))
-                       r->cfg.mode = IPT_DSTLIMIT_HASH_DIP;
-               else if (!strcmp(optarg, "dstip-destport") ||
-                        !strcmp(optarg, "dstip-dstport"))
-                       r->cfg.mode = IPT_DSTLIMIT_HASH_DIP|IPT_DSTLIMIT_HASH_DPT;
-               else if (!strcmp(optarg, "srcip-dstip"))
-                       r->cfg.mode = IPT_DSTLIMIT_HASH_SIP|IPT_DSTLIMIT_HASH_DIP;
-               else if (!strcmp(optarg, "srcip-dstip-destport") ||
-                        !strcmp(optarg, "srcip-dstip-dstport"))
-                       r->cfg.mode = IPT_DSTLIMIT_HASH_SIP|IPT_DSTLIMIT_HASH_DIP|IPT_DSTLIMIT_HASH_DPT;
-               else
-                       exit_error(PARAMETER_PROBLEM, 
-                               "bad --dstlimit-mode: `%s'\n", optarg);
-               *flags |= PARAM_MODE;
-               break;
-       case '"':
-               if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
-               if (strlen(optarg) == 0)
-                       exit_error(PARAMETER_PROBLEM, "Zero-length name?");
-               strncpy(r->name, optarg, sizeof(r->name));
-               *flags |= PARAM_NAME;
-               break;
-       default:
-               return 0;
-       }
-
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,
-                          "dstlimit does not support invert");
-
-       return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-       if (!(flags & PARAM_LIMIT))
-               exit_error(PARAMETER_PROBLEM,
-                               "You have to specify --dstlimit");
-       if (!(flags & PARAM_MODE))
-               exit_error(PARAMETER_PROBLEM,
-                               "You have to specify --dstlimit-mode");
-       if (!(flags & PARAM_NAME))
-               exit_error(PARAMETER_PROBLEM,
-                               "You have to specify --dstlimit-name");
-}
-
-static struct rates
-{
-       const char *name;
-       u_int32_t mult;
-} rates[] = { { "day", IPT_DSTLIMIT_SCALE*24*60*60 },
-             { "hour", IPT_DSTLIMIT_SCALE*60*60 },
-             { "min", IPT_DSTLIMIT_SCALE*60 },
-             { "sec", IPT_DSTLIMIT_SCALE } };
-
-static void print_rate(u_int32_t period)
-{
-       unsigned int i;
-
-       for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
-               if (period > rates[i].mult
-            || rates[i].mult/period < rates[i].mult%period)
-                       break;
-       }
-
-       printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       struct ipt_dstlimit_info *r = 
-               (struct ipt_dstlimit_info *)match->data;
-       printf("limit: avg "); print_rate(r->cfg.avg);
-       printf("burst %u ", r->cfg.burst);
-       switch (r->cfg.mode) {
-               case (IPT_DSTLIMIT_HASH_DIP):
-                       printf("mode dstip ");
-                       break;
-               case (IPT_DSTLIMIT_HASH_DIP|IPT_DSTLIMIT_HASH_DPT):
-                       printf("mode dstip-dstport ");
-                       break;
-               case (IPT_DSTLIMIT_HASH_SIP|IPT_DSTLIMIT_HASH_DIP):
-                       printf("mode srcip-dstip ");
-                       break;
-               case (IPT_DSTLIMIT_HASH_SIP|IPT_DSTLIMIT_HASH_DIP|IPT_DSTLIMIT_HASH_DPT):
-                       printf("mode srcip-dstip-dstport ");
-                       break;
-       }
-       if (r->cfg.size)
-               printf("htable-size %u ", r->cfg.size);
-       if (r->cfg.max)
-               printf("htable-max %u ", r->cfg.max);
-       if (r->cfg.gc_interval != IPT_DSTLIMIT_GCINTERVAL)
-               printf("htable-gcinterval %u ", r->cfg.gc_interval);
-       if (r->cfg.expire != IPT_DSTLIMIT_EXPIRE)
-               printf("htable-expire %u ", r->cfg.expire);
-}
-
-/* FIXME: Make minimalist: only print rate if not default --RR */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       struct ipt_dstlimit_info *r = 
-               (struct ipt_dstlimit_info *)match->data;
-
-       printf("--dstlimit "); print_rate(r->cfg.avg);
-       if (r->cfg.burst != IPT_DSTLIMIT_BURST)
-               printf("--dstlimit-burst %u ", r->cfg.burst);
-       switch (r->cfg.mode) {
-               case (IPT_DSTLIMIT_HASH_DIP):
-                       printf("--mode dstip ");
-                       break;
-               case (IPT_DSTLIMIT_HASH_DIP|IPT_DSTLIMIT_HASH_DPT):
-                       printf("--mode dstip-dstport ");
-                       break;
-               case (IPT_DSTLIMIT_HASH_SIP|IPT_DSTLIMIT_HASH_DIP):
-                       printf("--mode srcip-dstip ");
-                       break;
-               case (IPT_DSTLIMIT_HASH_SIP|IPT_DSTLIMIT_HASH_DIP|IPT_DSTLIMIT_HASH_DPT):
-                       printf("--mode srcip-dstip-dstport ");
-                       break;
-       }
-       if (r->cfg.size)
-               printf("--dstlimit-htable-size %u ", r->cfg.size);
-       if (r->cfg.max)
-               printf("--dstlimit-htable-max %u ", r->cfg.max);
-       if (r->cfg.gc_interval != IPT_DSTLIMIT_GCINTERVAL)
-               printf("--dstlimit-htable-gcinterval %u", r->cfg.gc_interval);
-       if (r->cfg.expire != IPT_DSTLIMIT_EXPIRE)
-               printf("--dstlimit-htable-expire %u ", r->cfg.expire);
-}
-
-static struct iptables_match dstlimit = { 
-       .next           = NULL,
-       .name           = "dstlimit",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_dstlimit_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_dstlimit_info)),
-       //offsetof(struct ipt_dstlimit_info, prev),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&dstlimit);
-}
diff --git a/extensions/libipt_dstlimit.man b/extensions/libipt_dstlimit.man
deleted file mode 100644 (file)
index 9df00f1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-This module allows you to limit the packet per second (pps) rate on a per
-destination IP or per destination port base.  As opposed to the `limit' match,
-every destination ip / destination port has it's own limit.
-.TP
-THIS MODULE IS DEPRECATED AND HAS BEEN REPLACED BY ``hashlimit''
-.TP
-.BI "--dstlimit " "avg"
-Maximum average match rate (packets per second unless followed by /sec /minute /hour /day postfixes).
-.TP
-.BI "--dstlimit-mode " "mode"
-The limiting hashmode.  Is the specified limit per
-.B dstip, dstip-dstport
-tuple, 
-.B srcip-dstip
-tuple, or per
-.B srcipdstip-dstport
-tuple.
-.TP
-.BI "--dstlimit-name " "name"
-Name for /proc/net/ipt_dstlimit/* file entry
-.TP
-.BI "[" "--dstlimit-burst " "burst" "]"
-Number of packets to match in a burst.  Default: 5
-.TP
-.BI "[" "--dstlimit-htable-size " "size" "]"
-Number of buckets in the hashtable
-.TP
-.BI "[" "--dstlimit-htable-max " "max" "]"
-Maximum number of entries in the hashtable
-.TP
-.BI "[" "--dstlimit-htable-gcinterval " "interval" "]"
-Interval between garbage collection runs of the hashtable (in miliseconds).
-Default is 1000 (1 second).
-.TP
-.BI "[" "--dstlimit-htable-expire " "time"
-After which time are idle entries expired from hashtable (in miliseconds)?
-Default is 10000 (10 seconds).
index 4abfba3..21e912b 100644 (file)
@@ -62,6 +62,9 @@ parse_esp_spis(const char *spistring, u_int32_t *spis)
 
                spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
                spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
+               if (spis[0] > spis[1])
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Invalid ESP spi range: %s", spistring);
        }
        free(buffer);
 }
diff --git a/extensions/libipt_fuzzy.c b/extensions/libipt_fuzzy.c
deleted file mode 100644 (file)
index d574db8..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* 
-   Shared library add-on to iptables to add match support for the fuzzy match.
-   
-   This file is distributed under the terms of the GNU General Public
-   License (GPL). Copies of the GPL can be obtained from:
-   ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-2002-08-07 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
-2003-06-09 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Bug corrections in
-the save function , thanks to information given by Jean-Francois Patenaude .
-
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_fuzzy.h>
-
-
-static void
-help(void)
-{
-       printf(
-"fuzzy v%s options:\n"
-"                      --lower-limit number (in packets per second)\n"
-"                      --upper-limit number\n"
-,IPTABLES_VERSION);
-};
-
-static struct option opts[] = {
-       { "lower-limit", 1 , 0 , '1' } ,
-       { "upper-limit", 1 , 0 , '2' } ,
-       { 0 }
-};
-
-/* Initialize data structures */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-       struct ipt_fuzzy_info *presentinfo = (struct ipt_fuzzy_info *)(m)->data;
-
-       /*
-        * Default rates ( I'll improve this very soon with something based 
-        * on real statistics of the running machine ) .
-       */
-
-       presentinfo->minimum_rate = 1000;
-       presentinfo->maximum_rate = 2000;
-}
-
-#define IPT_FUZZY_OPT_MINIMUM  0x01
-#define IPT_FUZZY_OPT_MAXIMUM  0x02
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-
-struct ipt_fuzzy_info *fuzzyinfo = (struct ipt_fuzzy_info *)(*match)->data;
-
-       u_int32_t num;
-
-       switch (c) {
-
-       case '1':
-               
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,"Can't specify ! --lower-limit");
-
-       if (*flags & IPT_FUZZY_OPT_MINIMUM)
-                     exit_error(PARAMETER_PROBLEM,"Can't specify --lower-limit twice");
-       
-       if (string_to_number(optarg,1,MAXFUZZYRATE,&num) == -1 || num < 1)
-                       exit_error(PARAMETER_PROBLEM,"BAD --lower-limit");
-
-               fuzzyinfo->minimum_rate = num ;
-
-               *flags |= IPT_FUZZY_OPT_MINIMUM;
-               
-               break;
-
-       case '2':
-
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,"Can't specify ! --upper-limit");
-
-       if (*flags & IPT_FUZZY_OPT_MAXIMUM)
-          exit_error(PARAMETER_PROBLEM,"Can't specify --upper-limit twice");
-
-       if (string_to_number(optarg,1,MAXFUZZYRATE,&num) == -1 || num < 1)
-               exit_error(PARAMETER_PROBLEM,"BAD --upper-limit");
-
-               fuzzyinfo->maximum_rate = num ;
-
-               *flags |= IPT_FUZZY_OPT_MAXIMUM;
-
-               break ;
-
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-static void final_check(unsigned int flags)
-{
-}
-
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       const struct ipt_fuzzy_info *fuzzyinfo
-               = (const struct ipt_fuzzy_info *)match->data;
-
-       printf(" fuzzy: lower limit = %u pps - upper limit = %u pps ",fuzzyinfo->minimum_rate,fuzzyinfo->maximum_rate);
-
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_fuzzy_info *fuzzyinfo
-               = (const struct ipt_fuzzy_info *)match->data;
-
-       printf("--lower-limit %u ",fuzzyinfo->minimum_rate);
-       printf("--upper-limit %u ",fuzzyinfo->maximum_rate);
-
-}
-
-static struct iptables_match fuzzy_match = { 
-       .next           = NULL,
-       .name           = "fuzzy",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_fuzzy_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_fuzzy_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&fuzzy_match);
-}
diff --git a/extensions/libipt_fuzzy.man b/extensions/libipt_fuzzy.man
deleted file mode 100644 (file)
index 397727a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-This module matches a rate limit based on a fuzzy logic controller [FLC]
-.TP
-.BI "--lower-limit " "number"
-Specifies the lower limit (in packets per second).
-.TP
-.BI "--upper-limit " "number"
-Specifies the upper limit (in packets per second).
index 1b0a5d4..c8128ec 100644 (file)
@@ -16,8 +16,8 @@ A rate just like the limit match
 .BI "--hashlimit-burst " "num"
 Burst value, just like limit match
 .TP
-.BI "--hashlimit-mode " "destip | destip-destport"
-Limit per IP or per port
+.BI "--hashlimit-mode " "dstip,srcip,dstport,srcport"
+A comma-separated list of objects to take into consideration
 .TP
 .BI "--hashlimit-name " "foo"
 The name for the /proc/net/ipt_hashlimit/foo entry
index 9d45c8c..a6e642a 100644 (file)
@@ -189,11 +189,15 @@ parse(int c, char **argv, int invert, unsigned int *flags,
 
        switch (c) {
        case '1':
+               if (*flags == 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "icmp match: only use --icmp-type once!");
                check_inverse(optarg, &invert, &optind, 0);
                parse_icmp(argv[optind-1], &icmpinfo->type, 
                           icmpinfo->code);
                if (invert)
                        icmpinfo->invflags |= IPT_ICMP_INV;
+               *flags = 1;
                break;
 
        default:
@@ -277,7 +281,7 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
        }
 }
 
-/* Final check; we don't care. */
+/* Final check; we don't care. We can pass 0xFF to match any type */
 static void final_check(unsigned int flags)
 {
 }
index 5b91514..55d24b4 100644 (file)
@@ -1,4 +1,4 @@
-This extension is loaded if `--protocol icmp' is specified.  It
+This extension can be used if `--protocol icmp' is specified.  It
 provides the following option:
 .TP
 .BR "--icmp-type " "[!] \fItypename\fP"
index 2ada8e2..e696702 100644 (file)
@@ -73,7 +73,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
                check_inverse(optarg, &invert, &optind, 0);
                if (invert) {
                        info->flags |= IPRANGE_SRC_INV;
-                       printf("hoho\n");
                }
                parse_iprange(optarg, &info->src);              
 
index 3d3b236..90183e5 100644 (file)
@@ -40,7 +40,6 @@ static struct option opts[] = {
 static int
 parse(int c, char **argv, int invert, unsigned int *flags,
       const struct ipt_entry *entry,
-      unsigned int *nfcache,
       struct ipt_entry_match **match)
 {
        struct ipt_ipv4options_info *info = (struct ipt_ipv4options_info *)(*match)->data;
diff --git a/extensions/libipt_mport.c b/extensions/libipt_mport.c
deleted file mode 100644 (file)
index a387b21..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/* Shared library add-on to iptables to add multiple TCP port support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_mport.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"mport v%s options:\n"
-" --source-ports port[,port:port,port...]\n"
-" --sports ...\n"
-"                              match source port(s)\n"
-" --destination-ports port[,port:port,port...]\n"
-" --dports ...\n"
-"                              match destination port(s)\n"
-" --ports port[,port:port,port]\n"
-"                              match both source and destination port(s)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "source-ports", 1, 0, '1' },
-       { "sports", 1, 0, '1' }, /* synonym */
-       { "destination-ports", 1, 0, '2' },
-       { "dports", 1, 0, '2' }, /* synonym */
-       { "ports", 1, 0, '3' },
-       {0}
-};
-
-static int
-service_to_port(const char *name, const char *proto)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, proto)) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-               return -1;
-}
-
-static u_int16_t
-parse_port(const char *port, const char *proto)
-{
-       unsigned int portnum;
-
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port, proto)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid port/service `%s' specified", port);
-}
-
-static void
-parse_multi_ports(const char *portstring, struct ipt_mport *minfo,
-                  const char *proto)
-{
-       char *buffer, *cp, *next, *range;
-       unsigned int i;
-        u_int16_t m;
-
-       buffer = strdup(portstring);
-       if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
-
-        minfo->pflags = 0;
-
-       for (cp=buffer, i=0, m=1; cp && i<IPT_MULTI_PORTS; cp=next,i++,m<<=1)
-       {
-               next=strchr(cp, ',');
-               if (next) *next++='\0';
-                range = strchr(cp, ':');
-                if (range) {
-                        if (i == IPT_MULTI_PORTS-1)
-                                exit_error(PARAMETER_PROBLEM,
-                                           "too many ports specified");
-                        *range++ = '\0';
-                }
-               minfo->ports[i] = parse_port(cp, proto);
-                if (range) {
-                        minfo->pflags |= m;
-                        minfo->ports[++i] = parse_port(range, proto);
-                        if (minfo->ports[i-1] >= minfo->ports[i])
-                                exit_error(PARAMETER_PROBLEM,
-                                           "invalid portrange specified");
-                        m <<= 1;
-                }
-       }
-       if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
-        if (i == IPT_MULTI_PORTS-1)
-                minfo->ports[i] = minfo->ports[i-1];
-        else if (i < IPT_MULTI_PORTS-1) {
-                minfo->ports[i] = ~0;
-                minfo->pflags |= 1<<i;
-        }
-       free(buffer);
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-}
-
-static const char *
-check_proto(const struct ipt_entry *entry)
-{
-       if (entry->ip.proto == IPPROTO_TCP)
-               return "tcp";
-       else if (entry->ip.proto == IPPROTO_UDP)
-               return "udp";
-       else if (!entry->ip.proto)
-               exit_error(PARAMETER_PROBLEM,
-                          "multiport needs `-p tcp' or `-p udp'");
-       else
-               exit_error(PARAMETER_PROBLEM,
-                          "multiport only works with TCP or UDP");
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       const char *proto;
-       struct ipt_mport *minfo
-               = (struct ipt_mport *)(*match)->data;
-
-       switch (c) {
-       case '1':
-               check_inverse(argv[optind-1], &invert, &optind, 0);
-               proto = check_proto(entry);
-               parse_multi_ports(argv[optind-1], minfo, proto);
-               minfo->flags = IPT_MPORT_SOURCE;
-               break;
-
-       case '2':
-               check_inverse(argv[optind-1], &invert, &optind, 0);
-               proto = check_proto(entry);
-               parse_multi_ports(argv[optind-1], minfo, proto);
-               minfo->flags = IPT_MPORT_DESTINATION;
-               break;
-
-       case '3':
-               check_inverse(argv[optind-1], &invert, &optind, 0);
-               proto = check_proto(entry);
-               parse_multi_ports(argv[optind-1], minfo, proto);
-               minfo->flags = IPT_MPORT_EITHER;
-               break;
-
-       default:
-               return 0;
-       }
-
-       if (invert)
-               exit_error(PARAMETER_PROBLEM,
-                          "multiport does not support invert");
-
-       if (*flags)
-               exit_error(PARAMETER_PROBLEM,
-                          "multiport can only have one option");
-       *flags = 1;
-       return 1;
-}
-
-/* Final check; must specify something. */
-static void
-final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM, "mport expects an option");
-}
-
-static char *
-port_to_service(int port, u_int8_t proto)
-{
-       struct servent *service;
-
-       if ((service = getservbyport(htons(port),
-                                    proto == IPPROTO_TCP ? "tcp" : "udp")))
-               return service->s_name;
-
-       return NULL;
-}
-
-static void
-print_port(u_int16_t port, u_int8_t protocol, int numeric)
-{
-       char *service;
-
-       if (numeric || (service = port_to_service(port, protocol)) == NULL)
-               printf("%u", port);
-       else
-               printf("%s", service);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       const struct ipt_mport *minfo
-               = (const struct ipt_mport *)match->data;
-       unsigned int i;
-        u_int16_t pflags = minfo->pflags;
-
-       printf("mport ");
-
-       switch (minfo->flags) {
-       case IPT_MPORT_SOURCE:
-               printf("sports ");
-               break;
-
-       case IPT_MPORT_DESTINATION:
-               printf("dports ");
-               break;
-
-       case IPT_MPORT_EITHER:
-               printf("ports ");
-               break;
-
-       default:
-               printf("ERROR ");
-               break;
-       }
-
-       for (i=0; i < IPT_MULTI_PORTS; i++) {
-                if (pflags & (1<<i)
-                    && minfo->ports[i] == 65535)
-                        break;
-                if (i == IPT_MULTI_PORTS-1
-                    && minfo->ports[i-1] == minfo->ports[i])
-                        break;
-               printf("%s", i ? "," : "");
-               print_port(minfo->ports[i], ip->proto, numeric);
-                if (pflags & (1<<i)) {
-                        printf(":");
-                        print_port(minfo->ports[++i], ip->proto, numeric);
-                }
-       }
-       printf(" ");
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_mport *minfo
-               = (const struct ipt_mport *)match->data;
-       unsigned int i;
-        u_int16_t pflags = minfo->pflags;
-
-       switch (minfo->flags) {
-       case IPT_MPORT_SOURCE:
-               printf("--sports ");
-               break;
-
-       case IPT_MPORT_DESTINATION:
-               printf("--dports ");
-               break;
-
-       case IPT_MPORT_EITHER:
-               printf("--ports ");
-               break;
-       }
-
-       for (i=0; i < IPT_MULTI_PORTS; i++) {
-                if (pflags & (1<<i)
-                    && minfo->ports[i] == 65535)
-                        break;
-                if (i == IPT_MULTI_PORTS-1
-                    && minfo->ports[i-1] == minfo->ports[i])
-                        break;
-               printf("%s", i ? "," : "");
-               print_port(minfo->ports[i], ip->proto, 1);
-                if (pflags & (1<<i)) {
-                        printf(":");
-                        print_port(minfo->ports[++i], ip->proto, 1);
-                }
-       }
-       printf(" ");
-}
-
-static struct iptables_match mport = { 
-       .next           = NULL,
-       .name           = "mport",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_mport)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_mport)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void
-_init(void)
-{
-       register_match(&mport);
-}
diff --git a/extensions/libipt_mport.man b/extensions/libipt_mport.man
deleted file mode 100644 (file)
index cead84e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-This module matches a set of source or destination ports.  Up to 15
-ports can be specified.  It can only be used in conjunction with
-.B "-p tcp"
-or
-.BR "-p udp" .
-.TP
-.BR "--source-ports " "\fIport\fP[,\fIport\fP[,\fIport\fP...]]"
-Match if the source port is one of the given ports.  The flag
-.B --sports
-is a convenient alias for this option.
-.TP
-.BR "--destination-ports " "\fIport\fP[,\fIport\fP[,\fIport\fP...]]"
-Match if the destination port is one of the given ports.  The flag
-.B --dports
-is a convenient alias for this option.
-.TP
-.BR "--ports " "\fIport\fP[,\fIport\fP[,\fIport\fP...]]"
-Match if the both the source and destination ports are equal to each
-other and to one of the given ports.
index 9f5193f..58b6a0e 100644 (file)
@@ -51,28 +51,23 @@ static struct option opts[] = {
        {0}
 };
 
-static int
-service_to_port(const char *name, const char *proto)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, proto)) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-               return -1;
-}
-
-static u_int16_t
-parse_port(const char *port, const char *proto)
+static char *
+proto_to_name(u_int8_t proto)
 {
-       unsigned int portnum;
-
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port, proto)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid port/service `%s' specified", port);
+       switch (proto) {
+       case IPPROTO_TCP:
+               return "tcp";
+       case IPPROTO_UDP:
+               return "udp";
+       case IPPROTO_UDPLITE:
+               return "udplite";
+       case IPPROTO_SCTP:
+               return "sctp";
+       case IPPROTO_DCCP:
+               return "dccp";
+       default:
+               return NULL;
+       }
 }
 
 static unsigned int
@@ -144,20 +139,21 @@ init(struct ipt_entry_match *m, unsigned int *nfcache)
 static const char *
 check_proto(const struct ipt_entry *entry)
 {
+       char *proto;
+
        if (entry->ip.invflags & IPT_INV_PROTO)
                exit_error(PARAMETER_PROBLEM,
-                          "multiport only works with TCP or UDP");
+                          "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
 
-       if (entry->ip.proto == IPPROTO_TCP)
-               return "tcp";
-       else if (entry->ip.proto == IPPROTO_UDP)
-               return "udp";
+       if ((proto = proto_to_name(entry->ip.proto)) != NULL)
+               return proto;
        else if (!entry->ip.proto)
                exit_error(PARAMETER_PROBLEM,
-                          "multiport needs `-p tcp' or `-p udp'");
+                          "multiport needs `-p tcp', `-p udp', `-p udplite', "
+                          "`-p sctp' or `-p dccp'");
        else
                exit_error(PARAMETER_PROBLEM,
-                          "multiport only works with TCP or UDP");
+                          "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
 }
 
 /* Function which parses command options; returns true if it
@@ -271,8 +267,7 @@ port_to_service(int port, u_int8_t proto)
 {
        struct servent *service;
 
-       if ((service = getservbyport(htons(port),
-                                    proto == IPPROTO_TCP ? "tcp" : "udp")))
+       if ((service = getservbyport(htons(port), proto_to_name(proto))))
                return service->s_name;
 
        return NULL;
diff --git a/extensions/libipt_nth.c b/extensions/libipt_nth.c
deleted file mode 100644 (file)
index 6f483b9..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/* 
-   Shared library add-on to iptables to add match support for every Nth packet
-   
-   This file is distributed under the terms of the GNU General Public
-   License (GPL). Copies of the GPL can be obtained from:
-   ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-   2001-07-17 Fabrice MARIE <fabrice@netfilter.org> : initial development.
-   2001-09-20 Richard Wagner (rwagner@cloudnet.com)
-        * added support for multiple counters
-        * added support for matching on individual packets
-          in the counter cycle
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_nth.h>
-
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"nth v%s options:\n"
-"   --every     Nth              Match every Nth packet\n"
-"  [--counter   num ]            Use counter 0-%u (default:0)\n"
-"  [--start     num ]            Initialize the counter at the number 'num'\n"
-"                                instead of 0. Must be between 0 and Nth-1\n"
-"  [--packet    num ]            Match on 'num' packet. Must be between 0\n"
-"                                and Nth-1.\n\n"
-"                                If --packet is used for a counter than\n"
-"                                there must be Nth number of --packet\n"
-"                                rules, covering all values between 0 and\n"
-"                                Nth-1 inclusively.\n",
-IPTABLES_VERSION, IPT_NTH_NUM_COUNTERS-1);
-}
-
-static struct option opts[] = {
-       { "every", 1, 0, '1' },
-       { "start", 1, 0, '2' },
-        { "counter", 1, 0, '3' },
-        { "packet", 1, 0, '4' },
-       { 0 }
-};
-
-#define IPT_NTH_OPT_EVERY      0x01
-#define IPT_NTH_OPT_NOT_EVERY  0x02
-#define IPT_NTH_OPT_START      0x04
-#define IPT_NTH_OPT_COUNTER     0x08
-#define IPT_NTH_OPT_PACKET      0x10
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_nth_info *nthinfo = (struct ipt_nth_info *)(*match)->data;
-       unsigned int num;
-
-       switch (c) {
-       case '1':
-               /* check for common mistakes... */
-               if ((!invert) && (*flags & IPT_NTH_OPT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --every twice");
-               if (invert && (*flags & IPT_NTH_OPT_NOT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify ! --every twice");
-               if ((!invert) && (*flags & IPT_NTH_OPT_NOT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --every with ! --every");
-               if (invert && (*flags & IPT_NTH_OPT_EVERY))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify ! --every with --every");
-
-               /* Remember, this function will interpret a leading 0 to be 
-                  Octal, a leading 0x to be hexdecimal... */
-                if (string_to_number(optarg, 2, 100, &num) == -1 || num < 2)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --every `%s', must be between 2 and 100", optarg);
-
-               /* assign the values */
-               nthinfo->every = num-1;
-               nthinfo->startat = 0;
-                nthinfo->packet = 0xFF;
-                if(!(*flags & IPT_NTH_OPT_EVERY))
-                {
-                        nthinfo->counter = 0;
-                }
-               if (invert)
-               {
-                       *flags |= IPT_NTH_OPT_NOT_EVERY;
-                       nthinfo->not = 1;
-               }
-               else
-               {
-                       *flags |= IPT_NTH_OPT_EVERY;
-                       nthinfo->not = 0;
-               }
-               break;
-       case '2':
-               /* check for common mistakes... */
-               if (!((*flags & IPT_NTH_OPT_EVERY) ||
-                     (*flags & IPT_NTH_OPT_NOT_EVERY)))
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --start before --every");
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify with ! --start");
-               if (*flags & IPT_NTH_OPT_START)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --start twice");
-               if (string_to_number(optarg, 0, nthinfo->every, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --start `%s', must between 0 and %u", optarg, nthinfo->every);
-               *flags |= IPT_NTH_OPT_START;
-               nthinfo->startat = num;
-               break;
-        case '3':
-                /* check for common mistakes... */
-                if (invert)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify with ! --counter");
-                if (*flags & IPT_NTH_OPT_COUNTER)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --counter twice");
-                if (string_to_number(optarg, 0, IPT_NTH_NUM_COUNTERS-1, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --counter `%s', must between 0 and %u", optarg, IPT_NTH_NUM_COUNTERS-1);
-                /* assign the values */
-                *flags |= IPT_NTH_OPT_COUNTER;
-                nthinfo->counter = num;
-                break;
-        case '4':
-                /* check for common mistakes... */
-                if (!((*flags & IPT_NTH_OPT_EVERY) ||
-                      (*flags & IPT_NTH_OPT_NOT_EVERY)))
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --packet before --every");
-                if ((*flags & IPT_NTH_OPT_NOT_EVERY))
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --packet with ! --every");
-                if (invert)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify with ! --packet");
-                if (*flags & IPT_NTH_OPT_PACKET)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --packet twice");
-                if (string_to_number(optarg, 0, nthinfo->every, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --packet `%s', must between 0 and %u", optarg, nthinfo->every);
-                *flags |= IPT_NTH_OPT_PACKET;
-                nthinfo->packet = num;
-                break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       const struct ipt_nth_info *nthinfo
-               = (const struct ipt_nth_info *)match->data;
-
-       if (nthinfo->not == 1)
-               printf(" !");
-       printf("every %uth ", (nthinfo->every +1));
-       if (nthinfo->counter != 0) 
-               printf("counter #%u ", (nthinfo->counter));
-        if (nthinfo->packet != 0xFF)
-                printf("packet #%u ", nthinfo->packet);
-       if (nthinfo->startat != 0)
-               printf("start at %u ", nthinfo->startat);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_nth_info *nthinfo
-               = (const struct ipt_nth_info *)match->data;
-
-       if (nthinfo->not == 1)
-               printf("! ");
-       printf("--every %u ", (nthinfo->every +1));
-       printf("--counter %u ", (nthinfo->counter));
-       if (nthinfo->startat != 0)
-               printf("--start %u ", nthinfo->startat );
-        if (nthinfo->packet != 0xFF)
-                printf("--packet %u ", nthinfo->packet );
-}
-
-static struct iptables_match nth = { 
-       .next           = NULL,
-       .name           = "nth",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_nth_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_nth_info)),
-       .help           = &help,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&nth);
-}
diff --git a/extensions/libipt_nth.man b/extensions/libipt_nth.man
deleted file mode 100644 (file)
index d215fd5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-This module matches every `n'th packet
-.TP
-.BI "--every " "value"
-Match every `value' packet
-.TP
-.BI "[" "--counter " "num" "]"
-Use internal counter number `num'.  Default is `0'.
-.TP
-.BI "[" "--start " "num" "]"
-Initialize the counter at the number `num' insetad of `0'.  Most between `0'
-and `value'-1.
-.TP
-.BI "[" "--packet " "num" "]"
-Match on `num' packet.  Most be between `0' and `value'-1.
diff --git a/extensions/libipt_osf.c b/extensions/libipt_osf.c
deleted file mode 100644 (file)
index 6747404..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * libipt_osf.c
- *
- * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * iptables interface for OS fingerprint matching module.
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_osf.h>
-
-static void help(void)
-{
-       printf("OS fingerprint match options:\n"
-               "--genre [!] string     Match a OS genre by passive fingerprinting.\n"
-               "--smart                Use some smart extensions to determine OS (do not use TTL).\n"
-               "--log level            Log all(or only first) determined genres even if "
-                                       "they do not match desired one. "
-                                       "Level may be 0(all) or 1(only first entry).\n"
-               "--netlink              Log through netlink(NETLINK_NFLOG).\n",
-               "--connector            Log through kernel connector [in 2.6.12-mm+].\n"
-               );
-}
-
-
-static struct option opts[] = {
-       { .name = "genre",      .has_arg = 1, .flag = 0, .val = '1' },
-       { .name = "smart",      .has_arg = 0, .flag = 0, .val = '2' },
-       { .name = "log",        .has_arg = 1, .flag = 0, .val = '3' },
-       { .name = "netlink",    .has_arg = 0, .flag = 0, .val = '4' },
-       { .name = "connector",  .has_arg = 0, .flag = 0, .val = '5' },
-       { .name = 0 }
-};
-
-static void parse_string(const unsigned char *s, struct ipt_osf_info *info)
-{
-       if (strlen(s) < MAXGENRELEN) 
-               strcpy(info->genre, s);
-       else 
-               exit_error(PARAMETER_PROBLEM, "Genre string too long `%s' [%d], max=%d", 
-                               s, strlen(s), MAXGENRELEN);
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
-                       const struct ipt_entry *entry,
-                       unsigned int *nfcache,
-                       struct ipt_entry_match **match)
-{
-       struct ipt_osf_info *info = (struct ipt_osf_info *)(*match)->data;
-       
-       switch(c) 
-       {
-               case '1': /* --genre */
-                       if (*flags & IPT_OSF_GENRE)
-                               exit_error(PARAMETER_PROBLEM, "Can't specify multiple genre parameter");
-                       check_inverse(optarg, &invert, &optind, 0);
-                       parse_string(argv[optind-1], info);
-                       if (invert)
-                               info->invert = 1;
-                       info->len=strlen((char *)info->genre);
-                       *flags |= IPT_OSF_GENRE;
-                       break;
-               case '2': /* --smart */
-                       if (*flags & IPT_OSF_SMART)
-                               exit_error(PARAMETER_PROBLEM, "Can't specify multiple smart parameter");
-                       *flags |= IPT_OSF_SMART;
-                       info->flags |= IPT_OSF_SMART;
-                       break;
-               case '3': /* --log */
-                       if (*flags & IPT_OSF_LOG)
-                               exit_error(PARAMETER_PROBLEM, "Can't specify multiple log parameter");
-                       *flags |= IPT_OSF_LOG;
-                       info->loglevel = atoi(argv[optind-1]);
-                       info->flags |= IPT_OSF_LOG;
-                       break;
-               case '4': /* --netlink */
-                       if (*flags & IPT_OSF_NETLINK)
-                               exit_error(PARAMETER_PROBLEM, "Can't specify multiple netlink parameter");
-                       *flags |= IPT_OSF_NETLINK;
-                       info->flags |= IPT_OSF_NETLINK;
-                       break;
-               case '5': /* --connector */
-                       if (*flags & IPT_OSF_CONNECTOR)
-                               exit_error(PARAMETER_PROBLEM, "Can't specify multiple connector parameter");
-                       *flags |= IPT_OSF_CONNECTOR;
-                       info->flags |= IPT_OSF_CONNECTOR;
-                       break;
-               default:
-                       return 0;
-       }
-
-       return 1;
-}
-
-static void final_check(unsigned int flags)
-{
-       if (!flags)
-               exit_error(PARAMETER_PROBLEM, "OS fingerprint match: You must specify `--genre'");
-}
-
-static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
-{
-       const struct ipt_osf_info *info = (const struct ipt_osf_info*) match->data;
-
-       printf("OS fingerprint match %s%s ", (info->invert) ? "!" : "", info->genre);
-}
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_osf_info *info = (const struct ipt_osf_info*) match->data;
-
-       printf("--genre %s%s ", (info->invert) ? "! ": "", info->genre);
-}
-
-
-static struct iptables_match osf_match = {
-    .name          = "osf",
-    .version       = IPTABLES_VERSION,
-    .size          = IPT_ALIGN(sizeof(struct ipt_osf_info)),
-    .userspacesize = IPT_ALIGN(sizeof(struct ipt_osf_info)),
-    .help          = &help,
-    .parse         = &parse,
-    .final_check   = &final_check,
-    .print         = &print,
-    .save          = &save,
-    .extra_opts    = opts
-};
-
-
-void _init(void)
-{
-       register_match(&osf_match);
-}
diff --git a/extensions/libipt_osf.man b/extensions/libipt_osf.man
deleted file mode 100644 (file)
index 38d25a0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-The idea of passive OS fingerprint matching exists for quite a long time,
-but was created as extension fo OpenBSD pf only some weeks ago.
-Original idea was lurked in some OpenBSD mailing list (thanks
-grange@open...) and than adopted for Linux netfilter in form of this code.
-
-Original fingerprint table was created by Michal Zalewski <lcamtuf@coredump.cx>.
-
-This module compares some data(WS, MSS, options and it's order, ttl,
-df and others) from first SYN packet (actually from packets with SYN
-bit set) with dynamically loaded OS fingerprints.
-.TP
-.B "--log 1/0" 
-If present, OSF will log determined genres even if they don't match
-desired one.   
-0 - log all determined entries, 
-1 - only first one.
-
-In syslog you find something like this:
-.IP
-ipt_osf: Windows [2000:SP3:Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
-.IP
-ipt_osf: Unknown: 16384:106:1:48:020405B401010402 44.33.22.11:1239 -> 11.22.33.44:80
-.TP
-.B "--smart"
-if present, OSF will use some smartness to determine remote OS.
-OSF will use initial TTL only if source of connection is in our local network.
-.TP
-.B "--netlink"
-If present, OSF will log all events also through netlink NETLINK_NFLOG groupt 1.
-.TP
-.BI "--genre " "[!] string"
-Match a OS genre by passive fingerprinting
-.P
-Example:
-
-#iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
-
-NOTE: -p tcp is obviously required as it is a TCP match.
-
-Fingerprints can be loaded and read through /proc/sys/net/ipv4/osf file.
-One can flush all fingerprints with following command:
-.IP
-echo -en FLUSH > /proc/sys/net/ipv4/osf
-.P
-Only one fingerprint per open/write/close.
-
-Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
diff --git a/extensions/libipt_psd.c b/extensions/libipt_psd.c
deleted file mode 100644 (file)
index 3d0034a..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/* 
-  Shared library add-on to iptables to add PSD support 
-   
-  Copyright (C) 2000,2001 astaro AG
-
-  This file is distributed under the terms of the GNU General Public
-  License (GPL). Copies of the GPL can be obtained from:
-     ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
-  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
-  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
-  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
-  2003-03-02 Harald Welte <laforge@netfilter.org>: fix 'storage' bug
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_psd.h>
-
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"psd v%s options:\n"
-" --psd-weight-threshold threshhold  Portscan detection weight threshold\n\n"
-" --psd-delay-threshold  delay       Portscan detection delay threshold\n\n"
-" --psd-lo-ports-weight  lo          Privileged ports weight\n\n"
-" --psd-hi-ports-weight  hi          High ports weight\n\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "psd-weight-threshold", 1, 0, '1' },
-       { "psd-delay-threshold", 1, 0, '2' },
-       { "psd-lo-ports-weight", 1, 0, '3' },
-       { "psd-hi-ports-weight", 1, 0, '4' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-       struct ipt_psd_info *psdinfo = (struct ipt_psd_info *)m->data;
-
-       psdinfo->weight_threshold = SCAN_WEIGHT_THRESHOLD;  
-       psdinfo->delay_threshold = SCAN_DELAY_THRESHOLD;
-       psdinfo->lo_ports_weight = PORT_WEIGHT_PRIV;
-       psdinfo->hi_ports_weight = PORT_WEIGHT_HIGH;
-}
-
-
-typedef struct _code {
-       char    *c_name;
-       int     c_val;
-} CODE;
-
-
-
-#define IPT_PSD_OPT_CTRESH 0x01
-#define IPT_PSD_OPT_DTRESH 0x02
-#define IPT_PSD_OPT_LPWEIGHT 0x04
-#define IPT_PSD_OPT_HPWEIGHT 0x08
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_psd_info *psdinfo = (struct ipt_psd_info *)(*match)->data;
-       unsigned int num;
-       
-       switch (c) {
-       /* PSD-weight-threshold */
-       case '1':
-               if (*flags & IPT_PSD_OPT_CTRESH)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --psd-weight-threshold "
-                                  "twice");
-                if (string_to_number(optarg, 0, 10000, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --psd-weight-threshold `%s'", optarg);
-               psdinfo->weight_threshold = num;
-               *flags |= IPT_PSD_OPT_CTRESH;
-               break;
-
-       /* PSD-delay-threshold */
-       case '2':
-               if (*flags & IPT_PSD_OPT_DTRESH)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --psd-delay-threshold twice");
-                if (string_to_number(optarg, 0, 10000, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --psd-delay-threshold `%s'", optarg);
-               psdinfo->delay_threshold = num;
-               *flags |= IPT_PSD_OPT_DTRESH;
-               break;
-
-       /* PSD-lo-ports-weight */
-       case '3':
-               if (*flags & IPT_PSD_OPT_LPWEIGHT)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --psd-lo-ports-weight twice");
-                if (string_to_number(optarg, 0, 10000, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --psd-lo-ports-weight `%s'", optarg);
-               psdinfo->lo_ports_weight = num;
-               *flags |= IPT_PSD_OPT_LPWEIGHT;
-               break;
-
-       /* PSD-hi-ports-weight */
-       case '4':
-               if (*flags & IPT_PSD_OPT_HPWEIGHT)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --psd-hi-ports-weight twice");
-                if (string_to_number(optarg, 0, 10000, &num) == -1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --psd-hi-ports-weight `%s'", optarg);
-               psdinfo->hi_ports_weight = num;
-               *flags |= IPT_PSD_OPT_HPWEIGHT;
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       const struct ipt_psd_info *psdinfo
-               = (const struct ipt_psd_info *)match->data;
-
-       printf("psd ");
-       printf("weight-threshold: %u ", psdinfo->weight_threshold);
-       printf("delay-threshold: %u ", psdinfo->delay_threshold);
-       printf("lo-ports-weight: %u ", psdinfo->lo_ports_weight);
-       printf("hi-ports-weight: %u ", psdinfo->hi_ports_weight);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_psd_info *psdinfo
-               = (const struct ipt_psd_info *)match->data;
-
-       printf("--psd-weight-threshold %u ", psdinfo->weight_threshold);
-       printf("--psd-delay-threshold %u ", psdinfo->delay_threshold);
-       printf("--psd-lo-ports-weight %u ", psdinfo->lo_ports_weight);
-       printf("--psd-hi-ports-weight %u ", psdinfo->hi_ports_weight);
-}
-
-static struct iptables_match psd = { 
-       .next           = NULL,
-       .name           = "psd",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_psd_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_psd_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&psd);
-}
diff --git a/extensions/libipt_psd.man b/extensions/libipt_psd.man
deleted file mode 100644 (file)
index b73fffc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-Attempt to detect TCP and UDP port scans. This match was derived from
-Solar Designer's scanlogd.
-.TP
-.BI "--psd-weight-threshold " "threshold"
-Total weight of the latest TCP/UDP packets with different
-destination ports coming from the same host to be treated as port
-scan sequence.
-.TP
-.BI "--psd-delay-threshold " "delay"
-Delay (in hundredths of second) for the packets with different
-destination ports coming from the same host to be treated as
-possible port scan subsequence.
-.TP
-.BI "--psd-lo-ports-weight " "weight"
-Weight of the packet with privileged (<=1024) destination port.
-.TP
-.BI "--psd-hi-ports-weight " "weight"
-Weight of the packet with non-priviliged destination port.
index a9c138c..8380754 100644 (file)
@@ -3,12 +3,13 @@
  *
  * Sam Johnston <samj@samj.net>
  */
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <getopt.h>
 #include <iptables.h>
 
-#include <linux/netfilter_ipv4/ipt_quota.h>
+#include <linux/netfilter/xt_quota.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
 static struct option opts[] = {
@@ -28,7 +29,7 @@ help(void)
 static void
 print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
 {
-        struct ipt_quota_info *q = (struct ipt_quota_info *) match->data;
+        struct xt_quota_info *q = (struct xt_quota_info *) match->data;
         printf("quota: %llu bytes", (unsigned long long) q->quota);
 }
 
@@ -36,7 +37,7 @@ print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
 static void
 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
 {
-        struct ipt_quota_info *q = (struct ipt_quota_info *) match->data;
+        struct xt_quota_info *q = (struct xt_quota_info *) match->data;
         printf("--quota %llu ", (unsigned long long) q->quota);
 }
 
@@ -62,7 +63,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
       const struct ipt_entry *entry,
       unsigned int *nfcache, struct ipt_entry_match **match)
 {
-        struct ipt_quota_info *info = (struct ipt_quota_info *) (*match)->data;
+        struct xt_quota_info *info = (struct xt_quota_info *) (*match)->data;
 
         switch (c) {
         case '1':
@@ -89,8 +90,8 @@ struct iptables_match quota = {
        .next           = NULL,
        .name           = "quota",
        .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof (struct ipt_quota_info)),
-       .userspacesize  = IPT_ALIGN(sizeof (struct ipt_quota_info)),
+       .size           = IPT_ALIGN(sizeof (struct xt_quota_info)),
+       .userspacesize  = offsetof(struct xt_quota_info, quota),
        .help           = &help,
        .parse          = &parse,
        .final_check    = &final_check,
index 8a07ec0..7945bee 100644 (file)
@@ -4,4 +4,3 @@ packet.
 .BI "--quota " "bytes"
 The quota in bytes.
 .P
-KNOWN BUGS: this does not work on SMP systems.
diff --git a/extensions/libipt_random.c b/extensions/libipt_random.c
deleted file mode 100644 (file)
index d28ab8c..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* 
-   Shared library add-on to iptables to add match support for random match.
-   
-   This file is distributed under the terms of the GNU General Public
-   License (GPL). Copies of the GPL can be obtained from:
-   ftp://prep.ai.mit.edu/pub/gnu/GPL
-
-   2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial development.
-*/
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_random.h>
-
-/**
- * The kernel random routing returns numbers between 0 and 255.
- * To ease the task of the user in choosing the probability
- * of matching, we want him to be able to use percentages.
- * Therefore we have to accept numbers in percentage here,
- * turn them into number between 0 and 255 for the kernel module,
- * and turn them back to percentages when we print/save
- * the rule.
- */
-
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"random v%s options:\n"
-"  [--average      percent ]    The probability in percentage of the match\n"
-"                               If ommited, a probability of 50%% percent is set.\n"
-"                               Percentage must be within : 1 <= percent <= 99.\n\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "average", 1, 0, '1' },
-       { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-       struct ipt_rand_info *randinfo = (struct ipt_rand_info *)(m)->data;
-
-       /* We assign the average to be 50 which is our default value */
-       /* 50 * 2.55 = 128 */
-       randinfo->average = 128;
-}
-
-#define IPT_RAND_OPT_AVERAGE   0x01
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_rand_info *randinfo = (struct ipt_rand_info *)(*match)->data;
-       unsigned int num;
-
-       switch (c) {
-       case '1':
-               /* check for common mistakes... */
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify ! --average");
-               if (*flags & IPT_RAND_OPT_AVERAGE)
-                       exit_error(PARAMETER_PROBLEM,
-                                  "Can't specify --average twice");
-
-               /* Remember, this function will interpret a leading 0 to be 
-                  Octal, a leading 0x to be hexdecimal... */
-                if (string_to_number(optarg, 1, 99, &num) == -1 || num < 1)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "bad --average `%s', must be between 1 and 99", optarg);
-
-               /* assign the values */
-               randinfo->average = (int)(num * 2.55);
-               *flags |= IPT_RAND_OPT_AVERAGE;
-               break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       const struct ipt_rand_info *randinfo
-               = (const struct ipt_rand_info *)match->data;
-       div_t result = div((randinfo->average*100), 255);
-       if (result.rem > 127)  /* round up... */
-               ++result.quot;
-
-       printf(" random %u%% ", result.quot);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       const struct ipt_rand_info *randinfo
-               = (const struct ipt_rand_info *)match->data;
-       div_t result = div((randinfo->average *100), 255);
-       if (result.rem > 127)  /* round up... */
-               ++result.quot;
-
-       printf("--average %u ", result.quot);
-}
-
-struct iptables_match rand_match = { 
-       .next           = NULL,
-       .name           = "random",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_rand_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_rand_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&rand_match);
-}
diff --git a/extensions/libipt_random.man b/extensions/libipt_random.man
deleted file mode 100644 (file)
index f808a77..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-This module randomly matches a certain percentage of all packets.
-.TP
-.BI "--average " "percent"
-Matches the given percentage.  If omitted, a probability of 50% is set. 
index 90e6089..1564677 100644 (file)
@@ -3,6 +3,8 @@
 #include <netdb.h>
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
 #include <getopt.h>
 #if defined(__GLIBC__) && __GLIBC__ == 2
 #include <net/ethernet.h>
@@ -17,7 +19,7 @@ static void
 help(void)
 {
        printf(
-"REALM v%s options:\n"
+"realm v%s options:\n"
 " --realm [!] value[/mask]\n"
 "                              Match realm\n"
 "\n", IPTABLES_VERSION);
@@ -28,6 +30,128 @@ static struct option opts[] = {
        {0}
 };
 
+struct realmname { 
+       int     id;
+       char*   name;
+       int     len;
+       struct realmname* next;
+};
+
+/* array of realms from /etc/iproute2/rt_realms */
+static struct realmname *realms = NULL;
+/* 1 if loading failed */
+static int rdberr = 0;
+
+
+void load_realms()
+{
+       const char* rfnm = "/etc/iproute2/rt_realms";
+       char buf[512];
+       FILE *fil;
+       char *cur, *nxt;
+       int id;
+       struct realmname *oldnm = NULL, *newnm = NULL;
+
+       fil = fopen(rfnm, "r");
+       if (!fil) {
+               rdberr = 1;
+               return;
+       }
+
+       while (fgets(buf, sizeof(buf), fil)) {
+               cur = buf;
+               while ((*cur == ' ') || (*cur == '\t'))
+                       cur++;
+               if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
+                       continue;
+
+               /* iproute2 allows hex and dec format */
+               errno = 0;
+               id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16);
+               if ((nxt == cur) || errno)
+                       continue;
+
+               /* same boundaries as in iproute2 */
+               if (id < 0 || id > 255)
+                       continue;
+               cur = nxt;
+
+               if (!isspace(*cur))
+                       continue;
+               while ((*cur == ' ') || (*cur == '\t'))
+                       cur++;
+               if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
+                       continue;
+               nxt = cur;
+               while ((*nxt != 0) && !isspace(*nxt))
+                       nxt++;
+               if (nxt == cur)
+                       continue;
+
+               /* found valid data */
+               newnm = (struct realmname*)malloc(sizeof(struct realmname));
+               if (newnm == NULL) {
+                       perror("libipt_realm: malloc failed");
+                       exit(1);
+               }
+               newnm->id = id;
+               newnm->len = nxt - cur;
+               newnm->name = (char*)malloc(newnm->len + 1);
+               if (newnm->name == NULL) {
+                       perror("libipt_realm: malloc failed");
+                       exit(1);
+               }
+               strncpy(newnm->name, cur, newnm->len);
+               newnm->name[newnm->len] = 0;
+               newnm->next = NULL;
+
+               if (oldnm)
+                       oldnm->next = newnm;
+               else
+                       realms = newnm;
+               oldnm = newnm;
+       }
+
+       fclose(fil);
+}
+
+/* get realm id for name, -1 if error/not found */
+int realm_name2id(const char* name)
+{
+       struct realmname* cur;
+
+       if ((realms == NULL) && (rdberr == 0))
+               load_realms();
+       cur = realms;
+       if (cur == NULL)
+               return -1;
+       while (cur) {
+               if (!strncmp(name, cur->name, cur->len + 1))
+                       return cur->id;
+               cur = cur->next;
+       }
+       return -1;
+}
+
+/* get realm name for id, NULL if error/not found */
+const char* realm_id2name(int id)
+{
+       struct realmname* cur;
+
+       if ((realms == NULL) && (rdberr == 0))
+               load_realms();
+       cur = realms;
+       if (cur == NULL)
+               return NULL;
+       while (cur) {
+               if (id == cur->id)
+                       return cur->name;
+               cur = cur->next;
+       }
+       return NULL;
+}
+
+
 /* Function which parses command options; returns true if it
    ate an option */
 static int
@@ -37,19 +161,30 @@ parse(int c, char **argv, int invert, unsigned int *flags,
       struct ipt_entry_match **match)
 {
        struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data;
+       int id;
 
        switch (c) {
                char *end;
        case '1':
                check_inverse(argv[optind-1], &invert, &optind, 0);
-               optarg = argv[optind-1];
+               end = optarg = argv[optind-1];
                realminfo->id = strtoul(optarg, &end, 0);
-               if (*end == '/') {
-                       realminfo->mask = strtoul(end+1, &end, 0);
-               } else
+               if (end != optarg && (*end == '/' || *end == '\0')) {
+                       if (*end == '/')
+                               realminfo->mask = strtoul(end+1, &end, 0);
+                       else
+                               realminfo->mask = 0xffffffff;
+                       if (*end != '\0' || end == optarg)
+                               exit_error(PARAMETER_PROBLEM,
+                                          "Bad realm value `%s'", optarg);
+               } else {
+                       id = realm_name2id(optarg);
+                       if (id == -1)
+                               exit_error(PARAMETER_PROBLEM,
+                                          "Realm `%s' not found", optarg);
+                       realminfo->id = (u_int32_t)id;
                        realminfo->mask = 0xffffffff;
-               if (*end != '\0' || end == optarg)
-                       exit_error(PARAMETER_PROBLEM, "Bad REALM value `%s'", optarg);
+               }
                if (invert)
                        realminfo->invert = 1;
                *flags = 1;
@@ -62,12 +197,20 @@ parse(int c, char **argv, int invert, unsigned int *flags,
 }
 
 static void
-print_realm(unsigned long id, unsigned long mask)
+print_realm(unsigned long id, unsigned long mask, int numeric)
 {
+       const char* name = NULL;
+
        if (mask != 0xffffffff)
                printf("0x%lx/0x%lx ", id, mask);
-       else
-               printf("0x%lx ", id);
+       else {
+               if (numeric == 0)
+                       name = realm_id2name(id);
+               if (name)
+                       printf("%s ", name);
+               else
+                       printf("0x%lx ", id);
+       }
 }
 
 /* Prints out the matchinfo. */
@@ -81,8 +224,8 @@ print(const struct ipt_ip *ip,
        if (ri->invert)
                printf("! ");
 
-       printf("REALM match ");
-       print_realm(ri->id, ri->mask);
+       printf("realm ");
+       print_realm(ri->id, ri->mask, numeric);
 }
 
 
@@ -96,7 +239,7 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
                printf("! ");
 
        printf("--realm ");
-       print_realm(ri->id, ri->mask);
+       print_realm(ri->id, ri->mask, 0);
 }
 
 /* Final check; must have specified --mark. */
@@ -105,7 +248,7 @@ final_check(unsigned int flags)
 {
        if (!flags)
                exit_error(PARAMETER_PROBLEM,
-                          "REALM match: You must specify `--realm'");
+                          "realm match: You must specify `--realm'");
 }
 
 static struct iptables_match realm = { NULL,
index 55e67fc..b33da0e 100644 (file)
@@ -1,5 +1,7 @@
 This matches the routing realm.  Routing realms are used in complex routing
 setups involving dynamic routing protocols like BGP.
 .TP
-.BI "--realm " "[!]" "value[/mask]"
-Matches a given realm number (and optionally mask).
+.BI "--realm " "[!] " "value[/mask]"
+Matches a given realm number (and optionally mask). If not a number, value
+can be a named realm from /etc/iproute2/rt_realms (mask can not be used in
+that case).
diff --git a/extensions/libipt_record_rpc.c b/extensions/libipt_record_rpc.c
deleted file mode 100644 (file)
index 571d286..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Shared library add-on to iptables for rpc match */
-#include <stdio.h>
-#include <getopt.h>
-#include <iptables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"record_rpc v%s takes no options\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       {0}
-};
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       return 0;
-}
-
-/* Final check; must have specified --mac. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-}
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-}
-
-static
-struct iptables_match record_rpc = { 
-       .next           = NULL,
-       .name           = "record_rpc",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(0),
-       .userspacesize  = IPT_ALIGN(0),
-       .help           = &help,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&record_rpc);
-}
diff --git a/extensions/libipt_rpc.c b/extensions/libipt_rpc.c
deleted file mode 100644 (file)
index dbfb396..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/* RPC extension for IP connection matching, Version 2.2
- * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
- *     - original rpc tracking module
- *     - "recent" connection handling for kernel 2.3+ netfilter
- *
- * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
- *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
- *
- * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
- *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
- *     - extended matching to support filtering on procedures
- *
- * libipt_rpc.c,v 2.2 2003/01/12 18:30:00
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- **
- *     Userspace library syntax:
- *     --rpc [--rpcs procedure1,procedure2,...procedure128] [--static]
- *
- *     Procedures can be supplied in either numeric or named formats.
- *     Without --rpcs, this module will behave as the old record-rpc.
- **
- *     Note to all:
- *
- *     RPCs should not be exposed to the internet - ask the Pentagon;
- *
- *       "The unidentified crackers pleaded guilty in July to charges
- *        of juvenile delinquency stemming from a string of Pentagon
- *        network intrusions in February.
- *
- *        The youths, going by the names TooShort and Makaveli, used
- *        a common server security hole to break in, according to
- *        Dane Jasper, owner of the California Internet service
- *        provider, Sonic. They used the hole, known as the 'statd'
- *        exploit, to attempt more than 800 break-ins, Jasper said."
- *
- *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
- *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
- **
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <rpc/rpc.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_rpc.h>
-#include <time.h>
-
-
-const int IPT_RPC_RPCS = 1;
-const int IPT_RPC_STRC = 2;
-
-const int IPT_RPC_INT_LBL = 1;
-const int IPT_RPC_INT_NUM = 2;
-const int IPT_RPC_INT_BTH = 3;
-
-const int IPT_RPC_CHAR_LEN = 11;
-const int IPT_RPC_MAX_ENTS = 128;
-
-const char preerr[11] = "RPC match:";
-
-
-static int k_itoa(char *string, int number)
-{
-       int maxoctet = IPT_RPC_CHAR_LEN - 1;
-       int store[IPT_RPC_CHAR_LEN];
-       int counter;
-
-
-        for (counter=0 ; maxoctet != 0 && number != 0; counter++, maxoctet--) {
-               store[counter] = number / 10;
-               store[counter] = number - ( store[counter] * 10 );
-               number = number / 10;
-        }
-
-        for ( ; counter != 0; counter--, string++)
-               *string = store[counter - 1] + 48;
-
-       *string = 0;
-
-       return(0);
-}
-
-
-static int k_atoi(char *string)
-{
-       unsigned int result = 0;
-       int maxoctet = IPT_RPC_CHAR_LEN;
-
-
-        for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
-                if (*string < 0)
-                        return(0);
-                if (*string == 0)
-                        break;
-                if (*string < 48 || *string > 57) {
-                        return(0);
-                }
-                result = result * 10 + ( *string - 48 );
-        }
-
-       return(result);
-}
-
-
-static void print_rpcs(char *c_procs, int i_procs, int labels)
-{
-       int   proc_ctr;
-       char *proc_ptr;
-       unsigned int proc_num;
-       struct rpcent *rpcent;
-
-
-       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
-
-               if ( proc_ctr != 0 )
-                       printf(",");
-
-               proc_ptr = c_procs;
-               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
-               proc_num = k_atoi(proc_ptr);
-
-               /* labels(1) == no labels, only numbers
-                * labels(2) == no numbers, only labels
-                * labels(3) == both labels and numbers
-                */
-
-               if (labels == IPT_RPC_INT_LBL || labels == IPT_RPC_INT_BTH ) {
-                       if ( (rpcent = getrpcbynumber(proc_num)) == NULL )
-                               printf("unknown");
-                       else
-                               printf("%s", rpcent->r_name);
-               }
-
-               if (labels == IPT_RPC_INT_BTH )
-                       printf("(");
-
-               if (labels == IPT_RPC_INT_NUM || labels == IPT_RPC_INT_BTH )
-                       printf("%i", proc_num);
-
-               if (labels == IPT_RPC_INT_BTH )
-                       printf(")");
-
-       }
-
-}
-
-
-static void help(void) 
-{
-       printf(
-               "RPC v%s options:\n"
-               "  --rpcs list,of,procedures"
-               "\ta list of rpc program numbers to apply\n"
-               "\t\t\t\tie. 100003,mountd,rquotad (numeric or\n"
-               "\t\t\t\tname form; see /etc/rpc).\n"
-               "  --strict"
-               "\t\t\ta flag to force the drop of packets\n"
-               "\t\t\t\tnot containing \"get\" portmapper requests.\n",
-               IPTABLES_VERSION);
-}
-
-
-static struct option opts[] = {
-       { "rpcs", 1, 0, '1'},
-       { "strict", 0, 0, '2'},
-       {0}
-};
-
-
-static void init(struct ipt_entry_match *match, unsigned int *nfcache)
-{
-       struct ipt_rpc_info *rpcinfo = ((struct ipt_rpc_info *)match->data);
-
-
-
-       /* initialise those funky user vars */
-       rpcinfo->i_procs = -1;
-       rpcinfo->strict  =  0;
-       memset((char *)rpcinfo->c_procs, 0, sizeof(rpcinfo->c_procs));
-}
-
-
-static void parse_rpcs_string(char *string, struct ipt_entry_match **match)
-{
-       char err1[64] = "%s invalid --rpcs option-set: `%s' (at character %i)";
-       char err2[64] = "%s unable to resolve rpc name entry: `%s'";
-       char err3[64] = "%s maximum number of --rpc options (%i) exceeded";
-       char buf[256];
-       char *dup = buf;
-       int idup = 0;
-       int term = 0;
-       char *src, *dst;
-       char *c_procs;
-       struct rpcent *rpcent_ptr;
-       struct ipt_rpc_info *rpcinfo = (struct ipt_rpc_info *)(*match)->data;
-
-
-       memset(buf, 0, sizeof(buf));
-
-       for (src=string, dst=buf; term != 1 ; src++, dst++) {
-
-               if ( *src != ',' && *src != '\0' ) {
-                       if ( ( *src >= 65 && *src <= 90 ) || ( *src >= 97 && *src <= 122) ) {
-                               *dst = *src;
-                               idup = 1;
-
-                       } else if ( *src >= 48 && *src <= 57 ) {
-                               *dst = *src;
-
-                       } else {
-                               exit_error(PARAMETER_PROBLEM, err1, preerr,
-                                          string, src - string + 1);
-
-                       }
-
-               } else {
-                       *dst = '\0';
-                       if ( idup == 1 ) {
-                               if ( (rpcent_ptr = getrpcbyname(dup)) == NULL )
-                                       exit_error(PARAMETER_PROBLEM, err2,
-                                                  preerr, dup);
-                               idup = rpcent_ptr->r_number;
-                       } else {
-                               idup = k_atoi(dup);
-                       }
-
-                       rpcinfo->i_procs++;
-                       if ( rpcinfo->i_procs > IPT_RPC_MAX_ENTS )
-                               exit_error(PARAMETER_PROBLEM, err3, preerr,
-                                          IPT_RPC_MAX_ENTS);
-                               
-                       c_procs  = (char *)rpcinfo->c_procs;
-                       c_procs += rpcinfo->i_procs * IPT_RPC_CHAR_LEN;
-                       
-                       memset(buf, 0, sizeof(buf));
-                       k_itoa((char *)dup, idup);
-
-                       strcpy(c_procs, dup);
-       
-                       if ( *src == '\0')
-                               term = 1;
-
-                       idup = 0;
-                       memset(buf, 0, sizeof(buf));
-                       dst = (char *)buf - 1;
-               }
-       }
-
-       return;
-}
-
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
-               const struct ipt_entry *entry,
-               unsigned int *nfcache,
-               struct ipt_entry_match **match)
-{
-       struct ipt_rpc_info *rpcinfo = (struct ipt_rpc_info *)(*match)->data;
-
-
-       switch (c)
-       {
-       case '1':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "%s unexpected '!' with --rpcs\n", preerr);
-               if (*flags & IPT_RPC_RPCS)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "%s repeated use of --rpcs\n", preerr);
-               parse_rpcs_string(optarg, match);
-
-               *flags |= IPT_RPC_RPCS;
-               break;
-
-       case '2':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "%s unexpected '!' with --strict\n", preerr);
-               if (*flags & IPT_RPC_STRC)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "%s repeated use of --strict\n", preerr);
-               rpcinfo->strict = 1;
-               *flags |= IPT_RPC_STRC;
-               break;
-
-       default:
-               return 0;
-       }
-
-       return 1;
-
-}
-
-
-static void final_check(unsigned int flags)
-{
-       if (flags != (flags | IPT_RPC_RPCS)) {
-               printf("%s option \"--rpcs\" was not used ... reverting ", preerr);
-               printf("to old \"record-rpc\" functionality ..\n");
-       }
-}
-
-
-static void print(const struct ipt_ip *ip,
-               const struct ipt_entry_match *match,
-               int numeric)
-{
-       struct ipt_rpc_info *rpcinfo = ((struct ipt_rpc_info *)match->data);
-
-
-       printf("RPCs");
-       if(rpcinfo->strict == 1)
-               printf("[strict]");
-
-       printf(": ");
-
-       if(rpcinfo->i_procs == -1) {
-               printf("any(*)");
-
-       } else {
-               print_rpcs((char *)&rpcinfo->c_procs, rpcinfo->i_procs, IPT_RPC_INT_BTH);
-       }
-       printf(" ");
-
-}
-
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       struct ipt_rpc_info *rpcinfo = ((struct ipt_rpc_info *)match->data);
-
-
-       if(rpcinfo->i_procs > -1) {
-               printf("--rpcs ");
-               print_rpcs((char *)&rpcinfo->c_procs, rpcinfo->i_procs, IPT_RPC_INT_NUM);
-               printf(" ");
-       }
-
-       if(rpcinfo->strict == 1)
-               printf("--strict ");
-
-}
-
-
-static struct iptables_match rpcstruct = { 
-       .next           = NULL,
-       .name           = "rpc",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_rpc_info)),
-       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_rpc_info)),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-
-void _init(void)
-{
-       register_match(&rpcstruct);
-}
-
index 18fe6ad..0354d19 100644 (file)
@@ -79,31 +79,6 @@ static struct option opts[] = {
        { .name = 0 }
 };
 
-static int
-service_to_port(const char *name)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, "sctp")) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-       return -1;
-}
-
-static u_int16_t
-parse_sctp_port(const char *port)
-{
-       unsigned int portnum;
-
-       DEBUGP("%s\n", port);
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid SCTP port/service `%s' specified", port);
-}
-
 static void
 parse_sctp_ports(const char *portstring, 
                 u_int16_t *ports)
@@ -114,14 +89,14 @@ parse_sctp_ports(const char *portstring,
        buffer = strdup(portstring);
        DEBUGP("%s\n", portstring);
        if ((cp = strchr(buffer, ':')) == NULL) {
-               ports[0] = ports[1] = parse_sctp_port(buffer);
+               ports[0] = ports[1] = parse_port(buffer, "sctp");
        }
        else {
                *cp = '\0';
                cp++;
 
-               ports[0] = buffer[0] ? parse_sctp_port(buffer) : 0;
-               ports[1] = cp[0] ? parse_sctp_port(cp) : 0xFFFF;
+               ports[0] = buffer[0] ? parse_port(buffer, "sctp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "sctp") : 0xFFFF;
 
                if (ports[0] > ports[1])
                        exit_error(PARAMETER_PROBLEM,
@@ -462,7 +437,8 @@ print_chunks(u_int32_t chunk_match_type,
        flag = 0;
        for (i = 0; i < 256; i++) {
                if (SCTP_CHUNKMAP_IS_SET(chunkmap, i)) {
-                       flag && printf(",");
+                       if (flag)
+                               printf(",");
                        flag = 1;
                        print_chunk(i, numeric);
                        for (j = 0; j < flag_count; j++) {
@@ -474,7 +450,8 @@ print_chunks(u_int32_t chunk_match_type,
                }
        }
 
-       flag && printf(" ");
+       if (flag)
+               printf(" ");
 out:
        return;
 }
index e485f05..cf5d19d 100644 (file)
@@ -18,7 +18,6 @@
 #include <errno.h>
 
 #include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ipt_set.h>
 #include "libipt_set.h"
 
@@ -112,7 +111,7 @@ print_match(const char *prefix, const struct ipt_set_info *info)
 
        get_set_byid(setname, info->index);
        printf("%s%s %s", 
-              (info->flags[0] & IPSET_MATCH_INV) ? "!" : "",
+              (info->flags[0] & IPSET_MATCH_INV) ? "! " : "",
               prefix,
               setname); 
        for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
index 0d6b329..02de0fa 100644 (file)
@@ -37,7 +37,7 @@ parse_bindings(const char *optarg, struct ipt_set_info *info)
        free(saved);
 }
 
-static int get_set_getsockopt(void *data, size_t * size)
+static int get_set_getsockopt(void *data, socklen_t * size)
 {
        int sockfd = -1;
        sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
@@ -51,7 +51,7 @@ static int get_set_getsockopt(void *data, size_t * size)
 static void get_set_byname(const char *setname, struct ipt_set_info *info)
 {
        struct ip_set_req_get_set req;
-       int size = sizeof(struct ip_set_req_get_set);
+       socklen_t size = sizeof(struct ip_set_req_get_set);
        int res;
 
        req.op = IP_SET_OP_GET_BYNAME;
@@ -66,7 +66,7 @@ static void get_set_byname(const char *setname, struct ipt_set_info *info)
        if (size != sizeof(struct ip_set_req_get_set))
                exit_error(OTHER_PROBLEM,
                           "Incorrect return size from kernel during ipset lookup, "
-                          "(want %d, got %d)\n",
+                          "(want %ld, got %ld)\n",
                           sizeof(struct ip_set_req_get_set), size);
        if (req.set.index == IP_SET_INVALID_ID)
                exit_error(PARAMETER_PROBLEM,
@@ -78,7 +78,7 @@ static void get_set_byname(const char *setname, struct ipt_set_info *info)
 static void get_set_byid(char * setname, ip_set_id_t index)
 {
        struct ip_set_req_get_set req;
-       int size = sizeof(struct ip_set_req_get_set);
+       socklen_t size = sizeof(struct ip_set_req_get_set);
        int res;
 
        req.op = IP_SET_OP_GET_BYINDEX;
@@ -92,7 +92,7 @@ static void get_set_byid(char * setname, ip_set_id_t index)
        if (size != sizeof(struct ip_set_req_get_set))
                exit_error(OTHER_PROBLEM,
                           "Incorrect return size from kernel during ipset lookup, "
-                          "(want %d, got %d)\n",
+                          "(want %ld, got %ld)\n",
                           sizeof(struct ip_set_req_get_set), size);
        if (req.set.name[0] == '\0')
                exit_error(PARAMETER_PROBLEM,
index acafe9a..6a784ff 100644 (file)
@@ -5,7 +5,7 @@
 #include <stdlib.h>
 #include <getopt.h>
 #include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
 #include <linux/netfilter_ipv4/ipt_state.h>
 
 #ifndef IPT_STATE_UNTRACKED
diff --git a/extensions/libipt_statistic.c b/extensions/libipt_statistic.c
new file mode 100644 (file)
index 0000000..4ed1813
--- /dev/null
@@ -0,0 +1,175 @@
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+
+#include <iptables.h>
+#include <linux/netfilter/xt_statistic.h>
+
+static void
+help(void)
+{
+       printf(
+"statistic match v%s options:\n"
+" --mode mode                    Match mode (random, nth)\n"
+" random mode:\n"
+" --probability p               Probability\n"
+" nth mode:\n"
+" --every n                     Match every nth packet\n"
+" --packet p                    Initial counter value (0 <= p <= n-1, default 0)\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "mode", 1, 0, '1' },
+       { "probability", 1, 0, '2' },
+       { "every", 1, 0, '3' },
+       { "packet", 1, 0, '4' },
+       { 0 }
+};
+
+static struct xt_statistic_info *info;
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ipt_entry *entry,
+      unsigned int *nfcache,
+      struct ipt_entry_match **match)
+{
+       double prob;
+
+       info = (void *)(*match)->data;
+
+       if (invert)
+               info->flags |= XT_STATISTIC_INVERT;
+
+       switch (c) {
+       case '1':
+               if (*flags & 0x1)
+                       exit_error(PARAMETER_PROBLEM, "double --mode");
+               if (!strcmp(optarg, "random"))
+                       info->mode = XT_STATISTIC_MODE_RANDOM;
+               else if (!strcmp(optarg, "nth"))
+                       info->mode = XT_STATISTIC_MODE_NTH;
+               else
+                       exit_error(PARAMETER_PROBLEM, "Bad mode `%s'", optarg);
+               *flags |= 0x1;
+               break;
+       case '2':
+               if (*flags & 0x2)
+                       exit_error(PARAMETER_PROBLEM, "double --probability");
+               prob = atof(optarg);
+               if (prob < 0 || prob > 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "--probability must be between 0 and 1");
+               info->u.random.probability = 0x80000000 * prob;
+               *flags |= 0x2;
+               break;
+       case '3':
+               if (*flags & 0x4)
+                       exit_error(PARAMETER_PROBLEM, "double --every");
+               if (string_to_number(optarg, 0, 0xFFFFFFFF,
+                                    &info->u.nth.every) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "cannot parse --every `%s'", optarg);
+               if (info->u.nth.every == 0)
+                       exit_error(PARAMETER_PROBLEM, "--every cannot be 0");
+               info->u.nth.every--;
+               *flags |= 0x4;
+               break;
+       case '4':
+               if (*flags & 0x8)
+                       exit_error(PARAMETER_PROBLEM, "double --packet");
+               if (string_to_number(optarg, 0, 0xFFFFFFFF,
+                                    &info->u.nth.packet) == -1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "cannot parse --packet `%s'", optarg);
+               *flags |= 0x8;
+               break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+/* Final check; must have specified --mark. */
+static void
+final_check(unsigned int flags)
+{
+       if (!(flags & 0x1))
+               exit_error(PARAMETER_PROBLEM, "no mode specified");
+       if ((flags & 0x2) && (flags & (0x4 | 0x8)))
+               exit_error(PARAMETER_PROBLEM,
+                          "both nth and random parameters given");
+       if (flags & 0x2 && info->mode != XT_STATISTIC_MODE_RANDOM)
+               exit_error(PARAMETER_PROBLEM,
+                          "--probability can only be used in random mode");
+       if (flags & 0x4 && info->mode != XT_STATISTIC_MODE_NTH)
+               exit_error(PARAMETER_PROBLEM,
+                          "--every can only be used in nth mode");
+       if (flags & 0x8 && info->mode != XT_STATISTIC_MODE_NTH)
+               exit_error(PARAMETER_PROBLEM,
+                          "--packet can only be used in nth mode");
+       info->u.nth.count = info->u.nth.every - info->u.nth.packet;
+}
+
+/* Prints out the matchinfo. */
+static void print_match(const struct xt_statistic_info *info, char *prefix)
+{
+       if (info->flags & XT_STATISTIC_INVERT)
+               printf("! ");
+
+       switch (info->mode) {
+       case XT_STATISTIC_MODE_RANDOM:
+               printf("%smode random %sprobability %f ", prefix, prefix,
+                      1.0 * info->u.random.probability / 0x80000000);
+               break;
+       case XT_STATISTIC_MODE_NTH:
+               printf("%smode nth %severy %u ", prefix, prefix,
+                      info->u.nth.every + 1);
+               if (info->u.nth.packet)
+                       printf("%spacket %u ", prefix, info->u.nth.packet);
+               break;
+       }
+}
+
+static void
+print(const struct ipt_ip *ip,
+      const struct ipt_entry_match *match,
+      int numeric)
+{
+       struct xt_statistic_info *info = (struct xt_statistic_info *)match->data;
+
+       printf("statistic ");
+       print_match(info, "");
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+{
+       struct xt_statistic_info *info = (struct xt_statistic_info *)match->data;
+
+       print_match(info, "--");
+}
+
+static struct iptables_match statistic = { 
+       .name           = "statistic",
+       .version        = IPTABLES_VERSION,
+       .size           = IPT_ALIGN(sizeof(struct xt_statistic_info)),
+       .userspacesize  = offsetof(struct xt_statistic_info, u.nth.count),
+       .help           = help,
+       .parse          = parse,
+       .final_check    = final_check,
+       .print          = print,
+       .save           = save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_match(&statistic);
+}
index 5492cfc..266b3e5 100644 (file)
@@ -307,7 +307,7 @@ print(const struct ipt_ip *ip,
        if (info->from_offset != 0)
                printf("FROM %u ", info->from_offset);
        if (info->to_offset != 0)
-               printf("TO %u", info->to_offset);
+               printf("TO %u ", info->to_offset);
 }
 
 
index f8ed249..c712b92 100644 (file)
@@ -38,30 +38,6 @@ static struct option opts[] = {
        {0}
 };
 
-static int
-service_to_port(const char *name)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, "tcp")) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-       return -1;
-}
-
-static u_int16_t
-parse_tcp_port(const char *port)
-{
-       unsigned int portnum;
-
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port)) != -1)
-               return (u_int16_t)portnum;
-
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid TCP port/service `%s' specified", port);
-}
-
 static void
 parse_tcp_ports(const char *portstring, u_int16_t *ports)
 {
@@ -70,13 +46,13 @@ parse_tcp_ports(const char *portstring, u_int16_t *ports)
 
        buffer = strdup(portstring);
        if ((cp = strchr(buffer, ':')) == NULL)
-               ports[0] = ports[1] = parse_tcp_port(buffer);
+               ports[0] = ports[1] = parse_port(buffer, "tcp");
        else {
                *cp = '\0';
                cp++;
 
-               ports[0] = buffer[0] ? parse_tcp_port(buffer) : 0;
-               ports[1] = cp[0] ? parse_tcp_port(cp) : 0xFFFF;
+               ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
 
                if (ports[0] > ports[1])
                        exit_error(PARAMETER_PROBLEM,
index e1f4405..cfafc9e 100644 (file)
@@ -1,4 +1,4 @@
-These extensions are loaded if `--protocol tcp' is specified. It
+These extensions can be used if `--protocol tcp' is specified. It
 provides the following options:
 .TP
 .BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
@@ -43,7 +43,3 @@ option is inverted.
 .TP
 .BR "--tcp-option " "[!] \fInumber\fP"
 Match if TCP option set.
-.TP
-.BR "--mss " "\fIvalue\fP[:\fIvalue\fP]"
-Match TCP SYN or SYN/ACK packets with the specified MSS value (or range),
-which control the maximum packet size for that connection.
index 5115d6b..91fe322 100644 (file)
@@ -1,4 +1,4 @@
 This matches the TCP MSS (maximum segment size) field of the TCP header.  You can only use this on TCP SYN or SYN/ACK packets, since the MSS is only negotiated during the TCP handshake at connection startup time.
 .TP
-.BI "[!] "--mss " "value[:value]"
+.BI "[!] "--mss " value[:value]"
 Match a given TCP MSS value or range.
diff --git a/extensions/libipt_time.c b/extensions/libipt_time.c
deleted file mode 100644 (file)
index dcf2dc6..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-/* Shared library add-on to iptables to add TIME matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h> /* for 'offsetof' */
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_time.h>
-#include <time.h>
-
-static int globaldays;
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-       printf(
-"TIME v%s options:\n"
-" [ --timestart value ] [ --timestop value] [ --days listofdays ] [ --datestart value ] [ --datestop value ]\n"
-"          timestart value : HH:MM (default 00:00)\n"
-"          timestop  value : HH:MM (default 23:59)\n"
-"                            Note: daylight savings time changes are not tracked\n"
-"          listofdays value: a list of days to apply\n"
-"                            from Mon,Tue,Wed,Thu,Fri,Sat,Sun\n"
-"                            Coma speparated, no space, case sensitive.\n"
-"                            Defaults to all days.\n"
-"          datestart value : YYYY[:MM[:DD[:hh[:mm[:ss]]]]]\n"
-"                            If any of month, day, hour, minute or second is\n"
-"                            not specified, then defaults to their smallest\n"
-"                            1900 <= YYYY < 2037\n"
-"                               1 <= MM <= 12\n"
-"                               1 <= DD <= 31\n"
-"                               0 <= hh <= 23\n"
-"                               0 <= mm <= 59\n"
-"                               0 <= ss <= 59\n"
-"          datestop  value : YYYY[:MM[:DD[:hh[:mm[:ss]]]]]\n"
-"                            If the whole option is ommited, default to never stop\n"
-"                            If any of month, day, hour, minute or second is\n"
-"                            not specified, then default to their smallest\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
-       { "timestart", 1, 0, '1' },
-       { "timestop", 1, 0, '2' },
-       { "days", 1, 0, '3'},
-       { "datestart", 1, 0, '4' },
-       { "datestop", 1, 0, '5' },
-       {0}
-};
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-       struct ipt_time_info *info = (struct ipt_time_info *)m->data;
-       globaldays = 0;
-        /* By default, we match on everyday */
-       info->days_match = 127;
-       /* By default, we match on every hour:min of the day */
-       info->time_start = 0;
-       info->time_stop  = 1439;  /* (23*60+59 = 1439 */
-       /* By default, we don't have any date-begin or date-end boundaries */
-       info->date_start = 0;
-       info->date_stop  = LONG_MAX;
-}
-
-/**
- * param: part1, a pointer on a string 2 chars maximum long string, that will contain the hours.
- * param: part2, a pointer on a string 2 chars maximum long string, that will contain the minutes.
- * param: str_2_parse, the string to parse.
- * return: 1 if ok, 0 if error.
- */
-static int
-split_time(char **part1, char **part2, const char *str_2_parse)
-{
-       unsigned short int i,j=0;
-       char *rpart1 = *part1;
-       char *rpart2 = *part2;
-       unsigned char found_column = 0;
-
-       /* Check the length of the string */
-       if (strlen(str_2_parse) > 5)
-               return 0;
-       /* parse the first part until the ':' */
-       for (i=0; i<2; i++)
-       {
-               if (str_2_parse[i] == ':')
-                       found_column = 1;
-               else
-                       rpart1[i] = str_2_parse[i];
-       }
-       if (!found_column)
-               i++;
-       j=i;
-       /* parse the second part */
-       for (; i<strlen(str_2_parse); i++)
-       {
-               rpart2[i-j] = str_2_parse[i];
-       }
-       /* if we are here, format should be ok. */
-       return 1;
-}
-
-static int
-parse_number(char *str, int num_min, int num_max, int *number)
-{
-       /* if the number starts with 0, replace it with a space else
-       string_to_number() will interpret it as octal !! */
-       if (strlen(str) == 0)
-               return 0;
-
-       if ((str[0] == '0') && (str[1] != '\0'))
-               str[0] = ' ';
-
-       return string_to_number(str, num_min, num_max, number);
-}
-
-static void
-parse_time_string(int *hour, int *minute, const char *time)
-{
-       char *hours;
-       char *minutes;
-       hours = (char *)malloc(3);
-       minutes = (char *)malloc(3);
-       memset(hours, 0, 3);
-       memset(minutes, 0, 3);
-
-       if (split_time((char **)&hours, (char **)&minutes, time) == 1)
-       {
-               *hour = 0;
-               *minute = 0;
-               if ((parse_number((char *)hours, 0, 23, hour) != -1) &&
-                   (parse_number((char *)minutes, 0, 59, minute) != -1))
-               {
-                       free(hours);
-                       free(minutes);
-                       return;
-               }
-       }
-
-       free(hours);
-       free(minutes);
-
-       /* If we are here, there was a problem ..*/
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid time `%s' specified, should be HH:MM format", time);
-}
-
-/* return 1->ok, return 0->error */
-static int
-parse_day(int *days, int from, int to, const char *string)
-{
-       char *dayread;
-       char *days_str[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
-       unsigned short int days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
-       unsigned int i;
-
-       dayread = (char *)malloc(4);
-       bzero(dayread, 4);
-       if ((to-from) != 3) {
-               free(dayread);
-               return 0;
-       }
-       for (i=from; i<to; i++)
-               dayread[i-from] = string[i];
-       for (i=0; i<7; i++)
-               if (strcmp(dayread, days_str[i]) == 0)
-               {
-                       *days |= days_of_week[i];
-                       free(dayread);
-                       return 1;
-               }
-       /* if we are here, we didn't read a valid day */
-       free(dayread);
-       return 0;
-}
-
-static void
-parse_days_string(int *days, const char *daystring)
-{
-       int len;
-       int i=0;
-       char *err = "invalid days `%s' specified, should be Sun,Mon,Tue... format";
-
-       len = strlen(daystring);
-       if (len < 3)
-               exit_error(PARAMETER_PROBLEM, err, daystring);  
-       while(i<len)
-       {
-               if (parse_day(days, i, i+3, daystring) == 0)
-                       exit_error(PARAMETER_PROBLEM, err, daystring);
-               i += 4;
-       }
-}
-
-static int
-parse_date_field(const char *str_to_parse, int str_to_parse_s, int start_pos,
-                 char *dest, int *next_pos)
-{
-       unsigned char found_value = 0;
-       unsigned char found_column = 0;
-       int i;
-
-       for (i=0; i<2; i++)
-       {
-               if ((i+start_pos) >= str_to_parse_s) /* don't exit boundaries of the string..  */
-                       break;
-               if (str_to_parse[i+start_pos] == ':')
-                       found_column = 1;
-               else
-               {
-                       found_value = 1;
-                       dest[i] = str_to_parse[i+start_pos];
-               }
-       }
-       if (found_value == 0)
-               return 0;
-       *next_pos = i + start_pos;
-       if (found_column == 0)
-               ++(*next_pos);
-       return 1;
-}
-
-static int
-split_date(char *year, char *month,  char *day,
-           char *hour, char *minute, char *second,
-           const char *str_to_parse)
-{
-        int i;
-        unsigned char found_column = 0;
-       int str_to_parse_s = strlen(str_to_parse);
-
-        /* Check the length of the string */
-        if ((str_to_parse_s > 19) ||  /* YYYY:MM:DD:HH:MM:SS */
-            (str_to_parse_s < 4))     /* YYYY*/
-                return 0;
-
-       /* Clear the buffers */
-        memset(year, 0, 4);
-       memset(month, 0, 2);
-       memset(day, 0, 2);
-       memset(hour, 0, 2);
-       memset(minute, 0, 2);
-       memset(second, 0, 2);
-
-       /* parse the year YYYY */
-       found_column = 0;
-       for (i=0; i<5; i++)
-       {
-               if (i >= str_to_parse_s)
-                       break;
-               if (str_to_parse[i] == ':')
-               {
-                       found_column = 1;
-                       break;
-               }
-               else
-                       year[i] = str_to_parse[i];
-       }
-       if (found_column == 1)
-               ++i;
-
-       /* parse the month if it exists */
-       if (! parse_date_field(str_to_parse, str_to_parse_s, i, month, &i))
-               return 1;
-
-       if (! parse_date_field(str_to_parse, str_to_parse_s, i, day, &i))
-               return 1;
-
-       if (! parse_date_field(str_to_parse, str_to_parse_s, i, hour, &i))
-               return 1;
-
-       if (! parse_date_field(str_to_parse, str_to_parse_s, i, minute, &i))
-               return 1;
-
-       parse_date_field(str_to_parse, str_to_parse_s, i, second, &i);
-
-        /* if we are here, format should be ok. */
-        return 1;
-}
-
-static time_t
-parse_date_string(const char *str_to_parse)
-{
-       char year[5];
-       char month[3];
-       char day[3];
-       char hour[3];
-       char minute[3];
-       char second[3];
-       struct tm t;
-       time_t temp_time;
-
-       memset(year, 0, 5);
-       memset(month, 0, 3);
-       memset(day, 0, 3);
-       memset(hour, 0, 3);
-       memset(minute, 0, 3);
-       memset(second, 0, 3);
-
-        if (split_date(year, month, day, hour, minute, second, str_to_parse) == 1)
-        {
-               memset((void *)&t, 0, sizeof(struct tm));
-               t.tm_isdst = -1;
-               t.tm_mday = 1;
-               if (!((parse_number(year, 1900, 2037, &(t.tm_year)) == -1) ||
-                     (parse_number(month, 1, 12, &(t.tm_mon)) == -1) ||
-                     (parse_number(day, 1, 31, &(t.tm_mday)) == -1) ||
-                     (parse_number(hour, 0, 9999, &(t.tm_hour)) == -1) ||
-                     (parse_number(minute, 0, 59, &(t.tm_min)) == -1) ||
-                     (parse_number(second, 0, 59, &(t.tm_sec)) == -1)))
-               {
-                       t.tm_year -= 1900;
-                       --(t.tm_mon);
-                       temp_time = mktime(&t);
-                       if (temp_time != -1)
-                               return temp_time;
-               }
-       }
-       exit_error(PARAMETER_PROBLEM,
-                  "invalid date `%s' specified, should be YYYY[:MM[:DD[:hh[:mm[:ss]]]]] format", str_to_parse);
-}
-
-#define IPT_TIME_START 0x01
-#define IPT_TIME_STOP  0x02
-#define IPT_TIME_DAYS  0x04
-#define IPT_DATE_START 0x08
-#define IPT_DATE_STOP  0x10
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ipt_entry *entry,
-      unsigned int *nfcache,
-      struct ipt_entry_match **match)
-{
-       struct ipt_time_info *timeinfo = (struct ipt_time_info *)(*match)->data;
-       int hours, minutes;
-       time_t temp_date;
-
-       switch (c)
-       {
-               /* timestart */
-       case '1':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "unexpected '!' with --timestart");
-               if (*flags & IPT_TIME_START)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --timestart twice");
-               parse_time_string(&hours, &minutes, optarg);
-               timeinfo->time_start = (hours * 60) + minutes;
-               *flags |= IPT_TIME_START;
-               break;
-               /* timestop */
-       case '2':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "unexpected '!' with --timestop");
-               if (*flags & IPT_TIME_STOP)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --timestop twice");
-               parse_time_string(&hours, &minutes, optarg);
-               timeinfo->time_stop = (hours * 60) + minutes;
-               *flags |= IPT_TIME_STOP;
-               break;
-
-               /* days */
-       case '3':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "unexpected '!' with --days");
-               if (*flags & IPT_TIME_DAYS)
-                        exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --days twice");
-               parse_days_string(&globaldays, optarg);
-               timeinfo->days_match = globaldays;
-               *flags |= IPT_TIME_DAYS;
-               break;
-
-               /* datestart */
-       case '4':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "unexpected '!' with --datestart");
-               if (*flags & IPT_DATE_START)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --datestart twice");
-               temp_date = parse_date_string(optarg);
-               timeinfo->date_start = temp_date;
-               *flags |= IPT_DATE_START;
-               break;
-
-               /* datestop*/
-       case '5':
-               if (invert)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "unexpected '!' with --datestop");
-               if (*flags & IPT_DATE_STOP)
-                       exit_error(PARAMETER_PROBLEM,
-                                   "Can't specify --datestop twice");
-               temp_date = parse_date_string(optarg);
-               timeinfo->date_stop = temp_date;
-               *flags |= IPT_DATE_STOP;
-               break;
-       default:
-               return 0;
-       }
-       return 1;
-}
-
-/* Final check */
-static void
-final_check(unsigned int flags)
-{
-       /* Nothing to do */
-}
-
-
-static void
-print_days(int daynum)
-{
-       char *days[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
-       unsigned short int days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
-       unsigned short int i, nbdays=0;
-
-       for (i=0; i<7; i++) {
-               if ((days_of_week[i] & daynum) == days_of_week[i])
-               {
-                       if (nbdays>0)
-                               printf(",%s", days[i]);
-                       else
-                               printf("%s", days[i]);
-                       ++nbdays;
-               }
-       }
-       printf(" ");
-}
-
-static void
-divide_time(int fulltime, int *hours, int *minutes)
-{
-       *hours = fulltime / 60;
-       *minutes = fulltime % 60;
-}
-
-static void
-print_date(time_t date, char *command)
-{
-       struct tm *t;
-
-       /* If it's default value, don't print..*/
-       if (((date == 0) || (date == LONG_MAX)) && (command != NULL))
-               return;
-       t = localtime(&date);
-       if (command != NULL)
-               printf("%s %d:%d:%d:%d:%d:%d ", command, (t->tm_year + 1900), (t->tm_mon + 1),
-                       t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
-        else
-               printf("%d-%d-%d %d:%d:%d ", (t->tm_year + 1900), (t->tm_mon + 1),
-                       t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
-      const struct ipt_entry_match *match,
-      int numeric)
-{
-       struct ipt_time_info *time = ((struct ipt_time_info *)match->data);
-       int hour_start, hour_stop, minute_start, minute_stop;
-
-       divide_time(time->time_start, &hour_start, &minute_start);
-       divide_time(time->time_stop, &hour_stop, &minute_stop);
-       printf("TIME ");
-       if (time->time_start != 0)
-               printf("from %d:%d ", hour_start, minute_start);
-       if (time->time_stop != 1439) /* 23*60+59 = 1439 */
-               printf("to %d:%d ", hour_stop, minute_stop);
-       printf("on ");
-       if (time->days_match == 127)
-               printf("all days ");
-       else
-               print_days(time->days_match);
-       if (time->date_start != 0)
-       {
-               printf("starting from ");
-               print_date(time->date_start, NULL);
-       }
-       if (time->date_stop != LONG_MAX)
-       {
-               printf("until date ");
-               print_date(time->date_stop, NULL);
-       }
-}
-
-/* Saves the data in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
-       struct ipt_time_info *time = ((struct ipt_time_info *)match->data);
-       int hour_start, hour_stop, minute_start, minute_stop;
-
-       divide_time(time->time_start, &hour_start, &minute_start);
-       divide_time(time->time_stop, &hour_stop, &minute_stop);
-       if (time->time_start != 0)
-               printf("--timestart %.2d:%.2d ",
-                       hour_start, minute_start);
-       
-       if (time->time_stop != 1439) /* 23*60+59 = 1439 */
-               printf("--timestop %.2d:%.2d ",
-                       hour_stop, minute_stop);
-       
-       if (time->days_match != 127)
-       {
-               printf("--days ");
-               print_days(time->days_match);
-               printf(" ");
-       }
-       print_date(time->date_start, "--datestart");
-       print_date(time->date_stop, "--datestop");
-}
-
-/* have to use offsetof() instead of IPT_ALIGN(), since kerneltime must not
- * be compared when user deletes rule with '-D' */
-static
-struct iptables_match timestruct = {
-       .next           = NULL,
-       .name           = "time",
-       .version        = IPTABLES_VERSION,
-       .size           = IPT_ALIGN(sizeof(struct ipt_time_info)),
-       .userspacesize  = offsetof(struct ipt_time_info, kerneltime),
-       .help           = &help,
-       .init           = &init,
-       .parse          = &parse,
-       .final_check    = &final_check,
-       .print          = &print,
-       .save           = &save,
-       .extra_opts     = opts
-};
-
-void _init(void)
-{
-       register_match(&timestruct);
-}
diff --git a/extensions/libipt_time.man b/extensions/libipt_time.man
deleted file mode 100644 (file)
index 94b4053..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-This matches if the packet arrival time/date is within a given range. All options are facultative.
-.TP
-.BI " --timestart " "value"
-Match only if it is after `value' (Inclusive, format: HH:MM ; default 00:00).
-.TP
-.BI "--timestop  " "value"
-Match only if it is before `value' (Inclusive, format: HH:MM ; default 23:59).
-.TP
-.BI "--days " "listofdays"
-Match only if today is one of the given days. (format: Mon,Tue,Wed,Thu,Fri,Sat,Sun ; default everyday)
-.TP
-.BI "--datestart " "date"
-Match only if it is after `date' (Inclusive, format: YYYY[:MM[:DD[:hh[:mm[:ss]]]]] ; h,m,s start from 0 ; default to 1970)
-.TP
-.BI "--datestop " "date"
-Match only if it is before `date' (Inclusive, format: YYYY[:MM[:DD[:hh[:mm[:ss]]]]] ; h,m,s start from 0 ; default to 2037)
index 7504510..cf9e63a 100644 (file)
@@ -93,7 +93,6 @@ u_int32_t parse_number(char **s, int pos)
 static int
 parse(int c, char **argv, int invert, unsigned int *flags,
       const struct ipt_entry *entry,
-      unsigned int *nfcache,
       struct ipt_entry_match **match)
 {
        struct ipt_u32 *data = (struct ipt_u32 *)(*match)->data;
index f45f364..7f461d8 100644 (file)
@@ -30,30 +30,6 @@ static struct option opts[] = {
        {0}
 };
 
-static int
-service_to_port(const char *name)
-{
-       struct servent *service;
-
-       if ((service = getservbyname(name, "udp")) != NULL)
-               return ntohs((unsigned short) service->s_port);
-
-               return -1;
-}
-
-static u_int16_t
-parse_udp_port(const char *port)
-{
-       unsigned int portnum;
-
-       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
-           (portnum = service_to_port(port)) != -1)
-               return (u_int16_t)portnum;
-
-               exit_error(PARAMETER_PROBLEM,
-                          "invalid UDP port/service `%s' specified", port);
-       }
-
 static void
 parse_udp_ports(const char *portstring, u_int16_t *ports)
 {
@@ -62,13 +38,13 @@ parse_udp_ports(const char *portstring, u_int16_t *ports)
 
        buffer = strdup(portstring);
        if ((cp = strchr(buffer, ':')) == NULL)
-               ports[0] = ports[1] = parse_udp_port(buffer);
+               ports[0] = ports[1] = parse_port(buffer, "udp");
        else {
                *cp = '\0';
                cp++;
 
-               ports[0] = buffer[0] ? parse_udp_port(buffer) : 0;
-               ports[1] = cp[0] ? parse_udp_port(cp) : 0xFFFF;
+               ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0;
+               ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF;
 
                if (ports[0] > ports[1])
                        exit_error(PARAMETER_PROBLEM,
index 0408479..1d5e590 100644 (file)
@@ -1,4 +1,4 @@
-These extensions are loaded if `--protocol udp' is specified.  It
+These extensions can be used if `--protocol udp' is specified.  It
 provides the following options:
 .TP
 .BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
index 549e041..8afe2ce 100644 (file)
@@ -8,11 +8,37 @@
 #define IP6T_LIB_DIR "/usr/local/lib/iptables"
 #endif
 
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+#ifndef IPPROTO_DCCP
+#define IPPROTO_DCCP 33
+#endif
+#ifndef IPPROTO_UDPLITE
+#define IPPROTO_UDPLITE 136
+#endif
+
+#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
+#define IP6T_SO_GET_REVISION_MATCH     68
+#define IP6T_SO_GET_REVISION_TARGET    69
+
+struct ip6t_get_revision
+{
+       char name[IP6T_FUNCTION_MAXNAMELEN-1];
+
+       u_int8_t revision;
+};
+#endif /* IP6T_SO_GET_REVISION_MATCH   Old kernel source */
+
 struct ip6tables_rule_match
 {
        struct ip6tables_rule_match *next;
 
        struct ip6tables_match *match;
+
+       /* Multiple matches of the same type: the ones before
+          the current one are completed from parsing point of view */  
+       unsigned int completed;
 };
 
 /* Include file for additions: new matches and targets. */
@@ -22,6 +48,9 @@ struct ip6tables_match
 
        ip6t_chainlabel name;
 
+       /* Revision of match (0 by default). */
+       u_int8_t revision;
+
        const char *version;
 
        /* Size of match data. */
@@ -122,6 +151,8 @@ extern int line;
 extern void register_match6(struct ip6tables_match *me);
 extern void register_target6(struct ip6tables_target *me);
 
+extern int service_to_port(const char *name, const char *proto);
+extern u_int16_t parse_port(const char *port, const char *proto);
 extern int do_command6(int argc, char *argv[], char **table,
                       ip6tc_handle_t *handle);
 /* Keeping track of external matches and targets: linked lists. */
@@ -143,6 +174,8 @@ extern void parse_interface(const char *arg, char *vianame, unsigned char *mask)
 extern int for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *), int verbose, int builtinstoo, ip6tc_handle_t *handle);
 extern int flush_entries(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
 extern int delete_chain(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
-extern int ip6tables_insmod(const char *modname, const char *modprobe);
+extern int
+ip6tables_insmod(const char *modname, const char *modprobe, int quiet);
+extern int load_ip6tables_ko(const char *modprobe, int quiet);
 
 #endif /*_IP6TABLES_USER_H*/
index bf71e52..cd51428 100644 (file)
 #ifndef IPPROTO_SCTP
 #define IPPROTO_SCTP 132
 #endif
+#ifndef IPPROTO_DCCP
+#define IPPROTO_DCCP 33
+#endif
+#ifndef IPPROTO_UDPLITE
+#define IPPROTO_UDPLITE        136
+#endif
 
 #ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
 #define IPT_SO_GET_REVISION_MATCH      (IPT_BASE_CTL + 2)
@@ -29,6 +35,10 @@ struct iptables_rule_match
        struct iptables_rule_match *next;
 
        struct iptables_match *match;
+
+       /* Multiple matches of the same type: the ones before
+          the current one are completed from parsing point of view */  
+       unsigned int completed;
 };
 
 /* Include file for additions: new matches and targets. */
@@ -144,7 +154,10 @@ extern int line;
 extern void register_match(struct iptables_match *me);
 extern void register_target(struct iptables_target *me);
 
+extern int service_to_port(const char *name, const char *proto);
+extern u_int16_t parse_port(const char *port, const char *proto);
 extern struct in_addr *dotted_to_addr(const char *dotted);
+extern struct in_addr *dotted_to_mask(const char *dotted);
 extern char *addr_to_dotted(const struct in_addr *addrp);
 extern char *addr_to_anyname(const struct in_addr *addr);
 extern char *mask_to_dotted(const struct in_addr *mask);
index 28bda9f..3b29327 100644 (file)
@@ -5,7 +5,8 @@
 enum exittype {
        OTHER_PROBLEM = 1,
        PARAMETER_PROBLEM,
-       VERSION_PROBLEM
+       VERSION_PROBLEM,
+       RESOURCE_PROBLEM
 };
 
 /* this is a special 64bit data type that is 8-byte aligned */
@@ -26,17 +27,26 @@ extern int string_to_number_ll(const char *,
                            unsigned long long int, 
                            unsigned long long int,
                            unsigned long long *);
-extern int iptables_insmod(const char *modname, const char *modprobe);
+extern int
+iptables_insmod(const char *modname, const char *modprobe, int quiet);
+extern int load_iptables_ko(const char *modprobe, int quiet);
 void exit_error(enum exittype, char *, ...)__attribute__((noreturn,
                                                          format(printf,2,3)));
 extern const char *program_name, *program_version;
 extern char *lib_dir;
 
+#define _init __attribute__((constructor)) my_init
 #ifdef NO_SHARED_LIBS
 # ifdef _INIT
+#  undef _init
 #  define _init _INIT
 # endif
   extern void init_extensions(void);
 #endif
 
+#define __be32 u_int32_t
+#define __le32 u_int32_t
+#define __be16 u_int16_t
+#define __le16 u_int16_t
+
 #endif /*_IPTABLES_COMMON_H*/
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
new file mode 100644 (file)
index 0000000..3b452a6
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef _NF_CONNTRACK_COMMON_H
+#define _NF_CONNTRACK_COMMON_H
+/* Connection state tracking for netfilter.  This is separated from,
+   but required by, the NAT layer; it can also be used by an iptables
+   extension. */
+enum ip_conntrack_info
+{
+       /* Part of an established connection (either direction). */
+       IP_CT_ESTABLISHED,
+
+       /* Like NEW, but related to an existing connection, or ICMP error
+          (in either direction). */
+       IP_CT_RELATED,
+
+       /* Started a new connection to track (only
+           IP_CT_DIR_ORIGINAL); may be a retransmission. */
+       IP_CT_NEW,
+
+       /* >= this indicates reply direction */
+       IP_CT_IS_REPLY,
+
+       /* Number of distinct IP_CT types (no NEW in reply dirn). */
+       IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
+};
+
+/* Bitset representing status of connection. */
+enum ip_conntrack_status {
+       /* It's an expected connection: bit 0 set.  This bit never changed */
+       IPS_EXPECTED_BIT = 0,
+       IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
+
+       /* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
+       IPS_SEEN_REPLY_BIT = 1,
+       IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
+
+       /* Conntrack should never be early-expired. */
+       IPS_ASSURED_BIT = 2,
+       IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+       /* Connection is confirmed: originating packet has left box */
+       IPS_CONFIRMED_BIT = 3,
+       IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
+
+       /* Connection needs src nat in orig dir.  This bit never changed. */
+       IPS_SRC_NAT_BIT = 4,
+       IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
+
+       /* Connection needs dst nat in orig dir.  This bit never changed. */
+       IPS_DST_NAT_BIT = 5,
+       IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
+
+       /* Both together. */
+       IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
+
+       /* Connection needs TCP sequence adjusted. */
+       IPS_SEQ_ADJUST_BIT = 6,
+       IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
+
+       /* NAT initialization bits. */
+       IPS_SRC_NAT_DONE_BIT = 7,
+       IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
+
+       IPS_DST_NAT_DONE_BIT = 8,
+       IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
+
+       /* Both together */
+       IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
+
+       /* Connection is dying (removed from lists), can not be unset. */
+       IPS_DYING_BIT = 9,
+       IPS_DYING = (1 << IPS_DYING_BIT),
+
+       /* Connection has fixed timeout. */
+       IPS_FIXED_TIMEOUT_BIT = 10,
+       IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+};
+
+/* Connection tracking event bits */
+enum ip_conntrack_events
+{
+       /* New conntrack */
+       IPCT_NEW_BIT = 0,
+       IPCT_NEW = (1 << IPCT_NEW_BIT),
+
+       /* Expected connection */
+       IPCT_RELATED_BIT = 1,
+       IPCT_RELATED = (1 << IPCT_RELATED_BIT),
+
+       /* Destroyed conntrack */
+       IPCT_DESTROY_BIT = 2,
+       IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
+
+       /* Timer has been refreshed */
+       IPCT_REFRESH_BIT = 3,
+       IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
+
+       /* Status has changed */
+       IPCT_STATUS_BIT = 4,
+       IPCT_STATUS = (1 << IPCT_STATUS_BIT),
+
+       /* Update of protocol info */
+       IPCT_PROTOINFO_BIT = 5,
+       IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
+
+       /* Volatile protocol info */
+       IPCT_PROTOINFO_VOLATILE_BIT = 6,
+       IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
+
+       /* New helper for conntrack */
+       IPCT_HELPER_BIT = 7,
+       IPCT_HELPER = (1 << IPCT_HELPER_BIT),
+
+       /* Update of helper info */
+       IPCT_HELPINFO_BIT = 8,
+       IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
+
+       /* Volatile helper info */
+       IPCT_HELPINFO_VOLATILE_BIT = 9,
+       IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
+
+       /* NAT info */
+       IPCT_NATINFO_BIT = 10,
+       IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+
+       /* Counter highest bit has been set */
+       IPCT_COUNTER_FILLING_BIT = 11,
+       IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
+};
+
+enum ip_conntrack_expect_events {
+       IPEXP_NEW_BIT = 0,
+       IPEXP_NEW = (1 << IPEXP_NEW_BIT),
+};
+
+#endif /* _NF_CONNTRACK_COMMON_H */
diff --git a/include/linux/netfilter/nf_conntrack_tuple.h b/include/linux/netfilter/nf_conntrack_tuple.h
new file mode 100644 (file)
index 0000000..cd5044e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Definitions and Declarations for tuple.
+ *
+ * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
+ *     - generalize L3 protocol dependent part.
+ *
+ * Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
+ */
+
+#ifndef _NF_CONNTRACK_TUPLE_H
+#define _NF_CONNTRACK_TUPLE_H
+
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+
+/* A `tuple' is a structure containing the information to uniquely
+  identify a connection.  ie. if two packets have the same tuple, they
+  are in the same connection; if not, they are not.
+
+  We divide the structure along "manipulatable" and
+  "non-manipulatable" lines, for the benefit of the NAT code.
+*/
+
+#define NF_CT_TUPLE_L3SIZE     4
+
+/* The l3 protocol-specific manipulable parts of the tuple: always in
+   network order! */
+union nf_conntrack_address {
+       u_int32_t all[NF_CT_TUPLE_L3SIZE];
+       __be32 ip;
+       __be32 ip6[4];
+};
+
+/* The protocol-specific manipulable parts of the tuple: always in
+   network order! */
+union nf_conntrack_man_proto
+{
+       /* Add other protocols here. */
+       u_int16_t all;
+
+       struct {
+               __be16 port;
+       } tcp;
+       struct {
+               __be16 port;
+       } udp;
+       struct {
+               __be16 id;
+       } icmp;
+       struct {
+               __be16 port;
+       } sctp;
+       struct {
+               __be16 key;     /* GRE key is 32bit, PPtP only uses 16bit */
+       } gre;
+};
+
+/* The manipulable part of the tuple. */
+struct nf_conntrack_man
+{
+       union nf_conntrack_address u3;
+       union nf_conntrack_man_proto u;
+       /* Layer 3 protocol */
+       u_int16_t l3num;
+};
+
+/* This contains the information to distinguish a connection. */
+struct nf_conntrack_tuple
+{
+       struct nf_conntrack_man src;
+
+       /* These are the parts of the tuple which are fixed. */
+       struct {
+               union nf_conntrack_address u3;
+               union {
+                       /* Add other protocols here. */
+                       u_int16_t all;
+
+                       struct {
+                               __be16 port;
+                       } tcp;
+                       struct {
+                               __be16 port;
+                       } udp;
+                       struct {
+                               u_int8_t type, code;
+                       } icmp;
+                       struct {
+                               __be16 port;
+                       } sctp;
+                       struct {
+                               __be16 key;
+                       } gre;
+               } u;
+
+               /* The protocol. */
+               u_int8_t protonum;
+
+               /* The direction (for tuplehash) */
+               u_int8_t dir;
+       } dst;
+};
+
+#endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h
new file mode 100644 (file)
index 0000000..8e145f0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _NF_CONNTRACK_TUPLE_COMMON_H
+#define _NF_CONNTRACK_TUPLE_COMMON_H
+
+enum ip_conntrack_dir
+{
+       IP_CT_DIR_ORIGINAL,
+       IP_CT_DIR_REPLY,
+       IP_CT_DIR_MAX
+};
+
+#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
+
+#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h
new file mode 100644 (file)
index 0000000..5d3b5e0
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _NF_NAT_H
+#define _NF_NAT_H
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/nf_conntrack_tuple.h>
+
+#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
+
+enum nf_nat_manip_type
+{
+       IP_NAT_MANIP_SRC,
+       IP_NAT_MANIP_DST
+};
+
+/* SRC manip occurs POST_ROUTING or LOCAL_IN */
+#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN)
+
+#define IP_NAT_RANGE_MAP_IPS 1
+#define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4
+
+/* Single range specification. */
+struct nf_nat_range
+{
+       /* Set to OR of flags above. */
+       unsigned int flags;
+
+       /* Inclusive: network order. */
+       __be32 min_ip, max_ip;
+
+       /* Inclusive: network order */
+       union nf_conntrack_man_proto min, max;
+};
+
+/* For backwards compat: don't use in modern code. */
+struct nf_nat_multi_range_compat
+{
+       unsigned int rangesize; /* Must be 1. */
+
+       /* hangs off end. */
+       struct nf_nat_range range[1];
+};
+
+#define ip_nat_range nf_nat_range
+#define ip_nat_multi_range nf_nat_multi_range_compat
+#endif
index 9f074c6..c8661b8 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef _IPT_CONNTRACK_H
 #define _IPT_CONNTRACK_H
 
-#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
 
 /* backwards compatibility crap. only exists in userspace - HW */
 #include <linux/version.h>
diff --git a/include/linux/netfilter_ipv6/ip6t_TCPMSS.h b/include/linux/netfilter_ipv6/ip6t_TCPMSS.h
new file mode 100644 (file)
index 0000000..412d1cb
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _IP6T_TCPMSS_H
+#define _IP6T_TCPMSS_H
+
+struct ip6t_tcpmss_info {
+       u_int16_t mss;
+};
+
+#define IP6T_TCPMSS_CLAMP_PMTU 0xffff
+
+#endif /*_IP6T_TCPMSS_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_multiport.h b/include/linux/netfilter_ipv6/ip6t_multiport.h
new file mode 100644 (file)
index 0000000..8c2cc9d
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _IP6T_MULTIPORT_H
+#define _IP6T_MULTIPORT_H
+
+enum ip6t_multiport_flags
+{
+       IP6T_MULTIPORT_SOURCE,
+       IP6T_MULTIPORT_DESTINATION,
+       IP6T_MULTIPORT_EITHER
+};
+
+#define IP6T_MULTI_PORTS       15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct ip6t_multiport
+{
+       u_int8_t flags;                         /* Type of comparison */
+       u_int8_t count;                         /* Number of ports */
+       u_int16_t ports[IP6T_MULTI_PORTS];      /* Ports */
+};
+
+struct ip6t_multiport_v1
+{
+       u_int8_t flags;                         /* Type of comparison */
+       u_int8_t count;                         /* Number of ports */
+       u_int16_t ports[IP6T_MULTI_PORTS];      /* Ports */
+       u_int8_t pflags[IP6T_MULTI_PORTS];      /* Port flags */
+       u_int8_t invert;                        /* Invert flag */
+};
+
+#endif /*_IP6T_MULTIPORT_H*/
index 38aa2d6..a607e18 100644 (file)
@@ -7,7 +7,7 @@
  *     Rusty Russell <rusty@linuxcare.com.au>
  * This code is distributed under the terms of GNU GPL v2
  *
- * $Id: ip6tables-restore.c 3980 2005-06-12 15:54:15Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org $
+ * $Id: ip6tables-restore.c 6828 2007-05-10 15:00:39Z /C=EU/ST=EU/CN=Patrick McHardy/emailAddress=kaber@trash.net $
  */
 
 #include <getopt.h>
@@ -62,19 +62,19 @@ ip6tc_handle_t create_handle(const char *tablename, const char* modprobe)
 
        if (!handle) {
                /* try to insmod the module if iptc_init failed */
-               ip6tables_insmod("ip6_tables", modprobe);
+               ip6tables_insmod("ip6_tables", modprobe, 0);
                handle = ip6tc_init(tablename);
        }
 
        if (!handle) {
-               exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
+               exit_error(PARAMETER_PROBLEM, "%s: unable to initialize "
                        "table '%s'\n", program_name, tablename);
                exit(1);
        }
        return handle;
 }
 
-int parse_counters(char *string, struct ip6t_counters *ctr)
+static int parse_counters(char *string, struct ip6t_counters *ctr)
 {
        return (sscanf(string, "[%llu:%llu]", (unsigned long long *)&ctr->pcnt, (unsigned long long *)&ctr->bcnt) == 2);
 }
@@ -154,13 +154,13 @@ int main(int argc, char *argv[])
        if (optind == argc - 1) {
                in = fopen(argv[optind], "r");
                if (!in) {
-                       fprintf(stderr, "Can't open %s: %s", argv[optind],
+                       fprintf(stderr, "Can't open %s: %s\n", argv[optind],
                                strerror(errno));
                        exit(1);
                }
        }
        else if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline");
+               fprintf(stderr, "Unknown arguments found on commandline\n");
                exit(1);
        }
        else in = stdin;
@@ -266,7 +266,10 @@ int main(int argc, char *argv[])
                                        char *ctrs;
                                        ctrs = strtok(NULL, " \t\n");
 
-                                       parse_counters(ctrs, &count);
+                                       if (!ctrs || !parse_counters(ctrs, &count))
+                                               exit_error(PARAMETER_PROBLEM,
+                                                         "invalid policy counters "
+                                                         "for chain '%s'\n", chain);
 
                                } else {
                                        memset(&count, 0, 
index 37b1f19..479a92b 100644 (file)
@@ -125,7 +125,7 @@ static void print_ip(char *prefix, const struct in6_addr *ip, const struct in6_a
        char buf[51];
        int l = ipv6_prefix_length(mask);
 
-       if (!mask && !ip)
+       if (l == 0 && !invert)
                return;
 
        printf("%s %s%s",
@@ -351,7 +351,7 @@ int main(int argc, char *argv[])
        }
 
        if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline");
+               fprintf(stderr, "Unknown arguments found on commandline\n");
                exit(1);
        }
 
index bf24d55..8528b8e 100644 (file)
@@ -480,8 +480,9 @@ Jozsef Kadlecsik wrote the REJECT target.
 .PP
 Harald Welte wrote the ULOG and NFQUEUE target, the new libiptc, aswell as TTL match+target and libipulog.
 .PP
-The Netfilter Core Team is: Marc Boucher, Martin Josefsson, Jozsef Kadlecsik,
-James Morris, Harald Welte and Rusty Russell.
+The Netfilter Core Team is: Marc Boucher, Martin Josefsson, Yasuyuki Kozakai,
+Jozsef Kadlecsik, Patrick McHardy, James Morris, Pablo Neira Ayuso,
+Harald Welte and Rusty Russell.
 .PP
 ip6tables man page created by Andras Kis-Szabo, based on
 iptables man page written by Herve Eychenne <rv@wallfire.org>.
index 6afe68f..f316c7a 100644 (file)
@@ -81,8 +81,7 @@
 #define CMD_NEW_CHAIN          0x0100U
 #define CMD_DELETE_CHAIN       0x0200U
 #define CMD_SET_POLICY         0x0400U
-#define CMD_CHECK              0x0800U
-#define CMD_RENAME_CHAIN       0x1000U
+#define CMD_RENAME_CHAIN       0x0800U
 #define NUMBER_OF_CMD  13
 static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
                                 'N', 'X', 'P', 'E' };
@@ -159,20 +158,19 @@ static unsigned int global_option_offset = 0;
 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Linux vs FreeBSD" */
 {
-       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  --line */
-/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x'},
-/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x'},
-/*LIST*/      {' ','x','x','x','x',' ',' ','x','x',' '},
-/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x'},
-/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x'},
-/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x'},
-/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x'},
-/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x'},
-/*CHECK*/     {'x','+','+','+','x',' ','x',' ',' ','x'},
-/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x'}
+       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  --line -c */
+/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' '},
+/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x','x'},
+/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x'},
+/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' '},
+/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' '},
+/*LIST*/      {' ','x','x','x','x',' ',' ','x','x',' ','x'},
+/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x','x'},
+/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x','x'},
+/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
+/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
+/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x'},
+/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x','x'}
 };
 
 static int inverse_for_options[NUMBER_OF_OPT] =
@@ -186,13 +184,17 @@ static int inverse_for_options[NUMBER_OF_OPT] =
 /* -x */ 0,
 /* -i */ IP6T_INV_VIA_IN,
 /* -o */ IP6T_INV_VIA_OUT,
-/*--line*/ 0
+/*--line*/ 0,
+/* -c */ 0,
 };
 
 const char *program_version;
 const char *program_name;
 char *lib_dir;
 
+/* the path to command to load kernel module */
+const char *modprobe = NULL;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct ip6tables_match *ip6tables_matches = NULL;
 struct ip6tables_target *ip6tables_targets = NULL;
@@ -217,13 +219,20 @@ struct pprot {
 #define IPPROTO_AH 51
 #endif
 #endif
+#ifndef IPPROTO_MH
+#define IPPROTO_MH 135
+#endif
 
 static const struct pprot chain_protos[] = {
        { "tcp", IPPROTO_TCP },
        { "udp", IPPROTO_UDP },
+       { "udplite", IPPROTO_UDPLITE },
        { "icmpv6", IPPROTO_ICMPV6 },
+       { "ipv6-icmp", IPPROTO_ICMPV6 },
        { "esp", IPPROTO_ESP },
        { "ah", IPPROTO_AH },
+       { "ipv6-mh", IPPROTO_MH },
+       { "mh", IPPROTO_MH },
        { "all", 0 },
 };
 
@@ -245,6 +254,30 @@ proto_to_name(u_int8_t proto, int nolookup)
        return NULL;
 }
 
+int
+service_to_port(const char *name, const char *proto)
+{
+       struct servent *service;
+
+       if ((service = getservbyname(name, proto)) != NULL)
+               return ntohs((unsigned short) service->s_port);
+
+       return -1;
+}
+
+u_int16_t
+parse_port(const char *port, const char *proto)
+{
+       unsigned int portnum;
+
+       if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
+           (portnum = service_to_port(port, proto)) != -1)
+               return (u_int16_t)portnum;
+
+       exit_error(PARAMETER_PROBLEM,
+                  "invalid port/service `%s' specified", port);
+}
+
 static void
 in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
 {
@@ -710,37 +743,46 @@ parse_hostnetworkmask(const char *name, struct in6_addr **addrpp,
 }
 
 struct ip6tables_match *
-find_match(const char *name, enum ip6t_tryload tryload, struct ip6tables_rule_match **matches)
+find_match(const char *match_name, enum ip6t_tryload tryload, struct ip6tables_rule_match **matches)
 {
        struct ip6tables_match *ptr;
-       int icmphack = 0;
+       const char *icmp6 = "icmp6";
+       const char *name;
   
        /* This is ugly as hell. Nonetheless, there is no way of changing
         * this without hurting backwards compatibility */
-       if ( (strcmp(name,"icmpv6") == 0) ||
-            (strcmp(name,"ipv6-icmp") == 0) ||
-            (strcmp(name,"icmp6") == 0) ) icmphack = 1;
+       if ( (strcmp(match_name,"icmpv6") == 0) ||
+            (strcmp(match_name,"ipv6-icmp") == 0) ||
+            (strcmp(match_name,"icmp6") == 0) )
+               name = icmp6;
+       else
+               name = match_name;
  
-       if (!icmphack) {
-               for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
-                       if (strcmp(name, ptr->name) == 0)
-                               break;
-               }
-       } else {
-               for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
-                       if (strcmp("icmp6", ptr->name) == 0)
-                               break;
-               }
-       }
+       for (ptr = ip6tables_matches; ptr; ptr = ptr->next) {
+               if (strcmp(name, ptr->name) == 0) {
+                       struct ip6tables_match *clone;
+                       
+                       /* First match of this type: */
+                       if (ptr->m == NULL)
+                               break;
+
+                       /* Second and subsequent clones */
+                       clone = fw_malloc(sizeof(struct ip6tables_match));
+                       memcpy(clone, ptr, sizeof(struct ip6tables_match));
+                       clone->mflags = 0;
+                       /* This is a clone: */
+                       clone->next = clone;
+
+                       ptr = clone;
+                       break;
+               }
+       }
 
 #ifndef NO_SHARED_LIBS
        if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
                char path[strlen(lib_dir) + sizeof("/libip6t_.so")
                         + strlen(name)];
-               if (!icmphack)
-                       sprintf(path, "%s/libip6t_%s.so", lib_dir, name);
-               else
-                       sprintf(path, "%s/libip6t_%s.so", lib_dir, "icmpv6");
+               sprintf(path, "%s/libip6t_%s.so", lib_dir, name);
                if (dlopen(path, RTLD_NOW)) {
                        /* Found library.  If it didn't register itself,
                           maybe they specified target as match. */
@@ -774,8 +816,12 @@ find_match(const char *name, enum ip6t_tryload tryload, struct ip6tables_rule_ma
 
                newentry = fw_malloc(sizeof(struct ip6tables_rule_match));
 
-               for (i = matches; *i; i = &(*i)->next);
+               for (i = matches; *i; i = &(*i)->next) {
+                       if (strcmp(name, (*i)->match->name) == 0)
+                               (*i)->completed = 1;
+               }
                newentry->match = ptr;
+               newentry->completed = 0;
                newentry->next = NULL;
                *i = newentry;
        }
@@ -808,6 +854,13 @@ parse_protocol(const char *s)
        if (string_to_number(s, 0, 255, &proto) == -1) {
                struct protoent *pent;
 
+               /* first deal with the special case of 'all' to prevent
+                * people from being able to redefine 'all' in nsswitch
+                * and/or provoke expensive [not working] ldap/nis/... 
+                * lookups */
+               if (!strcmp(s, "all"))
+                       return 0;
+
                if ((pent = getprotobyname(s)))
                        proto = pent->p_proto;
                else {
@@ -830,6 +883,15 @@ parse_protocol(const char *s)
        return (u_int16_t)proto;
 }
 
+/* These are invalid numbers as upper layer protocol */
+static int is_exthdr(u_int16_t proto)
+{
+       return (proto == IPPROTO_ROUTING ||
+               proto == IPPROTO_FRAGMENT ||
+               proto == IPPROTO_AH ||
+               proto == IPPROTO_DSTOPTS);
+}
+
 void parse_interface(const char *arg, char *vianame, unsigned char *mask)
 {
        int vialen = strlen(arg);
@@ -855,10 +917,10 @@ void parse_interface(const char *arg, char *vianame, unsigned char *mask)
                memset(mask, 0xFF, vialen + 1);
                memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
                for (i = 0; vianame[i]; i++) {
-                       if (!isalnum(vianame[i]) 
-                           && vianame[i] != '_' 
-                           && vianame[i] != '.') {
-                               printf("Warning: wierd character in interface"
+                       if (vianame[i] == ':' ||
+                           vianame[i] == '!' ||
+                           vianame[i] == '*') {
+                               printf("Warning: weird character in interface"
                                       " `%s' (No aliases, :, ! or *).\n",
                                       vianame);
                                break;
@@ -1047,10 +1109,53 @@ merge_options(struct option *oldopts, const struct option *newopts,
        return merge;
 }
 
+static int compatible_revision(const char *name, u_int8_t revision, int opt)
+{
+       struct ip6t_get_revision rev;
+       socklen_t s = sizeof(rev);
+       int max_rev, sockfd;
+
+       sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+       if (sockfd < 0) {
+               fprintf(stderr, "Could not open socket to kernel: %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       strcpy(rev.name, name);
+       rev.revision = revision;
+
+       load_ip6tables_ko(modprobe, 1);
+
+       max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+       if (max_rev < 0) {
+               /* Definitely don't support this? */
+               if (errno == EPROTONOSUPPORT) {
+                       close(sockfd);
+                       return 0;
+               } else if (errno == ENOPROTOOPT) {
+                       close(sockfd);
+                       /* Assume only revision 0 support (old kernel) */
+                       return (revision == 0);
+               } else {
+                       fprintf(stderr, "getsockopt failed strangely: %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+       }
+       close(sockfd);
+       return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t revision)
+{
+       return compatible_revision(name, revision, IP6T_SO_GET_REVISION_MATCH);
+}
+
 void
 register_match6(struct ip6tables_match *me)
 {
-       struct ip6tables_match **i;
+       struct ip6tables_match **i, *old;
 
        if (strcmp(me->version, program_version) != 0) {
                fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1058,12 +1163,36 @@ register_match6(struct ip6tables_match *me)
                exit(1);
        }
 
-       if (find_match(me->name, DURING_LOAD, NULL)) {
-               fprintf(stderr, "%s: match `%s' already registered.\n",
+       /* Revision field stole a char from name. */
+       if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+               fprintf(stderr, "%s: target `%s' has invalid name\n",
                        program_name, me->name);
                exit(1);
        }
 
+       old = find_match(me->name, DURING_LOAD, NULL);
+       if (old) {
+               if (old->revision == me->revision) {
+                       fprintf(stderr,
+                               "%s: match `%s' already registered.\n",
+                               program_name, me->name);
+                       exit(1);
+               }
+
+               /* Now we have two (or more) options, check compatibility. */
+               if (compatible_match_revision(old->name, old->revision)
+                   && old->revision > me->revision)
+                       return;
+
+               /* Replace if compatible. */
+               if (!compatible_match_revision(me->name, me->revision))
+                       return;
+
+               /* Delete old one. */
+               for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+               *i = old->next;
+       }
+       
        if (me->size != IP6T_ALIGN(me->size)) {
                fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
                        program_name, me->name, (unsigned int)me->size);
@@ -1621,10 +1750,10 @@ static char *get_modprobe(void)
        return NULL;
 }
 
-int ip6tables_insmod(const char *modname, const char *modprobe)
+int ip6tables_insmod(const char *modname, const char *modprobe, int quiet)
 {
        char *buf = NULL;
-       char *argv[3];
+       char *argv[4];
        int status;
 
        /* If they don't explicitly set it, read out of kernel */
@@ -1639,7 +1768,13 @@ int ip6tables_insmod(const char *modname, const char *modprobe)
        case 0:
                argv[0] = (char *)modprobe;
                argv[1] = (char *)modname;
-               argv[2] = NULL;
+               if (quiet) {
+                       argv[2] = "-q";
+                       argv[3] = NULL;
+               } else {
+                       argv[2] = NULL;
+                       argv[3] = NULL;
+               }
                execv(argv[0], argv);
 
                /* not usually reached */
@@ -1657,6 +1792,19 @@ int ip6tables_insmod(const char *modname, const char *modprobe)
        return -1;
 }
 
+int load_ip6tables_ko(const char *modprobe, int quiet)
+{
+       static int loaded = 0;
+       static int ret = -1;
+
+       if (!loaded) {
+               ret = ip6tables_insmod("ip6_tables", modprobe, quiet);
+               loaded = (ret == 0);
+       }
+
+       return ret;
+}
+
 static struct ip6t_entry *
 generate_entry(const struct ip6t_entry *fw,
               struct ip6tables_rule_match *matches,
@@ -1691,8 +1839,14 @@ void clear_rule_matches(struct ip6tables_rule_match **matches)
 
        for (matchp = *matches; matchp;) {
                tmp = matchp->next;
-               if (matchp->match->m)
+               if (matchp->match->m) {
                        free(matchp->match->m);
+                       matchp->match->m = NULL;
+               }
+               if (matchp->match == matchp->match->next) {
+                       free(matchp->match);
+                       matchp->match = NULL;
+               }
                free(matchp);
                matchp = tmp;
        }
@@ -1700,6 +1854,14 @@ void clear_rule_matches(struct ip6tables_rule_match **matches)
        *matches = NULL;
 }
 
+static void set_revision(char *name, u_int8_t revision)
+{
+       /* Old kernel sources don't have ".revision" field,
+          but we stole a byte from name. */
+       name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+       name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
 int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
 {
        struct ip6t_entry fw, *e = NULL;
@@ -1721,9 +1883,7 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
        struct ip6tables_target *t;
        const char *jumpto = "";
        char *protocol = NULL;
-       const char *modprobe = NULL;
        int proto_used = 0;
-       char icmp6p[] = "icmpv6";
 
        memset(&fw, 0, sizeof(fw));
 
@@ -1851,7 +2011,7 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                                newname = argv[optind++];
                        else
                                exit_error(PARAMETER_PROBLEM,
-                                          "-%c requires old-chain-name and "
+                                          "-%c requires old-chain-name and "
                                           "new-chain-name",
                                            cmd2char(CMD_RENAME_CHAIN));
                        break;
@@ -1892,8 +2052,6 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                                *protocol = tolower(*protocol);
 
                        protocol = argv[optind-1];
-                       if ( strcmp(protocol,"ipv6-icmp") == 0)
-                               protocol = icmp6p;
                        fw.ipv6.proto = parse_protocol(protocol);
                        fw.ipv6.flags |= IP6T_F_PROTO;
 
@@ -1901,6 +2059,12 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                            && (fw.ipv6.invflags & IP6T_INV_PROTO))
                                exit_error(PARAMETER_PROBLEM,
                                           "rule would never match protocol");
+                       
+                       if (is_exthdr(fw.ipv6.proto)
+                           && (fw.ipv6.invflags & IP6T_INV_PROTO) == 0)
+                               printf("Warning: never matched protocol: %s. "
+                                      "use extension match instead.\n",
+                                      protocol);
                        break;
 
                case 's':
@@ -1978,9 +2142,12 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                        m->m = fw_calloc(1, size);
                        m->m->u.match_size = size;
                        strcpy(m->m->u.user.name, m->name);
+                       set_revision(m->m->u.user.name, m->revision);
                        if (m->init != NULL)
                                m->init(m->m, &fw.nfcache);
-                       opts = merge_options(opts, m->extra_opts, &m->option_offset);
+                       if (m != m->next)
+                               /* Merge options for non-cloned matches */
+                               opts = merge_options(opts, m->extra_opts, &m->option_offset);
                }
                break;
 
@@ -2058,14 +2225,14 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                        exit_tryhelp(2);
 
                default:
-                       /* FIXME: This scheme doesn't allow two of the same
-                          matches --RR */
                        if (!target
                            || !(target->parse(c - target->option_offset,
                                               argv, invert,
                                               &target->tflags,
                                               &fw, &target->t))) {
                                for (matchp = matches; matchp; matchp = matchp->next) {
+                                       if (matchp->completed) 
+                                               continue;
                                        if (matchp->match->parse(c - matchp->match->option_offset,
                                                     argv, invert,
                                                     &matchp->match->mflags,
@@ -2080,7 +2247,7 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                                   actually hear this code suck. */
 
                                /* some explanations (after four different bugs
-                                * in 3 different releases): If we encountere a
+                                * in 3 different releases): If we encounter a
                                 * parameter, that has not been parsed yet,
                                 * it's not an option of an explicitly loaded
                                 * match or a target.  However, we support
@@ -2120,6 +2287,8 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                                        m->m = fw_calloc(1, size);
                                        m->m->u.match_size = size;
                                        strcpy(m->m->u.user.name, m->name);
+                                       set_revision(m->m->u.user.name,
+                                                    m->revision);
                                        if (m->init != NULL)
                                                m->init(m->m, &fw.nfcache);
 
@@ -2192,7 +2361,7 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle)
                *handle = ip6tc_init(*table);
 
        /* try to insmod the module if iptc_init failed */
-       if (!*handle && ip6tables_insmod("ip6_tables", modprobe) != -1)
+       if (!*handle && load_ip6tables_ko(modprobe, 0) != -1)
                *handle = ip6tc_init(*table);
 
        if (!*handle)
index 5cce591..ee0154e 100644 (file)
@@ -1,3 +1,31 @@
+2.3.0
+ - jiffies rollover bug in iptree type fixed (reported by Lukasz Nierycho
+   and others)
+ - endiannes bug in iptree type fixed (spotted by Jan Engelhardt)
+ - iptreemap type added (submitted by Sven Wegener)  
+ - 2.6.22/23 compatibility fixes (Jeremy Jacque)
+ - typo fixes in ipset (Neville D)
+ - separator changed to ':' from '%' (old one still supported) in ipset
+
+2.2.9a
+ - use correct type (socklen_t) for getsockopt (H. Nakano)
+ - incorrect return codes fixed (Tomasz Lemiech, Alexey Bortnikov)
+ - kernel header dependency removed (asm/bitops.h)
+ - ipset now tries to load in the ip_set kernel module if the protocol
+   is not available
+
+2.2.9
+ - 'ipset -N' did not generate proper return code
+ - 'limit' module parameter added to the kernel modules of the
+   iphash, ipporthash, nethash and iptree type of sets so that
+   the maximal number of elements can now be limited
+ - zero valued entries (port 0 or IP address 0.0.0.0) were
+   detected as members of the hash/tree kind of sets
+   (reported by Andrew Kraslavsky)
+ - list and save operations used the external identifier
+   of the sets for the bindings instead of the internal one
+   (reported by Amin Azez)
+
 2.2.8
  - Nasty off-by-one bug fixed in iptree type of sets
    (bug reported by Pablo Sole)
index 087a9dd..5593e53 100644 (file)
@@ -8,7 +8,7 @@ ifndef KERNEL_DIR
 KERNEL_DIR=/usr/src/linux
 endif
 
-IPSET_VERSION:=2.2.8
+IPSET_VERSION:=2.3.0
 
 PREFIX:=/usr/local
 LIBDIR:=$(PREFIX)/lib
@@ -21,9 +21,9 @@ IPSET_LIB_DIR:=$(LIBDIR)/ipset
 RELEASE_DIR:=/tmp
 
 COPT_FLAGS:=-O2
-CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -I$(KERNEL_DIR)/include -I. -g -DIPSET_DEBUG #-pg # -DIPTC_DEBUG
+CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -I$(KERNEL_DIR)/include -I. -g -DIPSET_DEBUG #-pg # -DIPTC_DEBUG
 SH_CFLAGS:=$(CFLAGS) -fPIC
-SETTYPES:=ipmap portmap macipmap iphash nethash iptree ipporthash
+SETTYPES:=ipmap portmap macipmap iphash nethash iptree iptreemap ipporthash
 
 PROGRAMS=ipset
 SHARED_LIBS=$(foreach T, $(SETTYPES),libipset_$(T).so)
diff --git a/ipset/Makefile.orig b/ipset/Makefile.orig
new file mode 100644 (file)
index 0000000..8679dc9
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/make
+
+######################################################################
+# YOU SHOULD NOT NEED TO TOUCH ANYTHING BELOW THIS LINE
+######################################################################
+
+ifndef KERNEL_DIR
+KERNEL_DIR=/usr/src/linux
+endif
+
+IPSET_VERSION:=2.2.9a
+
+PREFIX:=/usr/local
+LIBDIR:=$(PREFIX)/lib
+BINDIR:=$(PREFIX)/sbin
+MANDIR:=$(PREFIX)/man
+INCDIR:=$(PREFIX)/include
+IPSET_LIB_DIR:=$(LIBDIR)/ipset
+
+# directory for new iptables releases
+RELEASE_DIR:=/tmp
+
+COPT_FLAGS:=-O2
+CFLAGS:=$(COPT_FLAGS) -Wall -Wunused -I$(KERNEL_DIR)/include -I. -g -DIPSET_DEBUG #-pg # -DIPTC_DEBUG
+SH_CFLAGS:=$(CFLAGS) -fPIC
+SETTYPES:=ipmap portmap macipmap iphash nethash iptree ipporthash
+
+PROGRAMS=ipset
+SHARED_LIBS=$(foreach T, $(SETTYPES),libipset_$(T).so)
+INSTALL=$(DESTDIR)$(BINDIR)/ipset $(DESTDIR)$(MANDIR)/man8/ipset.8
+INSTALL+=$(foreach T, $(SETTYPES), $(DESTDIR)$(LIBDIR)/ipset/libipset_$(T).so)
+
+all: $(PROGRAMS) $(SHARED_LIBS)
+
+install: all $(INSTALL)
+
+clean: $(EXTRA_CLEANS)
+       rm -rf $(PROGRAMS) $(SHARED_LIBS) *.o *~
+
+#The ipset(8) self
+ipset.o: ipset.c
+       $(CC) $(CFLAGS) -DIPSET_VERSION=\"$(IPSET_VERSION)\" -DIPSET_LIB_DIR=\"$(IPSET_LIB_DIR)\" -c -o $@ $<
+
+ipset: ipset.o
+       $(CC) $(CFLAGS) -ldl -rdynamic -o $@ $^
+
+#Pooltypes
+ipset_%.o: ipset_%.c
+       $(CC) $(SH_CFLAGS) -o $@ -c $<
+
+libipset_%.so: ipset_%.o
+       $(LD) -shared -o $@ $<
+
+$(DESTDIR)$(LIBDIR)/ipset/libipset_%.so: libipset_%.so
+       @[ -d $(DESTDIR)$(LIBDIR)/ipset ] || mkdir -p $(DESTDIR)$(LIBDIR)/ipset
+       cp $< $@
+
+$(DESTDIR)$(BINDIR)/ipset: ipset
+       @[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
+       cp $< $@
+
+$(DESTDIR)$(MANDIR)/man8/ipset.8: ipset.8
+       @[ -d $(DESTDIR)$(MANDIR)/man8 ] || mkdir -p $(DESTDIR)$(MANDIR)/man8
+       cp $< $@
index 89a86ce..d2c8100 100644 (file)
@@ -231,10 +231,11 @@ The macipmap set type uses a memory range, where each 8 bytes
 represents one IP and a MAC addresses. A macipmap set type can store
 up to 65536 (B-class network) IP addresses with MAC.
 When adding an entry to a macipmap set, you must specify the entry as
-.I IP%MAC.
+.I IP:MAC.
 When deleting or testing macipmap entries, the
-.I %MAC
-part is not mandatory.
+.I :MAC
+part is not mandatory. (The old "%" separation token instead of ":", i.e
+IP%MAC is accepted as well.)
 .P
 Options to use when creating an macipmap set:
 .TP
@@ -307,6 +308,9 @@ When the optional
 parameter specified, network addresses will be 
 stored in the set instead of IP addresses.
 .P
+The iphash type of sets can store up to 65535 entries. If a set is full,
+no new entries can be added to it.
+.P
 Sets created by zero valued resize parameter won't be resized at all.
 The lookup time in an iphash type of set approximately linearly grows with
 the value of the 
@@ -342,6 +346,9 @@ by double-hashing (default 4).
 Increase the hash size by this many percent (default 50) when adding
 an IP to the hash could not be performed after
 .P
+The nethash type of sets can store up to 65535 entries. If a set is full,
+no new entries can be added to it.
+.P
 An IP address will be in a nethash type of set if it is in any of the
 netblocks added to the set and the matching always start from the smallest
 size of netblock (most specific netmask) to the biggest ones (least
@@ -367,7 +374,8 @@ store up to 65536 (B-class network) IP addresses with all possible port
 values. When adding, deleting and testing values in an ipporthash type of
 set, the entries must be specified as
 .B
-"IP%port".
+"IP:port".
+(Old "IP%port" format accepted as well.)
 .P
 The ipporthash types of sets evaluates two src/dst parameters of the 
 .I
@@ -416,7 +424,20 @@ If a set was created with a nonzero valued
 .B "--timeout"
 parameter then one may add IP addresses to the set with a specific 
 timeout value using the syntax 
-.I IP%timeout-value.
+.I IP:timeout-value.
+Similarly to the hash types, the iptree type of sets can store up to 65535
+entries.
+.SS iptreemap
+The iptreemap set type uses a tree to store IP addresses or networks, 
+where the last octet of an IP address are stored in a bitmap.
+As input entry, you can add IP addresses, CIDR blocks or network ranges
+to the set. Network ranges can be specified in the format
+.I IP1:IP2
+.P
+Options to use when creating an iptreemap set:
+.TP
+.BR "--gc " value
+How often the garbage collection should be called, in seconds (default 300)
 .SH GENERAL RESTRICTIONS
 Setnames starting with colon (:) cannot be defined. Zero valued set 
 entries cannot be used with hash type of sets.
@@ -439,6 +460,8 @@ OK, just kidding...
 .SH AUTHORS
 Jozsef Kadlecsik wrote ipset, which is based on ippool by
 Joakim Axelsson, Patrick Schaaf and Martin Josefsson.
+.P
+Sven Wegener wrote the iptreemap type.
 .\" .. and did I mention that we are incredibly cool people?
 .\" .. sexy, too ..
 .\" .. witty, charming, powerful ..
index adf37b1..9d7f78b 100644 (file)
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 #include <arpa/inet.h>
 #include <stdarg.h>
 #include <netdb.h>
 #include <dlfcn.h>
-#include <asm/bitops.h>
+#include <fcntl.h>
+/* #include <asm/bitops.h> */
 
 #include "ipset.h"
 
+#ifndef PROC_SYS_MODPROBE
+#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
+#endif
+
 char program_name[] = "ipset";
 char program_version[] = IPSET_VERSION;
 
@@ -42,7 +48,8 @@ static int option_quiet = 0;
 static int restore = 0;
 void *restore_data = NULL;
 struct ip_set_restore *restore_set = NULL;
-size_t restore_offset = 0, restore_size;
+size_t restore_offset = 0;
+socklen_t restore_size;
 unsigned line = 0;
 
 #define TEMPFILE_PATTERN       "/ipsetXXXXXX"
@@ -239,6 +246,73 @@ static char cmd2char(int option)
        return cmdflags[option];
 }
 
+/* From iptables.c ... */
+static char *get_modprobe(void)
+{
+       int procfile;
+       char *ret;
+
+#define PROCFILE_BUFSIZ        1024
+       procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
+       if (procfile < 0)
+               return NULL;
+
+       ret = (char *) malloc(PROCFILE_BUFSIZ);
+       if (ret) {
+               memset(ret, 0, PROCFILE_BUFSIZ);
+               switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
+               case -1: goto fail;
+               case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
+               }
+               if (ret[strlen(ret)-1]=='\n') 
+                       ret[strlen(ret)-1]=0;
+               close(procfile);
+               return ret;
+       }
+ fail:
+       free(ret);
+       close(procfile);
+       return NULL;
+}
+
+static int ipset_insmod(const char *modname, const char *modprobe)
+{
+       char *buf = NULL;
+       char *argv[3];
+       struct stat junk;
+       int status;
+       
+       if (!stat(modprobe, &junk)) {
+               /* Try to read out of the kernel */
+               buf = get_modprobe();
+               if (!buf)
+                       return -1;
+               modprobe = buf;
+       }
+       
+       switch (fork()) {
+       case 0:
+               argv[0] = (char *)modprobe;
+               argv[1] = (char *)modname;
+               argv[2] = NULL;
+               execv(argv[0], argv);
+               
+               /* Should not reach */
+               exit(1);
+       case -1:
+               return -1;
+       
+       default: /* parent */
+               wait(&status);
+       }
+       
+       free(buf);
+       
+       if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+               return 0;
+       return -1;
+}
+
 static int kernel_getsocket(void)
 {
        int sockfd = -1;
@@ -292,30 +366,50 @@ static void kernel_error(unsigned cmd, int err)
        exit_error(OTHER_PROBLEM, "Error from kernel: %s", strerror(err));
 }
 
-static void kernel_getfrom(unsigned cmd, void *data, size_t * size)
+static inline int wrapped_getsockopt(void *data, socklen_t *size)
 {
        int res;
        int sockfd = kernel_getsocket();
 
        /* Send! */
        res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
+       if (res != 0 
+           && errno == ENOPROTOOPT 
+           && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
+               res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
        DP("res=%d errno=%d", res, errno);
-
-       if (res != 0)
-               kernel_error(cmd, errno);
+       
+       return res;
 }
 
-static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
-                                    void *data, size_t size)
+static inline int wrapped_setsockopt(void *data, socklen_t size)
 {
        int res;
        int sockfd = kernel_getsocket();
 
        /* Send! */
        res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
+       if (res != 0 
+           && errno == ENOPROTOOPT 
+           && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
+               res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
        DP("res=%d errno=%d", res, errno);
+       
+       return res;
+}
+
+static void kernel_getfrom(unsigned cmd, void *data, socklen_t * size)
+{
+       int res = wrapped_getsockopt(data, size);
+
+       if (res != 0)
+               kernel_error(cmd, errno);
+}
+
+static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
+                                    void *data, socklen_t size)
+{
+       int res = wrapped_setsockopt(data, size);
 
        if (res != 0) {
                if (errno == EEXIST)
@@ -329,13 +423,7 @@ static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
 
 static void kernel_sendto(unsigned cmd, void *data, size_t size)
 {
-       int res;
-       int sockfd = kernel_getsocket();
-
-       /* Send! */
-       res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
-       DP("res=%d errno=%d", res, errno);
+       int res = wrapped_setsockopt(data, size);
 
        if (res != 0)
                kernel_error(cmd, errno);
@@ -343,13 +431,7 @@ static void kernel_sendto(unsigned cmd, void *data, size_t size)
 
 static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
 {
-       int res;
-       int sockfd = kernel_getsocket();
-
-       /* Send! */
-       res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
-
-       DP("res=%d errno=%d", res, errno);
+       int res = wrapped_getsockopt(data, size);
 
        if (res != 0) {
                if (errno == EAGAIN)
@@ -364,7 +446,7 @@ static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
 static void check_protocolversion(void)
 {
        struct ip_set_req_version req_version;
-       size_t size = sizeof(struct ip_set_req_version);
+       socklen_t size = sizeof(struct ip_set_req_version);
        int sockfd = kernel_getsocket();
        int res;
 
@@ -386,7 +468,7 @@ static void check_protocolversion(void)
                           req_version.version, IP_SET_PROTOCOL_VERSION);
 }
 
-static void set_command(int *cmd, const int newcmd)
+static void set_command(unsigned *cmd, const int newcmd)
 {
        if (*cmd != CMD_NONE)
                exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
@@ -958,7 +1040,7 @@ static size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
        struct ip_set_name_list *name_list;
        struct set *set;
        ip_set_id_t i;
-       size_t size, req_size;
+       socklen_t size, req_size;
        int repeated = 0, res = 0;
 
        DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
@@ -1069,13 +1151,17 @@ static size_t save_set(void *data, int *bindings,
        struct settype *settype;
        size_t used;
        
-       DP("offset %u, len %u", offset, len);
+       DP("offset %u (%u/%u/%u), len %u", offset,
+          sizeof(struct ip_set_save), 
+          set_save->header_size, set_save->members_size, 
+          len);
        if (offset + sizeof(struct ip_set_save) > len
            || offset + sizeof(struct ip_set_save)
               + set_save->header_size + set_save->members_size > len)
                exit_error(OTHER_PROBLEM,
                           "Save operation failed, try again later.");
 
+       DP("index: %u", set_save->index);
        if (set_save->index == IP_SET_INVALID_ID) {
                /* Marker */
                *bindings = 1;
@@ -1132,7 +1218,7 @@ static size_t save_default_bindings(void *data, int *bindings)
 static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
 {
        void *data = NULL;
-       size_t size, req_size = 0;
+       socklen_t size, req_size = 0;
        ip_set_id_t index;
        int res = 0, bindings = 0;
        time_t now = time(NULL);
@@ -1447,7 +1533,7 @@ static struct set *set_adt_get(const char *name)
 {
        struct ip_set_req_adt_get req_adt_get;
        struct set *set;
-       size_t size;
+       socklen_t size;
 
        DP("%s", name);
 
@@ -1456,7 +1542,7 @@ static struct set *set_adt_get(const char *name)
        strcpy(req_adt_get.set.name, name);
        size = sizeof(struct ip_set_req_adt_get);
 
-       kernel_getfrom(CMD_ADT_GET, &req_adt_get, &size);
+       kernel_getfrom(CMD_ADT_GET, (void *) &req_adt_get, &size);
 
        set = ipset_malloc(sizeof(struct set));
        strcpy(set->name, name);
@@ -1551,6 +1637,10 @@ static int set_bind(struct set *set, const char *adt,
        /* set may be null: '-U :all: :all:|:default:' */
        DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding);
 
+       /* Ugly */
+       if (strcmp(set->settype->typename, "iptreemap") == 0)
+               exit_error(PARAMETER_PROBLEM,
+                       "iptreemap type of sets cannot be used at binding operations\n");
        /* Alloc memory for the data to send */
        size = sizeof(struct ip_set_req_bind);
        if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
@@ -1705,7 +1795,7 @@ static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
 {
        void *data = NULL;
        ip_set_id_t index;
-       size_t size, req_size;
+       socklen_t size, req_size;
        int res = 0;
 
        DP("%s", name);
@@ -2043,6 +2133,7 @@ int parse_commandline(int argc, char *argv[])
                                                   "Unknown arg `%s'",
                                                   argv[optind - 1]);
 
+                               res = 0;
                                break;
                        }
 
@@ -2099,7 +2190,8 @@ int parse_commandline(int argc, char *argv[])
                                        exit_error(PARAMETER_PROBLEM,
                                                   "Unknown arg `%s'",
                                                   argv[optind - 1]);
-
+                               
+                               res = 0;
                        }
 
                        DP("next arg");
index 50a3476..4ac2da9 100644 (file)
@@ -184,4 +184,9 @@ extern void *ipset_malloc(size_t size);
 extern char *ipset_strdup(const char *);
 extern void ipset_free(void **data);
 
+#define BITSPERBYTE    (8*sizeof(char))
+#define ID2BYTE(id)    ((id)/BITSPERBYTE)
+#define ID2MASK(id)    (1 << ((id)%BITSPERBYTE))
+#define test_bit(id, heap)     ((((char *)(heap))[ID2BYTE(id)] & ID2MASK(id)) != 0)
+
 #endif /* __IPSET_H */
index 3272e6e..114cfad 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_iphash.h>
index 2d1c81c..df8efbf 100644 (file)
@@ -22,7 +22,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
+/* #include <asm/bitops.h> */
 
 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
 #include "ipset.h"
@@ -191,7 +191,7 @@ void create_final(void *data, unsigned int flags)
        }
        if (range > MAX_RANGE)
                exit_error(PARAMETER_PROBLEM,
-                          "Range to large. Max is %d IPs in range\n",
+                          "Range too large. Max is %d IPs in range\n",
                           MAX_RANGE+1);
 }
 
index 1ebbc50..ef527fa 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_ipporthash.h>
@@ -182,7 +181,7 @@ void create_final(void *data, unsigned int flags)
 
        if (mydata->to - mydata->from > MAX_RANGE)
                exit_error(PARAMETER_PROBLEM,
-                          "Range to large. Max is %d IPs in range\n",
+                          "Range too large. Max is %d IPs in range\n",
                           MAX_RANGE+1);
 }
 
@@ -207,7 +206,7 @@ ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
 
        DP("ipporthash: %p %p", optarg, data);
 
-       ptr = strsep(&tmp, "%");
+       ptr = strsep(&tmp, ":%");
        parse_ip(ptr, &mydata->ip);
 
        if (tmp)
@@ -263,7 +262,7 @@ void printips(struct set *set, void *data, size_t len, unsigned options)
                if (*ipptr) {
                        ip = (*ipptr>>16) + mysetdata->first_ip;
                        port = (uint16_t) *ipptr;
-                       printf("%s%%%s\n", 
+                       printf("%s:%s\n", 
                               ip_tostring(ip, options),
                               port_tostring(port, options));
                }
@@ -299,7 +298,7 @@ void saveips(struct set *set, void *data, size_t len, unsigned options)
                if (*ipptr) {
                        ip = (*ipptr>>16) + mysetdata->first_ip;
                        port = (uint16_t) *ipptr;
-                       printf("-A %s %s%%%s\n", set->name, 
+                       printf("-A %s %s:%s\n", set->name, 
                               ip_tostring(ip, options),
                               port_tostring(port, options));
                }
@@ -317,7 +316,7 @@ static char * unpack_ipport_tostring(struct set *set, ip_set_ip_t bip, unsigned
        
        ip = (bip>>16) + mysetdata->first_ip;
        port = (uint16_t) bip;
-       sprintf(buffer, "%s%%%s", 
+       sprintf(buffer, "%s:%s", 
                ip_tostring(ip, options), port_tostring(port, options));
                
        return buffer;
@@ -330,9 +329,9 @@ void usage(void)
             "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
             "-N set ipporthash --network IP/mask\n"
             "   [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
-            "-A set IP%%port\n"
-            "-D set IP%%port\n"
-            "-T set IP%%port\n");
+            "-A set IP:port\n"
+            "-D set IP:port\n"
+            "-T set IP:port\n");
 }
 
 static struct settype settype_ipporthash = {
index cce9884..c3678df 100644 (file)
@@ -84,7 +84,7 @@ ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
 
        DP("iptree: %p %p", optarg, data);
 
-       ptr = strsep(&tmp, "%");
+       ptr = strsep(&tmp, ":%");
        parse_ip(ptr, &mydata->ip);
 
        if (tmp)
@@ -130,8 +130,8 @@ void printips_sorted(struct set *set, void *data, size_t len, unsigned options)
        while (len >= offset + sizeof(struct ip_set_req_iptree)) {
                req = (struct ip_set_req_iptree *)(data + offset);
                if (mysetdata->timeout)
-                       printf("%s%%%u\n", ip_tostring(req->ip, options),
-                                          req->timeout);
+                       printf("%s:%u\n", ip_tostring(req->ip, options),
+                                         req->timeout);
                else
                        printf("%s\n", ip_tostring(req->ip, options));
                offset += sizeof(struct ip_set_req_iptree);
@@ -164,7 +164,7 @@ void saveips(struct set *set, void *data, size_t len, unsigned options)
        while (len >= offset + sizeof(struct ip_set_req_iptree)) {
                req = (struct ip_set_req_iptree *)(data + offset);
                if (mysetdata->timeout)
-                       printf("-A %s %s%%%u\n",
+                       printf("-A %s %s:%u\n",
                                set->name, 
                                ip_tostring(req->ip, options),
                                req->timeout);
@@ -180,7 +180,7 @@ void usage(void)
 {
        printf
            ("-N set iptree [--timeout value]\n"
-            "-A set IP[%%timeout]\n"
+            "-A set IP[:timeout]\n"
             "-D set IP\n"
             "-T set IP\n");
 }
diff --git a/ipset/ipset_iptreemap.c b/ipset/ipset_iptreemap.c
new file mode 100644 (file)
index 0000000..ccc5ec3
--- /dev/null
@@ -0,0 +1,206 @@
+/* Copyright 2007 Sven Wegener <sven.wegener@stealer.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/netfilter_ipv4/ip_set_iptreemap.h>
+
+#include "ipset.h"
+
+#define OPT_CREATE_GC 0x1
+
+void
+create_init(void *data)
+{
+       struct ip_set_req_iptreemap_create *mydata = (struct ip_set_req_iptreemap_create *) data;
+
+       mydata->gc_interval = 0;
+}
+
+int
+create_parse(int c, char *argv[], void *data, unsigned int *flags)
+{
+       struct ip_set_req_iptreemap_create *mydata = (struct ip_set_req_iptreemap_create *) data;
+
+       switch (c) {
+               case 'g':
+                       string_to_number(optarg, 0, UINT_MAX, &mydata->gc_interval);
+
+                       *flags |= OPT_CREATE_GC;
+               break;
+               default:
+                       return 0;
+               break;
+       }
+
+       return 1;
+}
+
+void
+create_final(void *data, unsigned int flags)
+{
+}
+
+static struct option create_opts[] = {
+       {"gc", 1, 0, 'g'},
+       {0}
+};
+
+ip_set_ip_t
+adt_parser(unsigned int cmd, const char *optarg, void *data)
+{
+       struct ip_set_req_iptreemap *mydata = (struct ip_set_req_iptreemap *) data;
+       ip_set_ip_t mask;
+
+       char *saved = ipset_strdup(optarg);
+       char *ptr, *tmp = saved;
+
+       if (strchr(tmp, '/')) {
+               parse_ipandmask(tmp, &mydata->start, &mask);
+               mydata->end = mydata->start | ~mask;
+       } else {
+               ptr = strsep(&tmp, ":");
+               parse_ip(ptr, &mydata->start);
+
+               if (tmp) {
+                       parse_ip(tmp, &mydata->end);
+               } else {
+                       mydata->end = mydata->start;
+               }
+       }
+
+       return 1;
+}
+
+void
+initheader(struct set *set, const void *data)
+{
+       struct ip_set_req_iptreemap_create *header = (struct ip_set_req_iptreemap_create *) data;
+       struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->settype->header;
+
+       map->gc_interval = header->gc_interval;
+}
+
+void
+printheader(struct set *set, unsigned int options)
+{
+       struct ip_set_iptreemap *mysetdata = (struct ip_set_iptreemap *) set->settype->header;
+
+       if (mysetdata->gc_interval)
+               printf(" gc: %u", mysetdata->gc_interval);
+
+       printf("\n");
+}
+
+void
+printips_sorted(struct set *set, void *data, size_t len, unsigned int options)
+{
+       struct ip_set_req_iptreemap *req;
+       size_t offset = 0;
+
+       while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
+               req = (struct ip_set_req_iptreemap *) (data + offset);
+
+               printf("%s", ip_tostring(req->start, options));
+               if (req->start != req->end)
+                       printf(":%s", ip_tostring(req->end, options));
+               printf("\n");
+
+               offset += sizeof(struct ip_set_req_iptreemap);
+       }
+}
+
+void
+saveheader(struct set *set, unsigned int options)
+{
+       struct ip_set_iptreemap *mysetdata = (struct ip_set_iptreemap *) set->settype->header;
+
+       printf("-N %s %s", set->name, set->settype->typename);
+
+       if (mysetdata->gc_interval)
+               printf(" --gc %u", mysetdata->gc_interval);
+
+       printf("\n");
+}
+
+void
+saveips(struct set *set, void *data, size_t len, unsigned int options)
+{
+       struct ip_set_req_iptreemap *req;
+       size_t offset = 0;
+
+       while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
+               req = (struct ip_set_req_iptreemap *) (data + offset);
+
+               printf("-A %s %s", set->name, ip_tostring(req->start, options));
+
+               if (req->start != req->end)
+                       printf(":%s", ip_tostring(req->end, options));
+
+               printf("\n");
+
+               offset += sizeof(struct ip_set_req_iptreemap);
+       }
+}
+
+void
+usage(void)
+{
+       printf(
+               "-N set iptreemap --gc interval\n"
+               "-A set IP\n"
+               "-D set IP\n"
+               "-T set IP\n"
+       );
+}
+
+static struct settype settype_iptreemap = {
+       .typename = SETTYPE_NAME,
+       .protocol_version = IP_SET_PROTOCOL_VERSION,
+
+       .create_size = sizeof(struct ip_set_req_iptreemap_create),
+       .create_init = &create_init,
+       .create_parse = &create_parse,
+       .create_final = &create_final,
+       .create_opts = create_opts,
+
+       .adt_size = sizeof(struct ip_set_req_iptreemap),
+       .adt_parser = &adt_parser,
+
+       .header_size = sizeof(struct ip_set_iptreemap),
+       .initheader = &initheader,
+       .printheader = &printheader,
+       .printips = &printips_sorted,
+       .printips_sorted = &printips_sorted,
+       .saveheader = &saveheader,
+       .saveips = &saveips,
+
+       .bindip_tostring = &binding_ip_tostring,
+       .bindip_parse = &parse_ip,
+
+       .usage = &usage,
+};
+
+void
+_init(void)
+{
+       settype_register(&settype_iptreemap);
+}
index 3ef8fb1..3385f19 100644 (file)
@@ -24,7 +24,6 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <linux/if_ether.h>
 
 #include <linux/netfilter_ipv4/ip_set_macipmap.h>
@@ -185,7 +184,7 @@ ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
 
        DP("macipmap: %p %p", optarg, data);
 
-       ptr = strsep(&tmp, "%");
+       ptr = strsep(&tmp, ":%");
        parse_ip(ptr, &mydata->ip);
 
        if (tmp)
@@ -247,7 +246,7 @@ void printips_sorted(struct set *set, void *data, size_t len, unsigned options)
        while (addr <= mysetdata->last_ip) {
                if (test_bit(IPSET_MACIP_ISSET,
                             (void *)&table[addr - mysetdata->first_ip].flags)) {
-                       printf("%s%%", ip_tostring(addr, options));
+                       printf("%s:", ip_tostring(addr, options));
                        print_mac(table[addr - mysetdata->first_ip].
                                  ethernet);
                        printf("\n");
@@ -282,7 +281,7 @@ void saveips(struct set *set, void *data, size_t len, unsigned options)
        while (addr <= mysetdata->last_ip) {
                if (test_bit(IPSET_MACIP_ISSET,
                             (void *)&table[addr - mysetdata->first_ip].flags)) {
-                       printf("-A %s %s%%",
+                       printf("-A %s %s:",
                               set->name, ip_tostring(addr, options));
                        print_mac(table[addr - mysetdata->first_ip].
                                  ethernet);
@@ -297,9 +296,9 @@ void usage(void)
        printf
            ("-N set macipmap --from IP --to IP [--matchunset]\n"
             "-N set macipmap --network IP/mask [--matchunset]\n"
-            "-A set IP%%MAC\n"
-            "-D set IP[%%MAC]\n"
-            "-T set IP[%%MAC]\n");
+            "-A set IP:MAC\n"
+            "-D set IP[:MAC]\n"
+            "-T set IP[:MAC]\n");
 }
 
 static struct settype settype_macipmap = {
index 758c4c1..fed4a02 100644 (file)
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 #include <asm/types.h>
 
 #include <linux/netfilter_ipv4/ip_set_nethash.h>
index 1c3965b..1d4f807 100644 (file)
@@ -21,7 +21,6 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <asm/bitops.h>
 
 #include <linux/netfilter_ipv4/ip_set_portmap.h>
 #include "ipset.h"
index 0563099..7ade333 100644 (file)
@@ -6,6 +6,7 @@
 int iptables_main(int argc, char **argv);
 int iptables_save_main(int argc, char **argv);
 int iptables_restore_main(int argc, char **argv);
+int iptables_xml_main(int argc, char **argv);
 
 int main(int argc, char **argv) {
   char *progname;
@@ -25,6 +26,9 @@ int main(int argc, char **argv) {
     if (!strcmp(progname, "iptables-restore"))
       return iptables_restore_main(argc, argv);
     
+    if (!strcmp(progname, "iptables-xml"))
+      return iptables_xml_main(argc, argv);
+    
     fprintf(stderr, "iptables multi-purpose version: unknown applet name %s\n", progname);
     exit(1);
   }
index 95e2cbe..1cbade7 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This code is distributed under the terms of GNU GPL v2
  *
- * $Id: iptables-restore.c 3980 2005-06-12 15:54:15Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org $
+ * $Id: iptables-restore.c 6828 2007-05-10 15:00:39Z /C=EU/ST=EU/CN=Patrick McHardy/emailAddress=kaber@trash.net $
  */
 
 #include <getopt.h>
@@ -59,19 +59,19 @@ iptc_handle_t create_handle(const char *tablename, const char* modprobe )
 
        if (!handle) {
                /* try to insmod the module if iptc_init failed */
-               iptables_insmod("ip_tables", modprobe);
+               iptables_insmod("ip_tables", modprobe, 0);
                handle = iptc_init(tablename);
        }
 
        if (!handle) {
-               exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
+               exit_error(PARAMETER_PROBLEM, "%s: unable to initialize "
                        "table '%s'\n", program_name, tablename);
                exit(1);
        }
        return handle;
 }
 
-int parse_counters(char *string, struct ipt_counters *ctr)
+static int parse_counters(char *string, struct ipt_counters *ctr)
 {
        return (sscanf(string, "[%llu:%llu]", (unsigned long long *)&ctr->pcnt, (unsigned long long *)&ctr->bcnt) == 2);
 }
@@ -157,13 +157,13 @@ main(int argc, char *argv[])
        if (optind == argc - 1) {
                in = fopen(argv[optind], "r");
                if (!in) {
-                       fprintf(stderr, "Can't open %s: %s", argv[optind],
+                       fprintf(stderr, "Can't open %s: %s\n", argv[optind],
                                strerror(errno));
                        exit(1);
                }
        }
        else if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline");
+               fprintf(stderr, "Unknown arguments found on commandline\n");
                exit(1);
        }
        else in = stdin;
@@ -269,7 +269,10 @@ main(int argc, char *argv[])
                                        char *ctrs;
                                        ctrs = strtok(NULL, " \t\n");
 
-                                       parse_counters(ctrs, &count);
+                                       if (!ctrs || !parse_counters(ctrs, &count))
+                                               exit_error(PARAMETER_PROBLEM,
+                                                          "invalid policy counters "
+                                                          "for chain '%s'\n", chain);
 
                                } else {
                                        memset(&count, 0, 
@@ -298,8 +301,9 @@ main(int argc, char *argv[])
                        char *parsestart;
 
                        /* the parser */
-                       char *param_start, *curchar;
+                       char *curchar;
                        int quote_open;
+                       int param_len;
 
                        /* reset the newargv */
                        newargc = 0;
@@ -346,9 +350,11 @@ main(int argc, char *argv[])
                         * longer a real hacker, but I can live with that */
 
                        quote_open = 0;
-                       param_start = parsestart;
+                       param_len = 0;
                        
                        for (curchar = parsestart; *curchar; curchar++) {
+                               char param_buffer[1024];
+
                                if (*curchar == '"') {
                                        /* quote_open cannot be true if there
                                         * was no previous character.  Thus, 
@@ -357,30 +363,27 @@ main(int argc, char *argv[])
                                            *(curchar-1) != '\\') {
                                                quote_open = 0;
                                                *curchar = ' ';
-                                       } else {
+                                       } else if (!quote_open) {
                                                quote_open = 1;
-                                               param_start++;
+                                               continue;
                                        }
                                } 
                                if (*curchar == ' '
                                    || *curchar == '\t'
                                    || * curchar == '\n') {
-                                       char param_buffer[1024];
-                                       int param_len = curchar-param_start;
 
-                                       if (quote_open)
+                                       if (quote_open) {
+                                               param_buffer[param_len++] = 
+                                                               *curchar;
                                                continue;
+                                       }
 
                                        if (!param_len) {
                                                /* two spaces? */
-                                               param_start++;
                                                continue;
                                        }
-                                       
-                                       /* end of one parameter */
-                                       strncpy(param_buffer, param_start,
-                                               param_len);
-                                       *(param_buffer+param_len) = '\0';
+
+                                       param_buffer[param_len] = '\0';
 
                                        /* check if table name specified */
                                        if (!strncmp(param_buffer, "-t", 3)
@@ -392,9 +395,26 @@ main(int argc, char *argv[])
                                        }
 
                                        add_argv(param_buffer);
-                                       param_start += param_len + 1;
+                                       param_len = 0;
                                } else {
-                                       /* regular character, skip */
+                                       /* Skip backslash that escapes quote: 
+                                        * the standard input does not require
+                                        * escaping. However, the output
+                                        * generated by iptables-save
+                                        * introduces bashlash to keep
+                                        * consistent with iptables
+                                        */
+                                       if (quote_open &&
+                                           *curchar == '\\' &&
+                                           *(curchar+1) == '"')
+                                               continue;
+
+                                       /* regular character, copy to buffer */
+                                       param_buffer[param_len++] = *curchar;
+
+                                       if (param_len >= sizeof(param_buffer))
+                                               exit_error(PARAMETER_PROBLEM, 
+                                                  "Parameter too long!");
                                }
                        }
 
diff --git a/iptables-restore.c.orig b/iptables-restore.c.orig
new file mode 100644 (file)
index 0000000..7cde347
--- /dev/null
@@ -0,0 +1,428 @@
+/* Code to restore the iptables state, from file by iptables-save. 
+ * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * based on previous code from Rusty Russell <rusty@linuxcare.com.au>
+ *
+ * This code is distributed under the terms of GNU GPL v2
+ *
+ * $Id: iptables-restore.c 6706 2006-12-09 13:06:04Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=yasuyuki/emailAddress=yasuyuki@netfilter.org $
+ */
+
+#include <getopt.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "iptables.h"
+#include "libiptc/libiptc.h"
+
+#ifdef DEBUG
+#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
+#else
+#define DEBUGP(x, args...) 
+#endif
+
+static int binary = 0, counters = 0, verbose = 0, noflush = 0;
+
+/* Keeping track of external matches and targets.  */
+static struct option options[] = {
+       { "binary", 0, 0, 'b' },
+       { "counters", 0, 0, 'c' },
+       { "verbose", 0, 0, 'v' },
+       { "test", 0, 0, 't' },
+       { "help", 0, 0, 'h' },
+       { "noflush", 0, 0, 'n'},
+       { "modprobe", 1, 0, 'M'},
+       { 0 }
+};
+
+static void print_usage(const char *name, const char *version) __attribute__((noreturn));
+
+static void print_usage(const char *name, const char *version)
+{
+       fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h]\n"
+                       "          [ --binary ]\n"
+                       "          [ --counters ]\n"
+                       "          [ --verbose ]\n"
+                       "          [ --test ]\n"
+                       "          [ --help ]\n"
+                       "          [ --noflush ]\n"
+                       "          [ --modprobe=<command>]\n", name);
+               
+       exit(1);
+}
+
+iptc_handle_t create_handle(const char *tablename, const char* modprobe )
+{
+       iptc_handle_t handle;
+
+       handle = iptc_init(tablename);
+
+       if (!handle) {
+               /* try to insmod the module if iptc_init failed */
+               iptables_insmod("ip_tables", modprobe);
+               handle = iptc_init(tablename);
+       }
+
+       if (!handle) {
+               exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
+                       "table '%s'\n", program_name, tablename);
+               exit(1);
+       }
+       return handle;
+}
+
+static int parse_counters(char *string, struct ipt_counters *ctr)
+{
+       return (sscanf(string, "[%llu:%llu]", (unsigned long long *)&ctr->pcnt, (unsigned long long *)&ctr->bcnt) == 2);
+}
+
+/* global new argv and argc */
+static char *newargv[255];
+static int newargc;
+
+/* function adding one argument to newargv, updating newargc 
+ * returns true if argument added, false otherwise */
+static int add_argv(char *what) {
+       DEBUGP("add_argv: %s\n", what);
+       if (what && ((newargc + 1) < sizeof(newargv)/sizeof(char *))) {
+               newargv[newargc] = strdup(what);
+               newargc++;
+               return 1;
+       } else 
+               return 0;
+}
+
+static void free_argv(void) {
+       int i;
+
+       for (i = 0; i < newargc; i++)
+               free(newargv[i]);
+}
+
+#ifdef IPTABLES_MULTI
+int
+iptables_restore_main(int argc, char *argv[])
+#else
+int
+main(int argc, char *argv[])
+#endif
+{
+       iptc_handle_t handle = NULL;
+       char buffer[10240];
+       int c;
+       char curtable[IPT_TABLE_MAXNAMELEN + 1];
+       FILE *in;
+       const char *modprobe = 0;
+       int in_table = 0, testing = 0;
+
+       program_name = "iptables-restore";
+       program_version = IPTABLES_VERSION;
+       line = 0;
+
+       lib_dir = getenv("IPTABLES_LIB_DIR");
+       if (!lib_dir)
+               lib_dir = IPT_LIB_DIR;
+
+#ifdef NO_SHARED_LIBS
+       init_extensions();
+#endif
+
+       while ((c = getopt_long(argc, argv, "bcvthnM:", options, NULL)) != -1) {
+               switch (c) {
+                       case 'b':
+                               binary = 1;
+                               break;
+                       case 'c':
+                               counters = 1;
+                               break;
+                       case 'v':
+                               verbose = 1;
+                               break;
+                       case 't':
+                               testing = 1;
+                               break;
+                       case 'h':
+                               print_usage("iptables-restore",
+                                           IPTABLES_VERSION);
+                               break;
+                       case 'n':
+                               noflush = 1;
+                               break;
+                       case 'M':
+                               modprobe = optarg;
+                               break;
+               }
+       }
+       
+       if (optind == argc - 1) {
+               in = fopen(argv[optind], "r");
+               if (!in) {
+                       fprintf(stderr, "Can't open %s: %s", argv[optind],
+                               strerror(errno));
+                       exit(1);
+               }
+       }
+       else if (optind < argc) {
+               fprintf(stderr, "Unknown arguments found on commandline");
+               exit(1);
+       }
+       else in = stdin;
+       
+       /* Grab standard input. */
+       while (fgets(buffer, sizeof(buffer), in)) {
+               int ret = 0;
+
+               line++;
+               if (buffer[0] == '\n')
+                       continue;
+               else if (buffer[0] == '#') {
+                       if (verbose)
+                               fputs(buffer, stdout);
+                       continue;
+               } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
+                       if (!testing) {
+                               DEBUGP("Calling commit\n");
+                               ret = iptc_commit(&handle);
+                       } else {
+                               DEBUGP("Not calling commit, testing\n");
+                               ret = 1;
+                       }
+                       in_table = 0;
+               } else if ((buffer[0] == '*') && (!in_table)) {
+                       /* New table */
+                       char *table;
+
+                       table = strtok(buffer+1, " \t\n");
+                       DEBUGP("line %u, table '%s'\n", line, table);
+                       if (!table) {
+                               exit_error(PARAMETER_PROBLEM, 
+                                       "%s: line %u table name invalid\n",
+                                       program_name, line);
+                               exit(1);
+                       }
+                       strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
+                       curtable[IPT_TABLE_MAXNAMELEN] = '\0';
+
+                       if (handle)
+                               iptc_free(&handle);
+
+                       handle = create_handle(table, modprobe);
+                       if (noflush == 0) {
+                               DEBUGP("Cleaning all chains of table '%s'\n",
+                                       table);
+                               for_each_chain(flush_entries, verbose, 1, 
+                                               &handle);
+       
+                               DEBUGP("Deleting all user-defined chains "
+                                      "of table '%s'\n", table);
+                               for_each_chain(delete_chain, verbose, 0, 
+                                               &handle) ;
+                       }
+
+                       ret = 1;
+                       in_table = 1;
+
+               } else if ((buffer[0] == ':') && (in_table)) {
+                       /* New chain. */
+                       char *policy, *chain;
+
+                       chain = strtok(buffer+1, " \t\n");
+                       DEBUGP("line %u, chain '%s'\n", line, chain);
+                       if (!chain) {
+                               exit_error(PARAMETER_PROBLEM,
+                                          "%s: line %u chain name invalid\n",
+                                          program_name, line);
+                               exit(1);
+                       }
+
+                       if (iptc_builtin(chain, handle) <= 0) {
+                               if (noflush && iptc_is_chain(chain, handle)) {
+                                       DEBUGP("Flushing existing user defined chain '%s'\n", chain);
+                                       if (!iptc_flush_entries(chain, &handle))
+                                               exit_error(PARAMETER_PROBLEM,
+                                                          "error flushing chain "
+                                                          "'%s':%s\n", chain,
+                                                          strerror(errno));
+                               } else {
+                                       DEBUGP("Creating new chain '%s'\n", chain);
+                                       if (!iptc_create_chain(chain, &handle))
+                                               exit_error(PARAMETER_PROBLEM,
+                                                          "error creating chain "
+                                                          "'%s':%s\n", chain,
+                                                          strerror(errno));
+                               }
+                       }
+
+                       policy = strtok(NULL, " \t\n");
+                       DEBUGP("line %u, policy '%s'\n", line, policy);
+                       if (!policy) {
+                               exit_error(PARAMETER_PROBLEM,
+                                          "%s: line %u policy invalid\n",
+                                          program_name, line);
+                               exit(1);
+                       }
+
+                       if (strcmp(policy, "-") != 0) {
+                               struct ipt_counters count;
+
+                               if (counters) {
+                                       char *ctrs;
+                                       ctrs = strtok(NULL, " \t\n");
+
+                                       if (!ctrs || !parse_counters(ctrs, &count))
+                                               exit_error(PARAMETER_PROBLEM,
+                                                          "invalid policy counters "
+                                                          "for chain '%s'\n", chain);
+
+                               } else {
+                                       memset(&count, 0, 
+                                              sizeof(struct ipt_counters));
+                               }
+
+                               DEBUGP("Setting policy of chain %s to %s\n",
+                                       chain, policy);
+
+                               if (!iptc_set_policy(chain, policy, &count,
+                                                    &handle))
+                                       exit_error(OTHER_PROBLEM,
+                                               "Can't set policy `%s'"
+                                               " on `%s' line %u: %s\n",
+                                               chain, policy, line,
+                                               iptc_strerror(errno));
+                       }
+
+                       ret = 1;
+
+               } else if (in_table) {
+                       int a;
+                       char *ptr = buffer;
+                       char *pcnt = NULL;
+                       char *bcnt = NULL;
+                       char *parsestart;
+
+                       /* the parser */
+                       char *param_start, *curchar;
+                       int quote_open;
+
+                       /* reset the newargv */
+                       newargc = 0;
+
+                       if (buffer[0] == '[') {
+                               /* we have counters in our input */
+                               ptr = strchr(buffer, ']');
+                               if (!ptr)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need ]\n",
+                                                  line);
+
+                               pcnt = strtok(buffer+1, ":");
+                               if (!pcnt)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need :\n",
+                                                  line);
+
+                               bcnt = strtok(NULL, "]");
+                               if (!bcnt)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need ]\n",
+                                                  line);
+
+                               /* start command parsing after counter */
+                               parsestart = ptr + 1;
+                       } else {
+                               /* start command parsing at start of line */
+                               parsestart = buffer;
+                       }
+
+                       add_argv(argv[0]);
+                       add_argv("-t");
+                       add_argv((char *) &curtable);
+                       
+                       if (counters && pcnt && bcnt) {
+                               add_argv("--set-counters");
+                               add_argv((char *) pcnt);
+                               add_argv((char *) bcnt);
+                       }
+
+                       /* After fighting with strtok enough, here's now
+                        * a 'real' parser. According to Rusty I'm now no
+                        * longer a real hacker, but I can live with that */
+
+                       quote_open = 0;
+                       param_start = parsestart;
+                       
+                       for (curchar = parsestart; *curchar; curchar++) {
+                               if (*curchar == '"') {
+                                       /* quote_open cannot be true if there
+                                        * was no previous character.  Thus, 
+                                        * curchar-1 has to be within bounds */
+                                       if (quote_open && 
+                                           *(curchar-1) != '\\') {
+                                               quote_open = 0;
+                                               *curchar = ' ';
+                                       } else {
+                                               quote_open = 1;
+                                               param_start++;
+                                       }
+                               } 
+                               if (*curchar == ' '
+                                   || *curchar == '\t'
+                                   || * curchar == '\n') {
+                                       char param_buffer[1024];
+                                       int param_len = curchar-param_start;
+
+                                       if (quote_open)
+                                               continue;
+
+                                       if (!param_len) {
+                                               /* two spaces? */
+                                               param_start++;
+                                               continue;
+                                       }
+                                       
+                                       /* end of one parameter */
+                                       strncpy(param_buffer, param_start,
+                                               param_len);
+                                       *(param_buffer+param_len) = '\0';
+
+                                       /* check if table name specified */
+                                       if (!strncmp(param_buffer, "-t", 3)
+                                            || !strncmp(param_buffer, "--table", 8)) {
+                                               exit_error(PARAMETER_PROBLEM, 
+                                                  "Line %u seems to have a "
+                                                  "-t table option.\n", line);
+                                               exit(1);
+                                       }
+
+                                       add_argv(param_buffer);
+                                       param_start += param_len + 1;
+                               } else {
+                                       /* regular character, skip */
+                               }
+                       }
+
+                       DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
+                               newargc, curtable);
+
+                       for (a = 0; a < newargc; a++)
+                               DEBUGP("argv[%u]: %s\n", a, newargv[a]);
+
+                       ret = do_command(newargc, newargv, 
+                                        &newargv[2], &handle);
+
+                       free_argv();
+               }
+               if (!ret) {
+                       fprintf(stderr, "%s: line %u failed\n",
+                                       program_name, line);
+                       exit(1);
+               }
+       }
+       if (in_table) {
+               fprintf(stderr, "%s: COMMIT expected at line %u\n",
+                               program_name, line + 1);
+               exit(1);
+       }
+
+       return 0;
+}
index 79b5dc7..a8a17aa 100644 (file)
@@ -141,7 +141,7 @@ static int print_match(const struct ipt_entry_match *e,
 /* print a given ip including mask if neccessary */
 static void print_ip(char *prefix, u_int32_t ip, u_int32_t mask, int invert)
 {
-       if (!mask && !ip)
+       if (!mask && !ip && !invert)
                return;
 
        printf("%s %s%u.%u.%u.%u",
@@ -368,7 +368,7 @@ main(int argc, char *argv[])
        }
 
        if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline");
+               fprintf(stderr, "Unknown arguments found on commandline\n");
                exit(1);
        }
 
index 257b677..e5c7841 100644 (file)
@@ -64,9 +64,13 @@ main(int argc, char *argv[])
        if (ret)
                ret = iptc_commit(&handle);
 
-       if (!ret)
+       if (!ret) {
                fprintf(stderr, "iptables: %s\n",
                        iptc_strerror(errno));
+               if (errno == EAGAIN) {
+                       exit(RESOURCE_PROBLEM);
+               }
+       }
 
        exit(!ret);
 }
diff --git a/iptables-xml.c b/iptables-xml.c
new file mode 100644 (file)
index 0000000..ce3049c
--- /dev/null
@@ -0,0 +1,860 @@
+/* Code to convert iptables-save format to xml format,
+ * (C) 2006 Ufo Mechanic <azez@ufomechanic.net>
+ * based on iptables-restor (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * based on previous code from Rusty Russell <rusty@linuxcare.com.au>
+ *
+ * This code is distributed under the terms of GNU GPL v2
+ *
+ * $Id: iptables-xml.c,v 1.4 2006/11/09 12:02:17 azez Exp $
+ */
+
+#include <getopt.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "iptables.h"
+#include "libiptc/libiptc.h"
+
+#ifdef DEBUG
+#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
+#else
+#define DEBUGP(x, args...)
+#endif
+
+/* no need to link with iptables.o */
+const char *program_name;
+const char *program_version;
+
+#ifndef IPTABLES_MULTI
+int line = 0;
+void exit_error(enum exittype status, char *msg, ...)
+{
+       va_list args;
+
+       va_start(args, msg);
+       fprintf(stderr, "%s v%s: ", program_name, program_version);
+       vfprintf(stderr, msg, args);
+       va_end(args);
+       fprintf(stderr, "\n");
+       /* On error paths, make sure that we don't leak memory */
+       exit(status);
+}
+#endif
+
+static void print_usage(const char *name, const char *version)
+           __attribute__ ((noreturn));
+
+static int verbose = 0;
+/* Whether to combine actions of sequential rules with identical conditions */
+static int combine = 0;
+/* Keeping track of external matches and targets.  */
+static struct option options[] = {
+       {"verbose", 0, 0, 'v'},
+       {"combine", 0, 0, 'c'},
+       {"help", 0, 0, 'h'},
+       {0}
+};
+
+static void
+print_usage(const char *name, const char *version)
+{
+       fprintf(stderr, "Usage: %s [-c] [-v] [-h]\n"
+               "          [--combine ]\n"
+               "          [ --verbose ]\n" "      [ --help ]\n", name);
+
+       exit(1);
+}
+
+static int
+parse_counters(char *string, struct ipt_counters *ctr)
+{
+       if (string != NULL)
+               return (sscanf
+                       (string, "[%llu:%llu]",
+                        (unsigned long long *) &ctr->pcnt,
+                        (unsigned long long *) &ctr->bcnt) == 2);
+       else
+               return (0 == 2);
+}
+
+/* global new argv and argc */
+static char *newargv[255];
+static int newargc = 0;
+
+static char *oldargv[255];
+static int oldargc = 0;
+
+/* arg meta data, were they quoted, frinstance */
+static int newargvattr[255];
+
+#define IPT_CHAIN_MAXNAMELEN IPT_TABLE_MAXNAMELEN
+char closeActionTag[IPT_TABLE_MAXNAMELEN + 1];
+char closeRuleTag[IPT_TABLE_MAXNAMELEN + 1];
+char curTable[IPT_TABLE_MAXNAMELEN + 1];
+char curChain[IPT_CHAIN_MAXNAMELEN + 1];
+
+typedef struct chain
+{
+       char *chain;
+       char *policy;
+       struct ipt_counters count;
+       int created;
+} chain;
+
+#define maxChains 10240                /* max chains per table */
+static chain chains[maxChains];
+static int nextChain = 0;
+
+/* funCtion adding one argument to newargv, updating newargc 
+ * returns true if argument added, false otherwise */
+static int
+add_argv(char *what, int quoted)
+{
+       DEBUGP("add_argv: %d %s\n", newargc, what);
+       if (what && ((newargc + 1) < sizeof(newargv) / sizeof(char *))) {
+               newargv[newargc] = strdup(what);
+               newargvattr[newargc] = quoted;
+               newargc++;
+               return 1;
+       } else
+               return 0;
+}
+
+static void
+free_argv(void)
+{
+       int i;
+
+       for (i = 0; i < newargc; i++) {
+               free(newargv[i]);
+               newargv[i] = NULL;
+       }
+       newargc = 0;
+
+       for (i = 0; i < oldargc; i++) {
+               free(oldargv[i]);
+               oldargv[i] = NULL;
+       }
+       oldargc = 0;
+}
+
+/* save parsed rule for comparison with next rule 
+   to perform action agregation on duplicate conditions */
+static void
+save_argv(void)
+{
+       int i;
+
+       for (i = 0; i < oldargc; i++)
+               free(oldargv[i]);
+       oldargc = newargc;
+       newargc = 0;
+       for (i = 0; i < oldargc; i++) {
+               oldargv[i] = newargv[i];
+               newargv[i] = NULL;
+       }
+}
+
+/* like puts but with xml encoding */
+static void
+xmlEncode(char *text)
+{
+       while (text && *text) {
+               if ((unsigned char) (*text) >= 127)
+                       printf("&#%d;", (unsigned char) (*text));
+               else if (*text == '&')
+                       printf("&amp;");
+               else if (*text == '<')
+                       printf("&lt;");
+               else if (*text == '>')
+                       printf("&gt;");
+               else if (*text == '"')
+                       printf("&quot;");
+               else
+                       putchar(*text);
+               text++;
+       }
+}
+
+/* Output text as a comment, avoiding a double hyphen */
+static void
+xmlCommentEscape(char *comment)
+{
+       int h_count = 0;
+
+       while (comment && *comment) {
+               if (*comment == '-') {
+                       h_count++;
+                       if (h_count >= 2) {
+                               h_count = 0;
+                               putchar(' ');
+                       }
+                       putchar('*');
+               }
+               /* strip trailing newline */
+               if (*comment == '\n' && *(comment + 1) == 0);
+               else
+                       putchar(*comment);
+               comment++;
+       }
+}
+
+static void
+xmlComment(char *comment)
+{
+       printf("<!-- ");
+       xmlCommentEscape(comment);
+       printf(" -->\n");
+}
+
+static void
+xmlAttrS(char *name, char *value)
+{
+       printf("%s=\"", name);
+       xmlEncode(value);
+       printf("\" ");
+}
+
+static void
+xmlAttrI(char *name, long long int num)
+{
+       printf("%s=\"%lld\" ", name, num);
+}
+
+static void
+closeChain()
+{
+       if (curChain[0] == 0)
+               return;
+
+       if (closeActionTag[0])
+               printf("%s\n", closeActionTag);
+       closeActionTag[0] = 0;
+       if (closeRuleTag[0])
+               printf("%s\n", closeRuleTag);
+       closeRuleTag[0] = 0;
+       if (curChain[0])
+               printf("    </chain>\n");
+       curChain[0] = 0;
+       //lastRule[0]=0;
+}
+
+static void
+openChain(char *chain, char *policy, struct ipt_counters *ctr, char close)
+{
+       closeChain();
+
+       strncpy(curChain, chain, IPT_CHAIN_MAXNAMELEN);
+       curChain[IPT_CHAIN_MAXNAMELEN] = '\0';
+
+       printf("    <chain ");
+       xmlAttrS("name", curChain);
+       if (strcmp(policy, "-") != 0)
+               xmlAttrS("policy", policy);
+       xmlAttrI("packet-count", (unsigned long long) ctr->pcnt);
+       xmlAttrI("byte-count", (unsigned long long) ctr->bcnt);
+       if (close) {
+               printf("%c", close);
+               curChain[0] = 0;
+       }
+       printf(">\n");
+}
+
+static int
+existsChain(char *chain)
+{
+       /* open a saved chain */
+       int c = 0;
+
+       if (0 == strcmp(curChain, chain))
+               return 1;
+       for (c = 0; c < nextChain; c++)
+               if (chains[c].chain && strcmp(chains[c].chain, chain) == 0)
+                       return 1;
+       return 0;
+}
+
+static void
+needChain(char *chain)
+{
+       /* open a saved chain */
+       int c = 0;
+
+       if (0 == strcmp(curChain, chain))
+               return;
+
+       for (c = 0; c < nextChain; c++)
+               if (chains[c].chain && strcmp(chains[c].chain, chain) == 0) {
+                       openChain(chains[c].chain, chains[c].policy,
+                                 &(chains[c].count), '\0');
+                       /* And, mark it as done so we don't create 
+                          an empty chain at table-end time */
+                       chains[c].created = 1;
+               }
+}
+
+static void
+saveChain(char *chain, char *policy, struct ipt_counters *ctr)
+{
+       if (nextChain >= maxChains) {
+               exit_error(PARAMETER_PROBLEM,
+                          "%s: line %u chain name invalid\n",
+                          program_name, line);
+               exit(1);
+       };
+       chains[nextChain].chain = strdup(chain);
+       chains[nextChain].policy = strdup(policy);
+       chains[nextChain].count = *ctr;
+       chains[nextChain].created = 0;
+       nextChain++;
+}
+
+static void
+finishChains()
+{
+       int c;
+
+       for (c = 0; c < nextChain; c++)
+               if (!chains[c].created) {
+                       openChain(chains[c].chain, chains[c].policy,
+                                 &(chains[c].count), '/');
+                       free(chains[c].chain);
+                       free(chains[c].policy);
+               }
+       nextChain = 0;
+}
+
+static void
+closeTable()
+{
+       closeChain();
+       finishChains();
+       if (curTable[0])
+               printf("  </table>\n");
+       curTable[0] = 0;
+}
+
+static void
+openTable(char *table)
+{
+       closeTable();
+
+       strncpy(curTable, table, IPT_TABLE_MAXNAMELEN);
+       curTable[IPT_TABLE_MAXNAMELEN] = '\0';
+
+       printf("  <table ");
+       xmlAttrS("name", curTable);
+       printf(">\n");
+}
+
+// is char* -j --jump -g or --goto
+static int
+isTarget(char *arg)
+{
+       return ((arg)
+               && (strcmp((arg), "-j") == 0 || strcmp((arg), "--jump") == 0
+                   || strcmp((arg), "-g") == 0
+                   || strcmp((arg), "--goto") == 0));
+}
+
+// part=-1 means do conditions, part=1 means do rules, part=0 means do both
+static void
+do_rule_part(char *leveltag1, char *leveltag2, int part, int argc,
+            char *argv[], int argvattr[])
+{
+       int arg = 1;            // ignore leading -A
+       char invert_next = 0;
+       char *thisChain = NULL;
+       char *spacer = "";      // space when needed to assemble arguments
+       char *level1 = NULL;
+       char *level2 = NULL;
+       char *leveli1 = "        ";
+       char *leveli2 = "          ";
+
+#define CLOSE_LEVEL(LEVEL) \
+       do { \
+               if (level ## LEVEL) printf("</%s>\n", \
+               (leveltag ## LEVEL)?(leveltag ## LEVEL):(level ## LEVEL)); \
+               level ## LEVEL=NULL;\
+       } while(0)
+
+#define OPEN_LEVEL(LEVEL,TAG) \
+       do {\
+               level ## LEVEL=TAG;\
+               if (leveltag ## LEVEL) {\
+                       printf("%s<%s ", (leveli ## LEVEL), \
+                               (leveltag ## LEVEL));\
+                       xmlAttrS("type", (TAG)); \
+               } else printf("%s<%s ", (leveli ## LEVEL), (level ## LEVEL)); \
+       } while(0)
+
+       thisChain = argv[arg++];
+
+       if (part == 1) {        /* skip */
+               /* use argvattr to tell which arguments were quoted 
+                  to avoid comparing quoted arguments, like comments, to -j, */
+               while (arg < argc && (argvattr[arg] || !isTarget(argv[arg])))
+                       arg++;
+       }
+
+       /* Before we start, if the first arg is -[^-] and not -m or -j or -g 
+          then start a dummy <match> tag for old style built-in matches.  
+          We would do this in any case, but no need if it would be empty */
+       if (arg < argc && argv[arg][0] == '-' && !isTarget(argv[arg])
+           && strcmp(argv[arg], "-m") != 0) {
+               OPEN_LEVEL(1, "match");
+               printf(">\n");
+       }
+       while (arg < argc) {
+               // If ! is followed by -* then apply to that else output as data
+               // Stop, if we need to
+               if (part == -1 && !argvattr[arg] && (isTarget(argv[arg]))) {
+                       break;
+               } else if (!argvattr[arg] && strcmp(argv[arg], "!") == 0) {
+                       if ((arg + 1) < argc && argv[arg + 1][0] == '-')
+                               invert_next = '!';
+                       else
+                               printf("%s%s", spacer, argv[arg]);
+                       spacer = " ";
+               } else if (!argvattr[arg] && isTarget(argv[arg])
+                          && existsChain(argv[arg + 1])
+                          && (2 + arg >= argc)) {
+                       if (!((1 + arg) < argc))
+                               // no args to -j, -m or -g, ignore & finish loop
+                               break;
+                       CLOSE_LEVEL(2);
+                       if (level1)
+                               printf("%s", leveli1);
+                       CLOSE_LEVEL(1);
+                       spacer = "";
+                       invert_next = 0;
+                       if (strcmp(argv[arg], "-g") == 0
+                           || strcmp(argv[arg], "--goto") == 0) {
+                               /* goto user chain */
+                               OPEN_LEVEL(1, "goto");
+                               printf(">\n");
+                               arg++;
+                               OPEN_LEVEL(2, argv[arg]);
+                               printf("/>\n");
+                               level2 = NULL;
+                       } else {
+                               /* call user chain */
+                               OPEN_LEVEL(1, "call");
+                               printf(">\n");
+                               arg++;
+                               OPEN_LEVEL(2, argv[arg]);
+                               printf("/>\n");
+                               level2 = NULL;
+                       }
+               } else if (!argvattr[arg]
+                          && (isTarget(argv[arg])
+                              || strcmp(argv[arg], "-m") == 0
+                              || strcmp(argv[arg], "--module") == 0)) {
+                       if (!((1 + arg) < argc))
+                               // no args to -j, -m or -g, ignore & finish loop
+                               break;
+                       CLOSE_LEVEL(2);
+                       if (level1)
+                               printf("%s", leveli1);
+                       CLOSE_LEVEL(1);
+                       spacer = "";
+                       invert_next = 0;
+                       arg++;
+                       OPEN_LEVEL(1, (argv[arg]));
+                       // Optimize case, can we close this tag already?
+                       if ((arg + 1) >= argc || (!argvattr[arg + 1]
+                                                 && (isTarget(argv[arg + 1])
+                                                     || strcmp(argv[arg + 1],
+                                                               "-m") == 0
+                                                     || strcmp(argv[arg + 1],
+                                                               "--module") ==
+                                                     0))) {
+                               printf(" />\n");
+                               level1 = NULL;
+                       } else {
+                               printf(">\n");
+                       }
+               } else if (!argvattr[arg] && argv[arg][0] == '-') {
+                       char *tag;
+                       CLOSE_LEVEL(2);
+                       // Skip past any -
+                       tag = argv[arg];
+                       while (*tag == '-' && *tag)
+                               tag++;
+
+                       spacer = "";
+                       OPEN_LEVEL(2, tag);
+                       if (invert_next)
+                               printf(" invert=\"1\"");
+                       invert_next = 0;
+
+                       // Optimize case, can we close this tag already?
+                       if (!((arg + 1) < argc)
+                           || (argv[arg + 1][0] == '-' /* NOT QUOTED */ )) {
+                               printf(" />\n");
+                               level2 = NULL;
+                       } else {
+                               printf(">");
+                       }
+               } else {        // regular data
+                       char *spaces = strchr(argv[arg], ' ');
+                       printf("%s", spacer);
+                       if (spaces || argvattr[arg])
+                               printf("&quot;");
+                       // if argv[arg] contains a space, enclose in quotes
+                       xmlEncode(argv[arg]);
+                       if (spaces || argvattr[arg])
+                               printf("&quot;");
+                       spacer = " ";
+               }
+               arg++;
+       }
+       CLOSE_LEVEL(2);
+       if (level1)
+               printf("%s", leveli1);
+       CLOSE_LEVEL(1);
+
+       return;
+}
+
+static int
+compareRules()
+{
+       /* compare arguments up to -j or -g for match.
+          NOTE: We don't want to combine actions if there were no criteria 
+          in each rule, or rules didn't have an action 
+          NOTE: Depends on arguments being in some kind of "normal" order which 
+          is the case when processing the ACTUAL output of actual iptables-save 
+          rather than a file merely in a compatable format */
+
+       int old = 0;
+       int new = 0;
+
+       int compare = 0;
+
+       while (new < newargc && old < oldargc) {
+               if (isTarget(oldargv[old]) && isTarget(newargv[new])) {
+                       compare = 1;
+                       break;
+               }
+               // break when old!=new
+               if (strcmp(oldargv[old], newargv[new]) != 0) {
+                       compare = 0;
+                       break;
+               }
+
+               old++;
+               new++;
+       }
+       // We won't match unless both rules had a target. 
+       // This means we don't combine target-less rules, which is good
+
+       return compare == 1;
+}
+
+/* has a nice parsed rule starting with -A */
+static void
+do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[])
+{
+       /* are these conditions the same as the previous rule?
+        * If so, skip arg straight to -j or -g */
+       if (combine && argc > 2 && !isTarget(argv[2]) && compareRules()) {
+               xmlComment("Combine action from next rule");
+       } else {
+
+               if (closeActionTag[0]) {
+                       printf("%s\n", closeActionTag);
+                       closeActionTag[0] = 0;
+               }
+               if (closeRuleTag[0]) {
+                       printf("%s\n", closeRuleTag);
+                       closeRuleTag[0] = 0;
+               }
+
+               printf("      <rule ");
+               //xmlAttrS("table",curTable); // not needed in full mode 
+               //xmlAttrS("chain",argv[1]); // not needed in full mode 
+               if (pcnt)
+                       xmlAttrS("packet-count", pcnt);
+               if (bcnt)
+                       xmlAttrS("byte-count", bcnt);
+               printf(">\n");
+
+               strncpy(closeRuleTag, "      </rule>\n", IPT_TABLE_MAXNAMELEN);
+               closeRuleTag[IPT_TABLE_MAXNAMELEN] = '\0';
+
+               /* no point in writing out condition if there isn't one */
+               if (argc >= 3 && !isTarget(argv[2])) {
+                       printf("       <conditions>\n");
+                       do_rule_part(NULL, NULL, -1, argc, argv, argvattr);
+                       printf("       </conditions>\n");
+               }
+       }
+       /* Write out the action */
+       //do_rule_part("action","arg",1,argc,argv,argvattr);
+       if (!closeActionTag[0]) {
+               printf("       <actions>\n");
+               strncpy(closeActionTag, "       </actions>\n",
+                       IPT_TABLE_MAXNAMELEN);
+               closeActionTag[IPT_TABLE_MAXNAMELEN] = '\0';
+       }
+       do_rule_part(NULL, NULL, 1, argc, argv, argvattr);
+}
+
+
+#ifdef IPTABLES_MULTI
+int
+iptables_xml_main(int argc, char *argv[])
+#else
+int
+main(int argc, char *argv[])
+#endif
+{
+       char buffer[10240];
+       int c;
+       FILE *in;
+
+       program_name = "iptables-xml";
+       program_version = IPTABLES_VERSION;
+       line = 0;
+
+       while ((c = getopt_long(argc, argv, "cvh", options, NULL)) != -1) {
+               switch (c) {
+               case 'c':
+                       combine = 1;
+                       break;
+               case 'v':
+                       printf("xptables-xml\n");
+                       verbose = 1;
+                       break;
+               case 'h':
+                       print_usage("iptables-xml", IPTABLES_VERSION);
+                       break;
+               }
+       }
+
+       if (optind == argc - 1) {
+               in = fopen(argv[optind], "r");
+               if (!in) {
+                       fprintf(stderr, "Can't open %s: %s", argv[optind],
+                               strerror(errno));
+                       exit(1);
+               }
+       } else if (optind < argc) {
+               fprintf(stderr, "Unknown arguments found on commandline");
+               exit(1);
+       } else
+               in = stdin;
+
+       printf("<iptables-rules version=\"1.0\">\n");
+
+       /* Grab standard input. */
+       while (fgets(buffer, sizeof(buffer), in)) {
+               int ret = 0;
+
+               line++;
+
+               if (buffer[0] == '\n')
+                       continue;
+               else if (buffer[0] == '#') {
+                       xmlComment(buffer);
+                       continue;
+               }
+
+               if (verbose) {
+                       printf("<!-- line %d ", line);
+                       xmlCommentEscape(buffer);
+                       printf(" -->\n");
+               }
+
+               if ((strcmp(buffer, "COMMIT\n") == 0) && (curTable[0])) {
+                       DEBUGP("Calling commit\n");
+                       closeTable();
+                       ret = 1;
+               } else if ((buffer[0] == '*')) {
+                       /* New table */
+                       char *table;
+
+                       table = strtok(buffer + 1, " \t\n");
+                       DEBUGP("line %u, table '%s'\n", line, table);
+                       if (!table) {
+                               exit_error(PARAMETER_PROBLEM,
+                                          "%s: line %u table name invalid\n",
+                                          program_name, line);
+                               exit(1);
+                       }
+                       openTable(table);
+
+                       ret = 1;
+               } else if ((buffer[0] == ':') && (curTable[0])) {
+                       /* New chain. */
+                       char *policy, *chain;
+                       struct ipt_counters count;
+                       char *ctrs;
+
+                       chain = strtok(buffer + 1, " \t\n");
+                       DEBUGP("line %u, chain '%s'\n", line, chain);
+                       if (!chain) {
+                               exit_error(PARAMETER_PROBLEM,
+                                          "%s: line %u chain name invalid\n",
+                                          program_name, line);
+                               exit(1);
+                       }
+
+                       DEBUGP("Creating new chain '%s'\n", chain);
+
+                       policy = strtok(NULL, " \t\n");
+                       DEBUGP("line %u, policy '%s'\n", line, policy);
+                       if (!policy) {
+                               exit_error(PARAMETER_PROBLEM,
+                                          "%s: line %u policy invalid\n",
+                                          program_name, line);
+                               exit(1);
+                       }
+
+                       ctrs = strtok(NULL, " \t\n");
+                       parse_counters(ctrs, &count);
+                       saveChain(chain, policy, &count);
+
+                       ret = 1;
+               } else if (curTable[0]) {
+                       int a;
+                       char *ptr = buffer;
+                       char *pcnt = NULL;
+                       char *bcnt = NULL;
+                       char *parsestart;
+                       char *chain = NULL;
+
+                       /* the parser */
+                       char *param_start, *curchar;
+                       int quote_open, quoted;
+
+                       /* reset the newargv */
+                       newargc = 0;
+
+                       if (buffer[0] == '[') {
+                               /* we have counters in our input */
+                               ptr = strchr(buffer, ']');
+                               if (!ptr)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need ]\n",
+                                                  line);
+
+                               pcnt = strtok(buffer + 1, ":");
+                               if (!pcnt)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need :\n",
+                                                  line);
+
+                               bcnt = strtok(NULL, "]");
+                               if (!bcnt)
+                                       exit_error(PARAMETER_PROBLEM,
+                                                  "Bad line %u: need ]\n",
+                                                  line);
+
+                               /* start command parsing after counter */
+                               parsestart = ptr + 1;
+                       } else {
+                               /* start command parsing at start of line */
+                               parsestart = buffer;
+                       }
+
+
+                       /* This is a 'real' parser crafted in artist mode
+                        * not hacker mode. If the author can live with that
+                        * then so can everyone else */
+
+                       quote_open = 0;
+                       /* We need to know which args were quoted so we 
+                          can preserve quote */
+                       quoted = 0;
+                       param_start = parsestart;
+
+                       for (curchar = parsestart; *curchar; curchar++) {
+                               if (*curchar == '"') {
+                                       /* quote_open cannot be true if there
+                                        * was no previous character.  Thus, 
+                                        * curchar-1 has to be within bounds */
+                                       if (quote_open &&
+                                           *(curchar - 1) != '\\') {
+                                               quote_open = 0;
+                                               *curchar = ' ';
+                                       } else {
+                                               quote_open = 1;
+                                               quoted = 1;
+                                               param_start++;
+                                       }
+                               }
+                               if (*curchar == ' '
+                                   || *curchar == '\t' || *curchar == '\n') {
+                                       char param_buffer[1024];
+                                       int param_len = curchar - param_start;
+
+                                       if (quote_open)
+                                               continue;
+
+                                       if (!param_len) {
+                                               /* two spaces? */
+                                               param_start++;
+                                               continue;
+                                       }
+
+                                       /* end of one parameter */
+                                       strncpy(param_buffer, param_start,
+                                               param_len);
+                                       *(param_buffer + param_len) = '\0';
+
+                                       /* check if table name specified */
+                                       if (!strncmp(param_buffer, "-t", 3)
+                                           || !strncmp(param_buffer,
+                                                       "--table", 8)) {
+                                               exit_error(PARAMETER_PROBLEM,
+                                                          "Line %u seems to have a "
+                                                          "-t table option.\n",
+                                                          line);
+                                               exit(1);
+                                       }
+
+                                       add_argv(param_buffer, quoted);
+                                       if (newargc >= 2
+                                           && 0 ==
+                                           strcmp(newargv[newargc - 2], "-A"))
+                                               chain = newargv[newargc - 1];
+                                       quoted = 0;
+                                       param_start += param_len + 1;
+                               } else {
+                                       /* regular character, skip */
+                               }
+                       }
+
+                       DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
+                              newargc, curTable);
+
+                       for (a = 0; a < newargc; a++)
+                               DEBUGP("argv[%u]: %s\n", a, newargv[a]);
+
+                       needChain(chain);// Should we explicitly look for -A
+                       do_rule(pcnt, bcnt, newargc, newargv, newargvattr);
+
+                       save_argv();
+                       ret = 1;
+               }
+               if (!ret) {
+                       fprintf(stderr, "%s: line %u failed\n",
+                               program_name, line);
+                       exit(1);
+               }
+       }
+       if (curTable[0]) {
+               fprintf(stderr, "%s: COMMIT expected at line %u\n",
+                       program_name, line + 1);
+               exit(1);
+       }
+
+       printf("</iptables-rules>\n");
+       free_argv();
+
+       return 0;
+}
index 66800a5..9904c48 100644 (file)
@@ -486,8 +486,9 @@ Jozsef Kadlecsik wrote the REJECT target.
 .PP
 Harald Welte wrote the ULOG and NFQUEUE target, the new libiptc, as well as the TTL, DSCP, ECN matches and targets.
 .PP
-The Netfilter Core Team is: Marc Boucher, Martin Josefsson, Jozsef Kadlecsik, 
-Patrick McHardy, James Morris, Harald Welte and Rusty Russell.
+The Netfilter Core Team is: Marc Boucher, Martin Josefsson, Yasuyuki Kozakai,
+Jozsef Kadlecsik, Patrick McHardy, James Morris, Pablo Neira Ayuso,
+Harald Welte and Rusty Russell.
 .PP
 Man page originally written by Herve Eychenne <rv@wallfire.org>.
 .\" .. and did I mention that we are incredibly cool people?
index e22b9ea..893b02d 100644 (file)
@@ -79,8 +79,7 @@
 #define CMD_NEW_CHAIN          0x0100U
 #define CMD_DELETE_CHAIN       0x0200U
 #define CMD_SET_POLICY         0x0400U
-#define CMD_CHECK              0x0800U
-#define CMD_RENAME_CHAIN       0x1000U
+#define CMD_RENAME_CHAIN       0x0800U
 #define NUMBER_OF_CMD  13
 static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
                                 'N', 'X', 'P', 'E' };
@@ -160,20 +159,19 @@ static unsigned int global_option_offset = 0;
 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
 /* Well, it's better than "Re: Linux vs FreeBSD" */
 {
-       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  -f  --line */
-/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x'},
-/*LIST*/      {' ','x','x','x','x',' ',' ','x','x','x',' '},
-/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
-/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x'},
-/*CHECK*/     {'x','+','+','+','x',' ','x',' ',' ',' ','x'},
-/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x','x'}
+       /*     -n  -s  -d  -p  -j  -v  -x  -i  -o  -f  --line -c */
+/*INSERT*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x',' '},
+/*DELETE*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x','x'},
+/*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x','x'},
+/*REPLACE*/   {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x',' '},
+/*APPEND*/    {'x',' ',' ',' ',' ',' ','x',' ',' ',' ','x',' '},
+/*LIST*/      {' ','x','x','x','x',' ',' ','x','x','x',' ','x'},
+/*FLUSH*/     {'x','x','x','x','x',' ','x','x','x','x','x','x'},
+/*ZERO*/      {'x','x','x','x','x',' ','x','x','x','x','x','x'},
+/*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'},
+/*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x','x'},
+/*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x','x','x'},
+/*RENAME*/    {'x','x','x','x','x',' ','x','x','x','x','x','x'}
 };
 
 static int inverse_for_options[NUMBER_OF_OPT] =
@@ -188,7 +186,8 @@ static int inverse_for_options[NUMBER_OF_OPT] =
 /* -i */ IPT_INV_VIA_IN,
 /* -o */ IPT_INV_VIA_OUT,
 /* -f */ IPT_INV_FRAG,
-/*--line*/ 0
+/*--line*/ 0,
+/* -c */ 0,
 };
 
 const char *program_version;
@@ -197,6 +196,9 @@ char *lib_dir;
 
 int kernel_version;
 
+/* the path to command to load kernel module */
+const char *modprobe = NULL;
+
 /* Keeping track of external matches and targets: linked lists.  */
 struct iptables_match *iptables_matches = NULL;
 struct iptables_target *iptables_targets = NULL;
@@ -225,6 +227,7 @@ struct pprot {
 static const struct pprot chain_protos[] = {
        { "tcp", IPPROTO_TCP },
        { "udp", IPPROTO_UDP },
+       { "udplite", IPPROTO_UDPLITE },
        { "icmp", IPPROTO_ICMP },
        { "esp", IPPROTO_ESP },
        { "ah", IPPROTO_AH },
@@ -250,8 +253,37 @@ proto_to_name(u_int8_t proto, int nolookup)
        return NULL;
 }
 
-struct in_addr *
-dotted_to_addr(const char *dotted)
+int
+service_to_port(const char *name, const char *proto)
+{
+       struct servent *service;
+
+       if ((service = getservbyname(name, proto)) != NULL)
+               return ntohs((unsigned short) service->s_port);
+
+       return -1;
+}
+
+u_int16_t
+parse_port(const char *port, const char *proto)
+{
+       unsigned int portnum;
+
+       if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
+           (portnum = service_to_port(port, proto)) != -1)
+               return (u_int16_t)portnum;
+
+       exit_error(PARAMETER_PROBLEM,
+                  "invalid port/service `%s' specified", port);
+}
+
+enum {
+       IPT_DOTTED_ADDR = 0,
+       IPT_DOTTED_MASK
+};
+
+static struct in_addr *
+__dotted_to_addr(const char *dotted, int type)
 {
        static struct in_addr addr;
        unsigned char *addrp;
@@ -267,8 +299,20 @@ dotted_to_addr(const char *dotted)
 
        p = buf;
        for (i = 0; i < 3; i++) {
-               if ((q = strchr(p, '.')) == NULL)
-                       return (struct in_addr *) NULL;
+               if ((q = strchr(p, '.')) == NULL) {
+                       if (type == IPT_DOTTED_ADDR) {
+                               /* autocomplete, this is a network address */
+                               if (string_to_number(p, 0, 255, &onebyte) == -1)
+                                       return (struct in_addr *) NULL;
+
+                               addrp[i] = (unsigned char) onebyte;
+                               while (i < 3)
+                                       addrp[++i] = 0;
+
+                               return &addr;
+                       } else
+                               return (struct in_addr *) NULL;
+               }
 
                *q = '\0';
                if (string_to_number(p, 0, 255, &onebyte) == -1)
@@ -287,6 +331,18 @@ dotted_to_addr(const char *dotted)
        return &addr;
 }
 
+struct in_addr *
+dotted_to_addr(const char *dotted)
+{
+       return __dotted_to_addr(dotted, IPT_DOTTED_ADDR);
+}
+
+struct in_addr *
+dotted_to_mask(const char *dotted)
+{
+       return __dotted_to_addr(dotted, IPT_DOTTED_MASK);
+}
+
 static struct in_addr *
 network_to_addr(const char *name)
 {
@@ -623,7 +679,7 @@ parse_mask(char *mask)
                maskaddr.s_addr = 0xFFFFFFFF;
                return &maskaddr;
        }
-       if ((addrp = dotted_to_addr(mask)) != NULL)
+       if ((addrp = dotted_to_mask(mask)) != NULL)
                /* dotted_to_addr already returns a network byte order addr */
                return addrp;
        if (string_to_number(mask, 0, 32, &bits) == -1)
@@ -680,9 +736,24 @@ find_match(const char *name, enum ipt_tryload tryload, struct iptables_rule_matc
        struct iptables_match *ptr;
 
        for (ptr = iptables_matches; ptr; ptr = ptr->next) {
-               if (strcmp(name, ptr->name) == 0)
+               if (strcmp(name, ptr->name) == 0) {
+                       struct iptables_match *clone;
+                       
+                       /* First match of this type: */
+                       if (ptr->m == NULL)
+                               break;
+
+                       /* Second and subsequent clones */
+                       clone = fw_malloc(sizeof(struct iptables_match));
+                       memcpy(clone, ptr, sizeof(struct iptables_match));
+                       clone->mflags = 0;
+                       /* This is a clone: */
+                       clone->next = clone;
+
+                       ptr = clone;
                        break;
-       }
+               }
+       }               
 
 #ifndef NO_SHARED_LIBS
        if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
@@ -722,8 +793,12 @@ find_match(const char *name, enum ipt_tryload tryload, struct iptables_rule_matc
 
                newentry = fw_malloc(sizeof(struct iptables_rule_match));
 
-               for (i = matches; *i; i = &(*i)->next);
+               for (i = matches; *i; i = &(*i)->next) {
+                       if (strcmp(name, (*i)->match->name) == 0)
+                               (*i)->completed = 1;
+               }
                newentry->match = ptr;
+               newentry->completed = 0;
                newentry->next = NULL;
                *i = newentry;
        }
@@ -756,6 +831,13 @@ parse_protocol(const char *s)
        if (string_to_number(s, 0, 255, &proto) == -1) {
                struct protoent *pent;
 
+               /* first deal with the special case of 'all' to prevent
+                * people from being able to redefine 'all' in nsswitch
+                * and/or provoke expensive [not working] ldap/nis/... 
+                * lookups */
+               if (!strcmp(s, "all"))
+                       return 0;
+
                if ((pent = getprotobyname(s)))
                        proto = pent->p_proto;
                else {
@@ -803,10 +885,10 @@ void parse_interface(const char *arg, char *vianame, unsigned char *mask)
                memset(mask, 0xFF, vialen + 1);
                memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
                for (i = 0; vianame[i]; i++) {
-                       if (!isalnum(vianame[i]) 
-                           && vianame[i] != '_' 
-                           && vianame[i] != '.') {
-                               printf("Warning: wierd character in interface"
+                       if (vianame[i] == ':' ||
+                           vianame[i] == '!' ||
+                           vianame[i] == '*') {
+                               printf("Warning: weird character in interface"
                                       " `%s' (No aliases, :, ! or *).\n",
                                       vianame);
                                break;
@@ -1068,6 +1150,8 @@ static int compatible_revision(const char *name, u_int8_t revision, int opt)
                exit(1);
        }
 
+       load_iptables_ko(modprobe, 1);
+
        strcpy(rev.name, name);
        rev.revision = revision;
 
@@ -1730,10 +1814,10 @@ static char *get_modprobe(void)
        return NULL;
 }
 
-int iptables_insmod(const char *modname, const char *modprobe)
+int iptables_insmod(const char *modname, const char *modprobe, int quiet)
 {
        char *buf = NULL;
-       char *argv[3];
+       char *argv[4];
        int status;
 
        /* If they don't explicitly set it, read out of kernel */
@@ -1748,7 +1832,13 @@ int iptables_insmod(const char *modname, const char *modprobe)
        case 0:
                argv[0] = (char *)modprobe;
                argv[1] = (char *)modname;
-               argv[2] = NULL;
+               if (quiet) {
+                       argv[2] = "-q";
+                       argv[3] = NULL;
+               } else {
+                       argv[2] = NULL;
+                       argv[3] = NULL;
+               }
                execv(argv[0], argv);
 
                /* not usually reached */
@@ -1766,6 +1856,19 @@ int iptables_insmod(const char *modname, const char *modprobe)
        return -1;
 }
 
+int load_iptables_ko(const char *modprobe, int quiet)
+{
+       static int loaded = 0;
+       static int ret = -1;
+
+       if (!loaded) {
+               ret = iptables_insmod("ip_tables", modprobe, quiet);
+               loaded = (ret == 0);
+       }
+
+       return ret;
+}
+
 static struct ipt_entry *
 generate_entry(const struct ipt_entry *fw,
               struct iptables_rule_match *matches,
@@ -1800,8 +1903,14 @@ void clear_rule_matches(struct iptables_rule_match **matches)
 
        for (matchp = *matches; matchp;) {
                tmp = matchp->next;
-               if (matchp->match->m)
+               if (matchp->match->m) {
                        free(matchp->match->m);
+                       matchp->match->m = NULL;
+               }
+               if (matchp->match == matchp->match->next) {
+                       free(matchp->match);
+                       matchp->match = NULL;
+               }
                free(matchp);
                matchp = tmp;
        }
@@ -1853,7 +1962,6 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
        struct iptables_target *t;
        const char *jumpto = "";
        char *protocol = NULL;
-       const char *modprobe = NULL;
        int proto_used = 0;
 
        memset(&fw, 0, sizeof(fw));
@@ -2126,7 +2234,9 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                        set_revision(m->m->u.user.name, m->revision);
                        if (m->init != NULL)
                                m->init(m->m, &fw.nfcache);
-                       opts = merge_options(opts, m->extra_opts, &m->option_offset);
+                       if (m != m->next)
+                               /* Merge options for non-cloned matches */
+                               opts = merge_options(opts, m->extra_opts, &m->option_offset);
                }
                break;
 
@@ -2204,14 +2314,14 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                        exit_tryhelp(2);
 
                default:
-                       /* FIXME: This scheme doesn't allow two of the same
-                          matches --RR */
                        if (!target
                            || !(target->parse(c - target->option_offset,
                                               argv, invert,
                                               &target->tflags,
                                               &fw, &target->t))) {
                                for (matchp = matches; matchp; matchp = matchp->next) {
+                                       if (matchp->completed) 
+                                               continue;
                                        if (matchp->match->parse(c - matchp->match->option_offset,
                                                     argv, invert,
                                                     &matchp->match->mflags,
@@ -2226,7 +2336,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                   actually hear this code suck. */
 
                                /* some explanations (after four different bugs
-                                * in 3 different releases): If we encountere a
+                                * in 3 different releases): If we encounter a
                                 * parameter, that has not been parsed yet,
                                 * it's not an option of an explicitly loaded
                                 * match or a target.  However, we support
@@ -2339,7 +2449,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                *handle = iptc_init(*table);
 
        /* try to insmod the module if iptc_init failed */
-       if (!*handle && iptables_insmod("ip_tables", modprobe) != -1)
+       if (!*handle && load_iptables_ko(modprobe, 0) != -1)
                *handle = iptc_init(*table);
 
        if (!*handle)
diff --git a/iptables.xslt b/iptables.xslt
new file mode 100644 (file)
index 0000000..4cf8419
--- /dev/null
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- Converts from simple xml iptables format to iptables-save format  
+     Copyright 2006 UfoMechanic 
+     Author: azez@ufomechanic.net 
+     This code is distributed and licensed under the terms of GNU GPL v2
+     
+     This sample usage outputs roughly want goes in
+       iptables-save | iptables-xml -c | xsltproc iptables.xslt -
+     -->
+<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:output method = "text" />
+  <xsl:strip-space elements="*" />
+
+  <!-- output conditions of a rule but not an action -->
+  <xsl:template match="iptables-rules/table/chain/rule/conditions/*">
+    <!-- <match> is the psuedo module when a match module doesn't need to be loaded
+         and when -m does not need to be inserted -->
+    <xsl:if test="name() != 'match'">
+      <xsl:text> -m </xsl:text><xsl:value-of select="name()"/>
+    </xsl:if>
+    <xsl:apply-templates select="node()"/>
+  </xsl:template>
+
+  <!-- delete the actions or conditions containers, and process child nodes -->
+  <xsl:template match="iptables-rules/table/chain/rule/actions|table/chain/rule/conditions">
+    <xsl:apply-templates select="*"/>
+  </xsl:template>
+
+  <xsl:template match="iptables-rules/table/chain/rule/actions/goto">
+    <xsl:text> -g </xsl:text>
+    <xsl:apply-templates select="*"/>
+    <xsl:text>&#xA;</xsl:text>
+  </xsl:template>
+  <xsl:template match="iptables-rules/table/chain/rule/actions/call">
+    <xsl:text> -j </xsl:text>
+    <xsl:apply-templates select="*"/>
+    <xsl:text>&#xA;</xsl:text>
+  </xsl:template>
+  <!-- all other actions are module actions -->
+  <xsl:template match="iptables-rules/table/chain/rule/actions/*">
+    <xsl:text> -j </xsl:text><xsl:value-of select="name()"/>
+    <xsl:apply-templates select="*"/>
+    <xsl:text>&#xA;</xsl:text>
+  </xsl:template>
+  
+  <!-- all child action nodes -->
+  <xsl:template match="iptables-rules/table/chain/rule/actions/*/*|iptables-rules/table/chain/rule/actions/*//*|iptables-rules/table/chain/rule/conditions/*/*|iptables-rules/table/chain/rule/conditions/*//*">
+    <xsl:if test="@invert=1"><xsl:text> !</xsl:text></xsl:if>
+    <xsl:text> -</xsl:text>
+    <!-- if length of name is 1 character, then only do 1 - not 2 -->
+    <xsl:if test="string-length(name())&gt;1">
+      <xsl:text>-</xsl:text>
+    </xsl:if>
+    <xsl:value-of select="name()"/>
+    <xsl:text> </xsl:text><xsl:value-of select="."/>
+  </xsl:template>
+
+  <xsl:template match="iptables-rules/table/chain/rule/actions/call/*|iptables-rules/table/chain/rule/actions/goto/*">
+    <xsl:value-of select="name()"/>
+    <!-- I bet there are no child nodes, should we risk it? -->
+    <xsl:apply-templates select="node()"/>
+  </xsl:template>
+
+  <!-- output the head of the rule, and any conditions -->
+  <xsl:template name="rule-head">
+    <xsl:if test="string-length(@packet-count)+string-length(@byte-count)">
+      <xsl:call-template name="counters"><xsl:with-param name="node" select="."/></xsl:call-template>
+      <xsl:text> </xsl:text>
+    </xsl:if>
+    <xsl:text>-A </xsl:text><!-- a rule must be under a chain -->
+    <xsl:value-of select="../@name" />
+    <xsl:apply-templates select="conditions"/>
+  </xsl:template>
+
+  <!-- Output a single rule, perhaps as multiple rules if we have more than one action -->
+  <xsl:template match="iptables-rules/table/chain/rule">
+    <xsl:choose>
+      <xsl:when test="count(actions/*)&gt;0">
+        <xsl:for-each select="actions/*">
+          <!-- and a for-each to re-select the rule as the current node, to write the rule-head -->
+          <xsl:for-each select="../..">
+            <xsl:call-template name="rule-head"/>
+          </xsl:for-each>
+          <!-- now write the this action -->
+          <xsl:apply-templates select="."/>
+        </xsl:for-each>
+      </xsl:when>
+      <xsl:otherwise>
+        <!-- no need to loop if there are no actions, just output conditions -->
+        <xsl:call-template name="rule-head"/>
+        <xsl:text>&#xA;</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="iptables-rules/table">
+    <xsl:text># Generated by iptables.xslt&#xA;</xsl:text>
+    <xsl:text>*</xsl:text><xsl:value-of select="@name"/><xsl:text>&#xA;</xsl:text>
+    <!-- Loop through each chain and output the chain header -->
+    <xsl:for-each select="chain">
+      <xsl:text>:</xsl:text>
+      <xsl:value-of select="@name"/>
+      <xsl:text> </xsl:text>
+      <xsl:choose>
+        <xsl:when test="not(string-length(@policy))"><xsl:text>-</xsl:text></xsl:when>
+        <xsl:otherwise><xsl:value-of select="@policy"/></xsl:otherwise>
+      </xsl:choose>
+      <xsl:text> </xsl:text>
+      <xsl:call-template name="counters"><xsl:with-param name="node" select="."/></xsl:call-template>
+      <xsl:text>&#xA;</xsl:text>
+    </xsl:for-each>
+    <!-- Loop through each chain and output the rules -->
+    <xsl:apply-templates select="node()"/>
+    <xsl:text>COMMIT&#xA;# Completed&#xA;</xsl:text>
+  </xsl:template>
+  
+  <xsl:template name="counters">
+    <xsl:param name="$node"/>
+    <xsl:text>[</xsl:text>
+    <xsl:if test="string-length($node/@packet-count)"><xsl:value-of select="$node/@packet-count"/></xsl:if>
+    <xsl:if test="string-length($node/@packet-count)=0">0</xsl:if>
+    <xsl:text>:</xsl:text>
+    <xsl:if test="string-length($node/@byte-count)"><xsl:value-of select="$node/@byte-count"/></xsl:if>
+    <xsl:if test="string-length($node/@byte-count)=0">0</xsl:if>
+    <xsl:text>]</xsl:text>
+  </xsl:template>  
+  
+  <!-- the bit that automatically recurses for us, NOTE: we use * not node(), we don't want to copy every white space text -->
+  <xsl:template match="@*|node()">
+    <xsl:copy>
+      <!-- with libxslt xsltproc we can't do @*|node() or the nodes may get processed before the attributes -->
+      <xsl:apply-templates select="@*"/>
+      <xsl:apply-templates select="node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:transform>
index 1fbebef..180de13 100644 (file)
@@ -2,7 +2,8 @@
 
 EXTRAS+=libiptc/libiptc.a
 
-DEVEL_LIBS+=libiptc/libiptc.a
+# libiptc is not a public interface and therefore not installed
+# DEVEL_LIBS+=libiptc/libiptc.a
 
 ifndef TOPLEVEL_INCLUDED
 local:
index 2e8647c..a0cdc2f 100644 (file)
@@ -94,6 +94,8 @@ typedef unsigned int socklen_t;
 #define TC_FREE                        iptc_free
 #define TC_COMMIT              iptc_commit
 #define TC_STRERROR            iptc_strerror
+#define TC_NUM_RULES           iptc_num_rules
+#define TC_GET_RULE            iptc_get_rule
 
 #define TC_AF                  AF_INET
 #define TC_IPPROTO             IPPROTO_IP
index 8ca5ea6..5b3ae0b 100644 (file)
@@ -89,6 +89,8 @@ typedef unsigned int socklen_t;
 #define TC_FREE                        ip6tc_free
 #define TC_COMMIT              ip6tc_commit
 #define TC_STRERROR            ip6tc_strerror
+#define TC_NUM_RULES           ip6tc_num_rules
+#define TC_GET_RULE            ip6tc_get_rule
 
 #define TC_AF                  AF_INET6
 #define TC_IPPROTO             IPPROTO_IPV6
index a281e89..1c17480 100644 (file)
@@ -1,4 +1,4 @@
-/* Library which manipulates firewall rules.  Version $Revision: 4511 $ */
+/* Library which manipulates firewall rules.  Version $Revision: 6665 $ */
 
 /* Architecture of firewall rules is as follows:
  *
@@ -1519,6 +1519,14 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
                DEBUGP("unable to map target of rule for chain `%s'\n", chain);
                free(r);
                return 0;
+       } else {
+               /* iptcc_map_target increment target chain references
+                * since this is a fake rule only used for matching
+                * the chain references count is decremented again. 
+                */
+               if (r->type == IPTCC_R_JUMP
+                   && r->jump)
+                       r->jump->references--;
        }
 
        list_for_each_entry(i, &c->rules, list) {
@@ -1648,6 +1656,9 @@ TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
                return 0;
        }
 
+       if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
+               c->counter_map.maptype = COUNTER_MAP_ZEROED;
+
        list_for_each_entry(r, &c->rules, list) {
                if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
                        r->counter_map.maptype = COUNTER_MAP_ZEROED;
@@ -2096,10 +2107,8 @@ TC_COMMIT(TC_HANDLE_T *handle)
 
        ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
                         sizeof(*repl) + repl->size);
-       if (ret < 0) {
-               errno = ret;
+       if (ret < 0)
                goto out_free_newcounters;
-       }
 
        /* Put counters back. */
        strcpy(newcounters->name, (*handle)->info.name);
@@ -2190,10 +2199,8 @@ TC_COMMIT(TC_HANDLE_T *handle)
 
        ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
                         newcounters, counterlen);
-       if (ret < 0) {
-               errno = ret;
+       if (ret < 0)
                goto out_free_newcounters;
-       }
 
        free(repl->counters);
        free(repl);