--- /dev/null
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter.h linux-2.6.0-test7/include/linux/netfilter.h
+--- linux-2.6.0-test7.org/include/linux/netfilter.h 2003-10-08 21:24:06.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter.h 2003-10-10 11:53:17.000000000 +0200
+@@ -23,6 +23,7 @@
+ <= 0x2000 is used for protocol-flags. */
+ #define NFC_UNKNOWN 0x4000
+ #define NFC_ALTERED 0x8000
++#define NFC_TRACE 0x10000
+
+ #ifdef __KERNEL__
+ #include <linux/config.h>
+@@ -99,6 +100,24 @@
+
+ extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
+
++typedef void nf_logfn(unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const char *prefix);
++
++/* Function to register/unregister log function. */
++int nf_log_register(int pf, nf_logfn *logfn);
++void nf_log_unregister(int pf, nf_logfn *logfn);
++
++/* Calls the registered backend logging function */
++void nf_log_packet(int pf,
++ unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const char *fmt, ...);
++
+ /* Activate hook; either okfn or kfree_skb called, unless a hook
+ returns NF_STOLEN (in which case, it's up to the hook to deal with
+ the consequences).
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.0-test7/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ip_conntrack.h 2003-10-08 21:24:48.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4/ip_conntrack.h 2003-10-10 11:53:17.000000000 +0200
+@@ -268,6 +268,9 @@
+
+ extern unsigned int ip_conntrack_htable_size;
+
++/* A fake conntrack entry which never vanishes. */
++extern struct ip_conntrack ip_conntrack_untracked;
++
+ /* eg. PROVIDES_CONNTRACK(ftp); */
+ #define PROVIDES_CONNTRACK(name) \
+ int needs_ip_conntrack_##name; \
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.0-test7/include/linux/netfilter_ipv4/ip_tables.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ip_tables.h 2003-10-08 21:24:07.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4/ip_tables.h 2003-10-10 11:53:17.000000000 +0200
+@@ -134,6 +134,12 @@
+ /* Back pointer */
+ unsigned int comefrom;
+
++ /* Name of the chain */
++ char *chainname;
++
++ /* Rule number in the chain. */
++ u_int32_t rulenum;
++
+ /* Packet and byte counters. */
+ struct ipt_counters counters;
+
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_ULOG.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_ULOG.h 2003-10-08 21:24:04.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_ULOG.h 2003-10-10 11:52:57.000000000 +0200
+@@ -11,6 +11,9 @@
+ #define NETLINK_NFLOG 5
+ #endif
+
++#define NFLOG_DEFAULT_NLGROUP 1
++#define NFLOG_DEFAULT_QTHRESHOLD 1
++
+ #define ULOG_MAC_LEN 80
+ #define ULOG_PREFIX_LEN 32
+
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_conntrack.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-10-08 21:24:26.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-10-10 11:53:17.000000000 +0200
+@@ -10,6 +10,7 @@
+
+ #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
+ #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
++#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
+
+ /* flags, invflags: */
+ #define IPT_CONNTRACK_STATE 0x01
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_sctp.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_sctp.h 2003-10-10 11:53:27.000000000 +0200
+@@ -0,0 +1,25 @@
++/* iptables module for matching the SCTP header
++ *
++ * (C) 2003 Harald Welte <laforge@gnumonks.org>
++ *
++ * This software is distributed under GNU GPL v2, 1991
++ *
++ * $Id$
++ */
++#ifndef _IPT_SCTP_H
++#define _IPT_SCTP_H
++
++struct ipt_sctp_info {
++ u_int16_t spts[2]; /* Souce port range */
++ u_int16_t dpts[2]; /* Destination port range */
++ u_int32_t chunks; /* chunks to be matched */
++ u_int32_t chunk_mask; /* chunk mask to be matched */
++ u_int8_t invflags; /* Inverse flags */
++};
++
++#define IPT_SCTP_INV_SRCPT 0x01 /* Invert the sense of source ports */
++#define IPT_SCTP_INV_DSTPT 0x02 /* Invert the sense of dest ports */
++#define IPT_SCTP_INV_CHUNKS 0x03 /* Invert the sense of chunks */
++#define IPT_SCTP_INV_MASK 0x03 /* All possible flags */
++
++#endif /* _IPT_SCTP_H */
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_state.h linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_state.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4/ipt_state.h 2003-10-08 21:24:42.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4/ipt_state.h 2003-10-10 11:53:17.000000000 +0200
+@@ -4,6 +4,8 @@
+ #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
+ #define IPT_STATE_INVALID (1 << 0)
+
++#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
++
+ struct ipt_state_info
+ {
+ unsigned int statemask;
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv4.h linux-2.6.0-test7/include/linux/netfilter_ipv4.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv4.h 2003-10-08 21:24:32.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv4.h 2003-10-10 11:53:17.000000000 +0200
+@@ -51,6 +51,8 @@
+
+ enum nf_ip_hook_priorities {
+ NF_IP_PRI_FIRST = INT_MIN,
++ NF_IP_PRI_CONNTRACK_DEFRAG = -400,
++ NF_IP_PRI_RAW = -300,
+ NF_IP_PRI_CONNTRACK = -200,
+ NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
+ NF_IP_PRI_MANGLE = -150,
+diff -Nur linux-2.6.0-test7.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.0-test7/include/linux/netfilter_ipv6/ip6_tables.h
+--- linux-2.6.0-test7.org/include/linux/netfilter_ipv6/ip6_tables.h 2003-10-08 21:24:51.000000000 +0200
++++ linux-2.6.0-test7/include/linux/netfilter_ipv6/ip6_tables.h 2003-10-10 11:53:17.000000000 +0200
+@@ -140,6 +140,12 @@
+ /* Back pointer */
+ unsigned int comefrom;
+
++ /* Name of the chain */
++ char *chainname;
++
++ /* Rule number in the chain. */
++ u_int32_t rulenum;
++
+ /* Packet and byte counters. */
+ struct ip6t_counters counters;
+
+diff -Nur linux-2.6.0-test7.org/net/core/netfilter.c linux-2.6.0-test7/net/core/netfilter.c
+--- linux-2.6.0-test7.org/net/core/netfilter.c 2003-10-08 21:24:04.000000000 +0200
++++ linux-2.6.0-test7/net/core/netfilter.c 2003-10-10 11:52:57.000000000 +0200
+@@ -8,8 +8,10 @@
+ *
+ * February 2000: Modified by James Morris to have 1 queue per protocol.
+ * 15-Mar-2000: Added NF_REPEAT --RR.
++ * 08-May-2003: Internal logging interface added by Jozsef Kadlecsik.
+ */
+ #include <linux/config.h>
++#include <linux/kernel.h>
+ #include <linux/netfilter.h>
+ #include <net/protocol.h>
+ #include <linux/init.h>
+@@ -743,7 +745,70 @@
+ EXPORT_SYMBOL(skb_ip_make_writable);
+ #endif /*CONFIG_INET*/
+
++/* Internal logging interface, which relies on the real
++ LOG target modules */
+
++#define NF_LOG_PREFIXLEN 128
++
++static nf_logfn *nf_logging[NPROTO]; /* = NULL */
++static int reported = 0;
++static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
++
++int nf_log_register(int pf, nf_logfn *logfn)
++{
++ int ret = -EBUSY;
++
++ /* Any setup of logging members must be done before
++ * substituting pointer. */
++ smp_wmb();
++ spin_lock(&nf_log_lock);
++ if (!nf_logging[pf]) {
++ nf_logging[pf] = logfn;
++ ret = 0;
++ }
++ spin_unlock(&nf_log_lock);
++ return ret;
++}
++
++void nf_log_unregister(int pf, nf_logfn *logfn)
++{
++ spin_lock(&nf_log_lock);
++ if (nf_logging[pf] == logfn)
++ nf_logging[pf] = NULL;
++ spin_unlock(&nf_log_lock);
++
++ /* Give time to concurrent readers. */
++ synchronize_net();
++}
++
++void nf_log_packet(int pf,
++ unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const char *fmt, ...)
++{
++ va_list args;
++ char prefix[NF_LOG_PREFIXLEN];
++ nf_logfn *logfn;
++
++ rcu_read_lock();
++ logfn = nf_logging[pf];
++ if (logfn) {
++ va_start(args, fmt);
++ vsnprintf(prefix, sizeof(prefix), fmt, args);
++ va_end(args);
++ /* We must read logging before nf_logfn[pf] */
++ smp_read_barrier_depends();
++ logfn(hooknum, skb, in, out, prefix);
++ } else if (!reported) {
++ printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
++ "no backend logging module loaded in!\n");
++ reported++;
++ }
++ rcu_read_unlock();
++}
++
+ /* This does not belong here, but ipt_REJECT needs it if connection
+ tracking in use: without this, connection may not be in hash table,
+ and hence manufactured ICMP or RST packets will not be associated
+@@ -773,3 +838,6 @@
+ EXPORT_SYMBOL(nf_unregister_hook);
+ EXPORT_SYMBOL(nf_unregister_queue_handler);
+ EXPORT_SYMBOL(nf_unregister_sockopt);
++EXPORT_SYMBOL(nf_log_register);
++EXPORT_SYMBOL(nf_log_unregister);
++EXPORT_SYMBOL(nf_log_packet);
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/Kconfig linux-2.6.0-test7/net/ipv4/netfilter/Kconfig
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/Kconfig 2003-10-08 21:24:27.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/Kconfig 2003-10-10 11:53:27.000000000 +0200
+@@ -197,6 +197,15 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_MATCH_SCTP
++ tristate "SCTP match support"
++ depends on IP_NF_IPTABLES
++ help
++ This match allows iptables to match on the SCTP header.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
+ config IP_NF_MATCH_LENGTH
+ tristate "LENGTH match support"
+ depends on IP_NF_IPTABLES
+@@ -527,6 +536,42 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_RAW
++ tristate "Raw table"
++ depends on IP_NF_IPTABLES
++ help
++ This option adds a `raw' table to iptables: see the man page for
++ iptables(8). This table is the very first in the netfilter
++ framework and hooks in at the PREROUTING and OUTPUT chains.
++ The TRACE and NOTRACK targets can be used in this table only.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_TARGET_TRACE
++ tristate "TRACE target support"
++ depends on IP_NF_RAW
++ help
++ The TRACE target allows packets to be traced as those matches
++ any subsequent rule in any table/rule. The matched rule and
++ the packet is logged with the prefix
++
++ TRACE: tablename/chainname/rulenum
++
++ if the ipt_LOG or ipt_ULOG targets are loaded in.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP_NF_TARGET_NOTRACK
++ tristate "NOTRACK target support"
++ depends on IP_NF_RAW
++ help
++ The NOTRACK target allows a select rule to specify which
++ packets *not* to enter the conntrack/NAT subsystems
++ with all the consequences (no ICMP error tracking,
++ no protocol helpers for the selected packets).
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+ config IP_NF_ARPTABLES
+ tristate "ARP tables support"
+
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/Makefile linux-2.6.0-test7/net/ipv4/netfilter/Makefile
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/Makefile 2003-10-08 21:24:02.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/Makefile 2003-10-10 11:53:27.000000000 +0200
+@@ -34,12 +34,14 @@
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+
+-# the three instances of ip_tables
++# the four instances of ip_tables
+ obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
+ obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
+ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
++obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
+
+ # matches
++obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
+ obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
+ obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+ obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
+@@ -81,6 +83,8 @@
+ obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
+ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
+ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
++obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
++obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
+
+ # generic ARP tables
+ obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_amanda.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_amanda.c 2003-10-08 21:24:17.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_amanda.c 2003-10-10 11:52:23.000000000 +0200
+@@ -210,5 +210,7 @@
+ PROVIDES_CONNTRACK(amanda);
+ EXPORT_SYMBOL(ip_amanda_lock);
+
++EXPORT_SYMBOL(ip_amanda_lock);
++
+ module_init(init);
+ module_exit(fini);
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_core.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_core.c 2003-10-08 21:24:00.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_core.c 2003-10-10 11:53:17.000000000 +0200
+@@ -29,8 +29,7 @@
+ #include <linux/slab.h>
+ #include <linux/random.h>
+ #include <linux/jhash.h>
+-/* For ERR_PTR(). Yeah, I know... --RR */
+-#include <linux/fs.h>
++#include <linux/err.h>
+
+ /* This rwlock protects the main hash table, protocol/helper/expected
+ registrations, conntrack timers*/
+@@ -63,6 +62,7 @@
+ static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
+ struct list_head *ip_conntrack_hash;
+ static kmem_cache_t *ip_conntrack_cachep;
++struct ip_conntrack ip_conntrack_untracked;
+
+ extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
+
+@@ -808,18 +808,10 @@
+ }
+ #endif
+
+- /* Previously seen (loopback)? Ignore. Do this before
+- fragment check. */
++ /* Previously seen (loopback or untracked)? Ignore. */
+ if ((*pskb)->nfct)
+ return NF_ACCEPT;
+
+- /* Gather fragments. */
+- if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+- *pskb = ip_ct_gather_frags(*pskb);
+- if (!*pskb)
+- return NF_STOLEN;
+- }
+-
+ proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
+
+ /* It may be an icmp error... */
+@@ -953,7 +945,6 @@
+ }
+ } else if (related_to->helper->max_expected &&
+ related_to->expecting >= related_to->helper->max_expected) {
+- struct list_head *cur_item;
+ /* old == NULL */
+ if (!(related_to->helper->flags &
+ IP_CT_HELPER_F_REUSE_EXPECT)) {
+@@ -978,21 +969,14 @@
+ NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
+
+ /* choose the the oldest expectation to evict */
+- list_for_each(cur_item, &related_to->sibling_list) {
+- struct ip_conntrack_expect *cur;
+-
+- cur = list_entry(cur_item,
+- struct ip_conntrack_expect,
+- expected_list);
+- if (cur->sibling == NULL) {
+- old = cur;
++ list_for_each_entry(old, &related_to->sibling_list,
++ expected_list)
++ if (old->sibling == NULL)
+ break;
+- }
+- }
+
+- /* (!old) cannot happen, since related_to->expecting is the
+- * number of unconfirmed expects */
+- IP_NF_ASSERT(old);
++ /* We cannot fail since related_to->expecting is the number
++ * of unconfirmed expectations */
++ IP_NF_ASSERT(old && old->sibling == NULL);
+
+ /* newnat14 does not reuse the real allocated memory
+ * structures but rather unexpects the old and
+@@ -1024,7 +1008,7 @@
+ atomic_set(&new->use, 1);
+
+ /* add to expected list for this connection */
+- list_add(&new->expected_list, &related_to->sibling_list);
++ list_add_tail(&new->expected_list, &related_to->sibling_list);
+ /* add to global list of expectations */
+ list_prepend(&ip_conntrack_expect_list, &new->list);
+ /* add and start timer if required */
+@@ -1419,6 +1403,15 @@
+
+ /* For use by ipt_REJECT */
+ ip_ct_attach = ip_conntrack_attach;
++
++ /* Set up fake conntrack:
++ - to never be deleted, not in any hashes */
++ atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
++ /* - and look it like as a confirmed connection */
++ set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
++ /* - and prepare the ctinfo field for NAT. */
++ ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
++
+ return ret;
+
+ err_free_hash:
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-10-08 21:24:04.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-10-10 11:53:17.000000000 +0200
+@@ -186,6 +186,26 @@
+ return ip_conntrack_confirm(*pskb);
+ }
+
++static unsigned int ip_conntrack_defrag(unsigned int hooknum,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ /* Previously seen (loopback)? Ignore. Do this before
++ fragment check. */
++ if ((*pskb)->nfct)
++ return NF_ACCEPT;
++
++ /* Gather fragments. */
++ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
++ *pskb = ip_ct_gather_frags(*pskb);
++ if (!*pskb)
++ return NF_STOLEN;
++ }
++ return NF_ACCEPT;
++}
++
+ static unsigned int ip_refrag(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+@@ -225,6 +245,15 @@
+ return ip_conntrack_in(hooknum, pskb, in, out, okfn);
+ }
+
++/* At the very first: defragment */
++static struct nf_hook_ops ip_conntrack_defrag_ops = {
++ .hook = ip_conntrack_defrag,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_PRE_ROUTING,
++ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
++};
++
+ /* Connection tracking may drop packets, but never alters them, so
+ make it the first hook. */
+ static struct nf_hook_ops ip_conntrack_in_ops = {
+@@ -367,10 +396,15 @@
+ if (!proc) goto cleanup_init;
+ proc->owner = THIS_MODULE;
+
++ ret = nf_register_hook(&ip_conntrack_defrag_ops);
++ if (ret < 0) {
++ printk("ip_conntrack: can't register pre-routing hook to defrag.\n");
++ goto cleanup_proc;
++ }
+ ret = nf_register_hook(&ip_conntrack_in_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register pre-routing hook.\n");
+- goto cleanup_proc;
++ goto cleanup_defragops;
+ }
+ ret = nf_register_hook(&ip_conntrack_local_out_ops);
+ if (ret < 0) {
+@@ -408,6 +442,8 @@
+ nf_unregister_hook(&ip_conntrack_local_out_ops);
+ cleanup_inops:
+ nf_unregister_hook(&ip_conntrack_in_ops);
++ cleanup_defragops:
++ nf_unregister_hook(&ip_conntrack_defrag_ops);
+ cleanup_proc:
+ proc_net_remove("ip_conntrack");
+ cleanup_init:
+@@ -499,5 +535,6 @@
+ EXPORT_SYMBOL(ip_conntrack_expect_list);
+ EXPORT_SYMBOL(ip_conntrack_lock);
+ EXPORT_SYMBOL(ip_conntrack_hash);
++EXPORT_SYMBOL(ip_conntrack_untracked);
+ EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
+ EXPORT_SYMBOL_GPL(ip_conntrack_put);
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_tftp.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_conntrack_tftp.c 2003-10-08 21:24:03.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_conntrack_tftp.c 2003-10-10 11:52:47.000000000 +0200
+@@ -97,8 +97,6 @@
+
+ for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+ /* Create helper structure */
+- memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
+-
+ tftp[i].tuple.dst.protonum = IPPROTO_UDP;
+ tftp[i].tuple.src.u.udp.port = htons(ports[i]);
+ tftp[i].mask.dst.protonum = 0xFFFF;
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_amanda.c linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_amanda.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_amanda.c 2003-10-08 21:24:02.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_amanda.c 2003-10-10 11:52:47.000000000 +0200
+@@ -195,8 +195,6 @@
+ struct ip_nat_helper *hlpr;
+
+ hlpr = &ip_nat_amanda_helper;
+- memset(hlpr, 0, sizeof(struct ip_nat_helper));
+-
+ hlpr->tuple.dst.protonum = IPPROTO_UDP;
+ hlpr->tuple.src.u.udp.port = htons(10080);
+ hlpr->mask.src.u.udp.port = 0xFFFF;
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_core.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_core.c 2003-10-08 21:24:02.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_core.c 2003-10-10 11:53:17.000000000 +0200
+@@ -809,7 +809,7 @@
+
+ /* Have to grab read lock before sibling_list traversal */
+ READ_LOCK(&ip_conntrack_lock);
+- list_for_each(cur_item, &ct->sibling_list) {
++ list_for_each_prev(cur_item, &ct->sibling_list) {
+ exp = list_entry(cur_item, struct ip_conntrack_expect,
+ expected_list);
+
+@@ -1009,7 +1009,11 @@
+ /* FIXME: Man, this is a hack. <SIGH> */
+ IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
+ ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
+-
++
++ /* Initialize fake conntrack so that NAT will skip it */
++ ip_conntrack_untracked.nat.info.initialized |=
++ (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
++
+ return 0;
+ }
+
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_rule.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_rule.c 2003-10-08 21:24:04.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_rule.c 2003-10-10 11:53:17.000000000 +0200
+@@ -67,7 +67,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* POST_ROUTING */
+@@ -75,7 +75,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_OUT */
+@@ -83,7 +83,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } }
+ },
+@@ -92,7 +92,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_error),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
+ { } },
+ "ERROR"
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_tftp.c linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_tftp.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_nat_tftp.c 2003-10-08 21:24:03.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_nat_tftp.c 2003-10-10 11:52:47.000000000 +0200
+@@ -164,8 +164,6 @@
+ ports[0] = TFTP_PORT;
+
+ for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+- memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
+-
+ tftp[i].tuple.dst.protonum = IPPROTO_UDP;
+ tftp[i].tuple.src.u.udp.port = htons(ports[i]);
+ tftp[i].mask.dst.protonum = 0xFFFF;
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ip_tables.c linux-2.6.0-test7/net/ipv4/netfilter/ip_tables.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ip_tables.c 2003-10-08 21:24:02.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ip_tables.c 2003-10-10 11:53:17.000000000 +0200
+@@ -11,6 +11,7 @@
+ #include <linux/config.h>
+ #include <linux/cache.h>
+ #include <linux/skbuff.h>
++#include <linux/socket.h>
+ #include <linux/kmod.h>
+ #include <linux/vmalloc.h>
+ #include <linux/netdevice.h>
+@@ -23,8 +24,17 @@
+ #include <asm/semaphore.h>
+ #include <linux/proc_fs.h>
+
++#include <linux/netfilter.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+
++static const char *hooknames[] = {
++ [NF_IP_PRE_ROUTING] "PREROUTING",
++ [NF_IP_LOCAL_IN] "INPUT",
++ [NF_IP_FORWARD] "FORWARD",
++ [NF_IP_LOCAL_OUT] "OUTPUT",
++ [NF_IP_POST_ROUTING] "POSTROUTING",
++};
++
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+ MODULE_DESCRIPTION("IPv4 packet filter");
+@@ -322,6 +332,12 @@
+
+ t = ipt_get_target(e);
+ IP_NF_ASSERT(t->u.kernel.target);
++
++ /* The packet traced and the rule isn't an unconditional return/END. */
++ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
++ nf_log_packet(AF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
++ table->name, e->chainname, e->rulenum);
++ }
+ /* Standard target? */
+ if (!t->u.kernel.target->target) {
+ int v;
+@@ -474,6 +490,29 @@
+ return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
+ }
+
++static inline int
++find_error_target(struct ipt_entry *s,
++ struct ipt_entry *e,
++ char **chainname)
++{
++ struct ipt_entry_target *t;
++ static struct ipt_entry *found = NULL;
++
++ if (s == e) {
++ if (!found)
++ return 0;
++ t = ipt_get_target(found);
++ if (strcmp(t->u.user.name,
++ IPT_ERROR_TARGET) == 0) {
++ *chainname = t->data;
++ return 1;
++ }
++ } else
++ found = s;
++
++ return 0;
++}
++
+ /* All zeroes == unconditional rule. */
+ static inline int
+ unconditional(const struct ipt_ip *ip)
+@@ -493,6 +532,8 @@
+ mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
+ {
+ unsigned int hook;
++ char *chainname = NULL;
++ u_int32_t rulenum;
+
+ /* No recursion; use packet counter to save back ptrs (reset
+ to 0 as we leave), and comefrom to save source hook bitmask */
+@@ -506,6 +547,8 @@
+
+ /* Set initial back pointer. */
+ e->counters.pcnt = pos;
++ rulenum = 1;
++ chainname = (char *) hooknames[hook];
+
+ for (;;) {
+ struct ipt_standard_target *t
+@@ -518,6 +561,8 @@
+ }
+ e->comefrom
+ |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
++ e->rulenum = rulenum++;
++ e->chainname = chainname;
+
+ /* Unconditional return/END. */
+ if (e->target_offset == sizeof(struct ipt_entry)
+@@ -527,6 +572,10 @@
+ && unconditional(&e->ip)) {
+ unsigned int oldpos, size;
+
++ /* Set unconditional rulenum to zero. */
++ e->rulenum = 0;
++ e->counters.bcnt = 0;
++
+ /* Return: backtrack through the last
+ big jump. */
+ do {
+@@ -552,6 +601,11 @@
+ (newinfo->entries + pos);
+ } while (oldpos == pos + e->next_offset);
+
++ /* Restore chainname, rulenum. */
++ chainname = e->chainname;
++ rulenum = e->counters.bcnt;
++ e->counters.bcnt = 0;
++
+ /* Move along one */
+ size = e->next_offset;
+ e = (struct ipt_entry *)
+@@ -567,6 +621,17 @@
+ /* This a jump; chase it. */
+ duprintf("Jump rule %u -> %u\n",
+ pos, newpos);
++ e->counters.bcnt = rulenum++;
++ rulenum = 1;
++ e = (struct ipt_entry *)
++ (newinfo->entries + newpos);
++ if (IPT_ENTRY_ITERATE(newinfo->entries,
++ newinfo->size,
++ find_error_target,
++ e, &chainname) == 0) {
++ printk("ip_tables: table screwed up!\n");
++ return 0;
++ }
+ } else {
+ /* ... this is a fallthru */
+ newpos = pos + e->next_offset;
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_LOG.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_LOG.c 2003-10-08 21:24:43.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_LOG.c 2003-10-10 11:52:57.000000000 +0200
+@@ -4,12 +4,14 @@
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
+ #include <linux/skbuff.h>
++#include <linux/socket.h>
+ #include <linux/ip.h>
+ #include <net/icmp.h>
+ #include <net/udp.h>
+ #include <net/tcp.h>
+ #include <net/route.h>
+
++#include <linux/netfilter.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+ #include <linux/netfilter_ipv4/ipt_LOG.h>
+
+@@ -17,6 +19,10 @@
+ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+ MODULE_DESCRIPTION("iptables syslog logging module");
+
++static unsigned int nflog = 1;
++MODULE_PARM(nflog, "i");
++MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
++
+ #if 0
+ #define DEBUGP printk
+ #else
+@@ -315,28 +321,25 @@
+ /* maxlen = 230+ 91 + 230 + 252 = 803 */
+ }
+
+-static unsigned int
+-ipt_log_target(struct sk_buff **pskb,
++static void
++ipt_log_packet(unsigned int hooknum,
++ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+- unsigned int hooknum,
+- const void *targinfo,
+- void *userinfo)
++ const struct ipt_log_info *loginfo,
++ const char *level_string,
++ const char *prefix)
+ {
+- const struct ipt_log_info *loginfo = targinfo;
+- char level_string[4] = "< >";
+-
+- level_string[1] = '0' + (loginfo->level % 8);
+ spin_lock_bh(&log_lock);
+ printk(level_string);
+ printk("%sIN=%s OUT=%s ",
+- loginfo->prefix,
++ prefix == NULL ? loginfo->prefix : prefix,
+ in ? in->name : "",
+ out ? out->name : "");
+ #ifdef CONFIG_BRIDGE_NETFILTER
+- if ((*pskb)->nf_bridge) {
+- struct net_device *physindev = (*pskb)->nf_bridge->physindev;
+- struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
++ if (skb->nf_bridge) {
++ struct net_device *physindev = skb->nf_bridge->physindev;
++ struct net_device *physoutdev = skb->nf_bridge->physoutdev;
+
+ if (physindev && in != physindev)
+ printk("PHYSIN=%s ", physindev->name);
+@@ -348,25 +351,56 @@
+ if (in && !out) {
+ /* MAC logging for input chain only. */
+ printk("MAC=");
+- if ((*pskb)->dev && (*pskb)->dev->hard_header_len
+- && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
++ if (skb->dev && skb->dev->hard_header_len
++ && skb->mac.raw != (void*)skb->nh.iph) {
+ int i;
+- unsigned char *p = (*pskb)->mac.raw;
+- for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
++ unsigned char *p = skb->mac.raw;
++ for (i = 0; i < skb->dev->hard_header_len; i++,p++)
+ printk("%02x%c", *p,
+- i==(*pskb)->dev->hard_header_len - 1
++ i==skb->dev->hard_header_len - 1
+ ? ' ':':');
+ } else
+ printk(" ");
+ }
+
+- dump_packet(loginfo, *pskb, 0);
++ dump_packet(loginfo, skb, 0);
+ printk("\n");
+ spin_unlock_bh(&log_lock);
++}
++
++static unsigned int
++ipt_log_target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ipt_log_info *loginfo = targinfo;
++ char level_string[4] = "< >";
++
++ level_string[1] = '0' + (loginfo->level % 8);
++ ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
+
+ return IPT_CONTINUE;
+ }
+
++static void
++ipt_logfn(unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const char *prefix)
++{
++ struct ipt_log_info loginfo = {
++ .level = 0,
++ .logflags = IPT_LOG_MASK,
++ .prefix = ""
++ };
++
++ ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
++}
++
+ static int ipt_log_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+@@ -406,12 +440,17 @@
+ {
+ if (ipt_register_target(&ipt_log_reg))
+ return -EINVAL;
++ if (nflog)
++ nf_log_register(PF_INET, &ipt_logfn);
+
+ return 0;
+ }
+
+ static void __exit fini(void)
+ {
++ if (nflog)
++ nf_log_unregister(PF_INET, &ipt_logfn);
++
+ ipt_unregister_target(&ipt_log_reg);
+ }
+
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_NOTRACK.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_NOTRACK.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_NOTRACK.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_NOTRACK.c 2003-10-10 11:53:17.000000000 +0200
+@@ -0,0 +1,79 @@
++/* This is a module which is used for setting up fake conntracks
++ * on packets so that they are not seen by the conntrack/NAT code.
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++
++static unsigned int
++target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userinfo)
++{
++ /* Previously seen (loopback)? Ignore. */
++ if ((*pskb)->nfct != NULL)
++ return IPT_CONTINUE;
++
++ /* Attach fake conntrack entry.
++ If there is a real ct entry correspondig to this packet,
++ it'll hang aroun till timing out. We don't deal with it
++ for performance reasons. JK */
++ (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
++ nf_conntrack_get((*pskb)->nfct);
++
++ return IPT_CONTINUE;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ if (targinfosize != 0) {
++ printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
++ targinfosize);
++ return 0;
++ }
++
++ if (strcmp(tablename, "raw") != 0) {
++ printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_notrack_reg = {
++ .name = "NOTRACK",
++ .target = target,
++ .checkentry = checkentry,
++ .destroy = NULL,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ if (ipt_register_target(&ipt_notrack_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_notrack_reg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
++MODULE_DESCRIPTION("IPv4 NOTRACK target");
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_TRACE.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_TRACE.c 2003-10-10 11:53:17.000000000 +0200
+@@ -0,0 +1,67 @@
++/* This is a module which is used for setting
++ * the NFC_TRACE flag in the nfcache field of an skb.
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++static unsigned int
++target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo,
++ void *userinfo)
++{
++ (*pskb)->nfcache |= NFC_TRACE;
++ return IPT_CONTINUE;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ if (targinfosize != 0) {
++ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
++ targinfosize);
++ return 0;
++ }
++
++ if (strcmp(tablename, "raw") != 0) {
++ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ipt_target ipt_trace_reg = {
++ .name = "TRACE",
++ .target = target,
++ .checkentry = checkentry,
++ .destroy = NULL,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ if (ipt_register_target(&ipt_trace_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_target(&ipt_trace_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
++MODULE_DESCRIPTION("IPv4 TRACE target");
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_ULOG.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_ULOG.c 2003-10-08 21:24:03.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_ULOG.c 2003-10-10 11:52:57.000000000 +0200
+@@ -45,6 +45,7 @@
+ #include <linux/netlink.h>
+ #include <linux/netdevice.h>
+ #include <linux/mm.h>
++#include <linux/netfilter.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+ #include <linux/netfilter_ipv4/ipt_ULOG.h>
+ #include <linux/netfilter_ipv4/lockhelp.h>
+@@ -75,6 +76,10 @@
+ MODULE_PARM(flushtimeout, "i");
+ MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
+
++static unsigned int nflog = 1;
++MODULE_PARM(nflog, "i");
++MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
++
+ /* global data structures */
+
+ typedef struct {
+@@ -152,17 +157,17 @@
+ return skb;
+ }
+
+-static unsigned int ipt_ulog_target(struct sk_buff **pskb,
+- const struct net_device *in,
+- const struct net_device *out,
+- unsigned int hooknum,
+- const void *targinfo, void *userinfo)
++static void ipt_ulog_packet(unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const struct ipt_ulog_info *loginfo,
++ const char *prefix)
+ {
+ ulog_buff_t *ub;
+ ulog_packet_msg_t *pm;
+ size_t size, copy_len;
+ struct nlmsghdr *nlh;
+- struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
+
+ /* ffs == find first bit set, necessary because userspace
+ * is already shifting groupnumber, but we need unshifted.
+@@ -171,8 +176,8 @@
+
+ /* calculate the size of the skb needed */
+ if ((loginfo->copy_range == 0) ||
+- (loginfo->copy_range > (*pskb)->len)) {
+- copy_len = (*pskb)->len;
++ (loginfo->copy_range > skb->len)) {
++ copy_len = skb->len;
+ } else {
+ copy_len = loginfo->copy_range;
+ }
+@@ -209,19 +214,21 @@
+
+ /* copy hook, prefix, timestamp, payload, etc. */
+ pm->data_len = copy_len;
+- pm->timestamp_sec = (*pskb)->stamp.tv_sec;
+- pm->timestamp_usec = (*pskb)->stamp.tv_usec;
+- pm->mark = (*pskb)->nfmark;
++ pm->timestamp_sec = skb->stamp.tv_sec;
++ pm->timestamp_usec = skb->stamp.tv_usec;
++ pm->mark = skb->nfmark;
+ pm->hook = hooknum;
+- if (loginfo->prefix[0] != '\0')
++ if (prefix != NULL)
++ strncpy(pm->prefix, prefix, sizeof(pm->prefix));
++ else if (loginfo->prefix[0] != '\0')
+ strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
+ else
+ *(pm->prefix) = '\0';
+
+ if (in && in->hard_header_len > 0
+- && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
++ && skb->mac.raw != (void *) skb->nh.iph
+ && in->hard_header_len <= ULOG_MAC_LEN) {
+- memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
++ memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
+ pm->mac_len = in->hard_header_len;
+ } else
+ pm->mac_len = 0;
+@@ -236,8 +243,8 @@
+ else
+ pm->outdev_name[0] = '\0';
+
+- /* copy_len <= (*pskb)->len, so can't fail. */
+- if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
++ /* copy_len <= skb->len, so can't fail. */
++ if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
+ BUG();
+
+ /* check if we are building multi-part messages */
+@@ -261,8 +268,7 @@
+
+ UNLOCK_BH(&ulog_lock);
+
+- return IPT_CONTINUE;
+-
++ return;
+
+ nlmsg_failure:
+ PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
+@@ -271,8 +277,35 @@
+ PRINTR("ipt_ULOG: Error building netlink message\n");
+
+ UNLOCK_BH(&ulog_lock);
++}
++
++static unsigned int ipt_ulog_target(struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ unsigned int hooknum,
++ const void *targinfo, void *userinfo)
++{
++ struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
+
+- return IPT_CONTINUE;
++ ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
++
++ return IPT_CONTINUE;
++}
++
++static void ipt_logfn(unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const char *prefix)
++{
++ struct ipt_ulog_info loginfo = {
++ .nl_group = NFLOG_DEFAULT_NLGROUP,
++ .copy_range = 0,
++ .qthreshold = NFLOG_DEFAULT_QTHRESHOLD,
++ .prefix = ""
++ };
++
++ ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
+ }
+
+ static int ipt_ulog_checkentry(const char *tablename,
+@@ -337,6 +370,9 @@
+ return -EINVAL;
+ }
+
++ if (nflog)
++ nf_log_register(PF_INET, &ipt_logfn);
++
+ return 0;
+ }
+
+@@ -347,6 +383,9 @@
+
+ DEBUGP("ipt_ULOG: cleanup_module\n");
+
++ if (nflog)
++ nf_log_unregister(PF_INET, &ipt_logfn);
++
+ ipt_unregister_target(&ipt_ulog_reg);
+ sock_release(nflognl->sk_socket);
+
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_conntrack.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_conntrack.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_conntrack.c 2003-10-08 21:24:44.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_conntrack.c 2003-10-10 11:53:17.000000000 +0200
+@@ -29,7 +29,9 @@
+
+ #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
+
+- if (ct)
++ if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
++ statebit = IPT_CONNTRACK_STATE_UNTRACKED;
++ else if (ct)
+ statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
+ else
+ statebit = IPT_CONNTRACK_STATE_INVALID;
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_sctp.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_sctp.c 2003-10-10 11:53:27.000000000 +0200
+@@ -0,0 +1,125 @@
++/* IP tables module for matching the SCTP header
++ *
++ * $ipt_sctp.c,v 1.3 2002/05/29 15:09:00 laforge Exp$
++ *
++ * (C) 2003 by Harald Welte <laforge@gnumonks.org>
++ *
++ * This software is distributed under the terms GNU GPL v2
++ */
++
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/sctp.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_sctp.h>
++
++MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
++MODULE_DESCRIPTION("IP tables SCTP matching module");
++MODULE_LICENSE("GPL");
++
++/* Returns 1 if the port is matched by the range, 0 otherwise */
++static inline int
++port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
++{
++ int ret;
++
++ ret = (port >= min && port <= max) ^ invert;
++ return ret;
++}
++
++static int chunk_match(const struct sk_buff *skb, u_int32_t chunks, u_int32_t chunk_mask)
++{
++ sctp_chunkhdr_t *ch = (sctp_chunkhdr_t *) skb->data;
++
++ u_int32_t chunks_present = 0;
++
++ do {
++ u_int8_t *ch_end;
++ ch_end = ((u_int8_t *) ch) + WORD_ROUND(ntohs(ch->length));
++
++ if (ch->type < 32)
++ chunks_present |= (1 << ch_type);
++ else if (ch->type == SCTP_CID_ASCONF)
++ chunks_present |= (1 << 31);
++ else if (ch->type == SCTP_CID_ASCONF_ACK)
++ chunks_present |= (1 << 30);
++
++ ch = (sctp_chunkhdr_t *) ch_end;
++ } while (ch_end < skb->tail);
++
++ return ((chunks_present& chunk_mask) == chunks);
++}
++
++static int match(const struct sk_buff *skb, const struct net_device *in,
++ const struct net_device *out, const void *matchinfo,
++ int offset, const void *hdr, u_int16_t datalen,
++ int *hotdrop)
++{
++ const struct ipt_sctp_info *info = matchinfo;
++ const struct iphdr *iph = skb->nh.iph;
++ const struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
++
++ if (iph->protocol != IPPROTO_SCTP)
++ return 0;
++
++ if (offset == 1) {
++ duprintf("Dropping evil SCTP offset=1 frag.\n");
++ *hotdrop = 1;
++ return 0;
++ } else if (offset == 0 && datalen < sizeof(struct sctphdr)) {
++ /* We've been askd o examine this packet, and we can't.
++ * Hence, no choice but to drop. */
++ duprintf("Dropping evil SCTP offset=0 tinygram.\n");
++ *hotdrop = 1;
++ return 0;
++ }
++
++ return (!offset
++ && port_match(info->spts[0], info->spts[1],
++ ntohs(sh->source),
++ !!(info->invflags & IPT_SCTP_INV_SRCPT))
++ && port_match(info->dpts[0], info->dpts[1],
++ ntohs(sh->dest),
++ !!(info->invflags & IPT_SCTP_INV_DSTPT))
++ && chunk_match(skb, info->chunks, info->chunk_mask)
++ );
++}
++
++static int checkentry(const char *tablename, const struct ipt_ip *ip,
++ void *matchinfo, unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ const struct ipt_sctp_info *info = matchinfo;
++
++ if (matchsize != IPT_ALIGN(sizeof(struct ipt_sctp_info)))
++ return 0;
++
++ if (ip->proto != IPPROTO_SCTP && !(ip->invflags & IPT_INV_PROTO))
++ return 0;
++
++ if !(info->invflags & ~IPT_SCTP_INV_MASK)
++ return 0;
++
++ return 1;
++}
++
++static struct ipt_match sctp_match = {
++ .name = "sctp",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ return ipt_register_match(&sctp_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&sctp_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_state.c linux-2.6.0-test7/net/ipv4/netfilter/ipt_state.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/ipt_state.c 2003-10-08 21:24:53.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/ipt_state.c 2003-10-10 11:53:17.000000000 +0200
+@@ -23,10 +23,12 @@
+ enum ip_conntrack_info ctinfo;
+ unsigned int statebit;
+
+- if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
+- statebit = IPT_STATE_INVALID;
+- else
++ if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
++ statebit = IPT_STATE_UNTRACKED;
++ else if (ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
+ statebit = IPT_STATE_BIT(ctinfo);
++ else
++ statebit = IPT_STATE_INVALID;
+
+ return (sinfo->statemask & statebit);
+ }
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.0-test7/net/ipv4/netfilter/iptable_filter.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/iptable_filter.c 2003-10-08 21:24:04.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/iptable_filter.c 2003-10-10 11:53:17.000000000 +0200
+@@ -52,7 +52,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* FORWARD */
+@@ -60,7 +60,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_OUT */
+@@ -68,7 +68,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } }
+ },
+@@ -77,7 +77,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_error),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
+ { } },
+ "ERROR"
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.0-test7/net/ipv4/netfilter/iptable_mangle.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/iptable_mangle.c 2003-10-08 21:24:43.000000000 +0200
++++ linux-2.6.0-test7/net/ipv4/netfilter/iptable_mangle.c 2003-10-10 11:53:17.000000000 +0200
+@@ -69,7 +69,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_IN */
+@@ -77,7 +77,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* FORWARD */
+@@ -85,7 +85,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_OUT */
+@@ -93,7 +93,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* POST_ROUTING */
+@@ -101,7 +101,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ },
+@@ -110,7 +110,7 @@
+ 0,
+ sizeof(struct ipt_entry),
+ sizeof(struct ipt_error),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
+ { } },
+ "ERROR"
+diff -Nur linux-2.6.0-test7.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.0-test7/net/ipv4/netfilter/iptable_raw.c
+--- linux-2.6.0-test7.org/net/ipv4/netfilter/iptable_raw.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/net/ipv4/netfilter/iptable_raw.c 2003-10-10 11:53:17.000000000 +0200
+@@ -0,0 +1,153 @@
++/*
++ * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
++ *
++ * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ */
++#include <linux/module.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
++
++/* Standard entry. */
++struct ipt_standard
++{
++ struct ipt_entry entry;
++ struct ipt_standard_target target;
++};
++
++struct ipt_error_target
++{
++ struct ipt_entry_target target;
++ char errorname[IPT_FUNCTION_MAXNAMELEN];
++};
++
++struct ipt_error
++{
++ struct ipt_entry entry;
++ struct ipt_error_target target;
++};
++
++static struct
++{
++ struct ipt_replace repl;
++ struct ipt_standard entries[2];
++ struct ipt_error term;
++} initial_table __initdata
++= { { "raw", RAW_VALID_HOOKS, 3,
++ sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
++ { [NF_IP_PRE_ROUTING] 0,
++ [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
++ { [NF_IP_PRE_ROUTING] 0,
++ [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
++ 0, NULL, { } },
++ {
++ /* PRE_ROUTING */
++ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
++ 0,
++ sizeof(struct ipt_entry),
++ sizeof(struct ipt_standard),
++ 0, NULL, 0, { 0, 0 }, { } },
++ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
++ -NF_ACCEPT - 1 } },
++ /* LOCAL_OUT */
++ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
++ 0,
++ sizeof(struct ipt_entry),
++ sizeof(struct ipt_standard),
++ 0, NULL, 0, { 0, 0 }, { } },
++ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
++ -NF_ACCEPT - 1 } }
++ },
++ /* ERROR */
++ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
++ 0,
++ sizeof(struct ipt_entry),
++ sizeof(struct ipt_error),
++ 0, NULL, 0, { 0, 0 }, { } },
++ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
++ { } },
++ "ERROR"
++ }
++ }
++};
++
++static struct ipt_table packet_raw = {
++ .name = "raw",
++ .table = &initial_table.repl,
++ .valid_hooks = RAW_VALID_HOOKS,
++ .lock = RW_LOCK_UNLOCKED,
++ .me = THIS_MODULE,
++};
++
++/* The work comes in here from netfilter.c. */
++static unsigned int
++ipt_hook(unsigned int hook,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
++}
++
++/* 'raw' is the very first table. */
++static struct nf_hook_ops ipt_ops[] = {
++ { /* PRE_ROUTING hook */
++ .hook = ipt_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_PRE_ROUTING,
++ .priority = NF_IP_PRI_RAW,
++ },
++ { /* LOCAL_OUT hook */
++ .hook = ipt_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET,
++ .hooknum = NF_IP_LOCAL_OUT,
++ .priority = NF_IP_PRI_RAW,
++ },
++};
++
++static int __init init(void)
++{
++ int ret;
++
++ /* Register table */
++ ret = ipt_register_table(&packet_raw);
++ if (ret < 0)
++ return ret;
++
++ /* Register hooks */
++ ret = nf_register_hook(&ipt_ops[0]);
++ if (ret < 0)
++ goto cleanup_table;
++
++ ret = nf_register_hook(&ipt_ops[1]);
++ if (ret < 0)
++ goto cleanup_hook0;
++
++ return ret;
++
++ cleanup_hook0:
++ nf_unregister_hook(&ipt_ops[0]);
++ cleanup_table:
++ ipt_unregister_table(&packet_raw);
++
++ return ret;
++}
++
++static void __exit fini(void)
++{
++ unsigned int i;
++
++ for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
++ nf_unregister_hook(&ipt_ops[i]);
++
++ ipt_unregister_table(&packet_raw);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
++MODULE_DESCRIPTION("IPv4 raw table");
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/Kconfig linux-2.6.0-test7/net/ipv6/netfilter/Kconfig
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/Kconfig 2003-10-08 21:24:43.000000000 +0200
++++ linux-2.6.0-test7/net/ipv6/netfilter/Kconfig 2003-10-10 11:53:17.000000000 +0200
+@@ -217,6 +217,31 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP6_NF_RAW
++ tristate "Raw table"
++ depends on IP6_NF_IPTABLES
++ help
++ This option adds a `raw' table to iptables: see the man page for
++ iptables(8). This table is the very first in the netfilter
++ framework and hooks in at the PREROUTING and OUTPUT chains.
++ The TRACE target can be used in this table only.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
++config IP6_NF_TARGET_TRACE
++ tristate "TRACE target support"
++ depends on IP6_NF_RAW
++ help
++ The TRACE target allows packets to be traced as those matches
++ any subsequent rule in any IPv6 netfilter table/rule. The matched
++ rule and the packet is logged with the prefix
++
++ TRACE: tablename/chainname/rulenum
++
++ if the ip6t_LOG target is loaded in.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+ #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
+ endmenu
+
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/Makefile linux-2.6.0-test7/net/ipv6/netfilter/Makefile
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/Makefile 2003-10-08 21:24:15.000000000 +0200
++++ linux-2.6.0-test7/net/ipv6/netfilter/Makefile 2003-10-10 11:53:17.000000000 +0200
+@@ -18,7 +18,9 @@
+ obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
+ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
+ obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
++obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
+ obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+ obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
+ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
++obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
+ obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.0-test7/net/ipv6/netfilter/ip6_tables.c
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/ip6_tables.c 2003-10-08 21:24:43.000000000 +0200
++++ linux-2.6.0-test7/net/ipv6/netfilter/ip6_tables.c 2003-10-10 11:53:18.000000000 +0200
+@@ -12,6 +12,7 @@
+ */
+ #include <linux/config.h>
+ #include <linux/skbuff.h>
++#include <linux/socket.h>
+ #include <linux/kmod.h>
+ #include <linux/vmalloc.h>
+ #include <linux/netdevice.h>
+@@ -24,8 +25,17 @@
+ #include <asm/semaphore.h>
+ #include <linux/proc_fs.h>
+
++#include <linux/netfilter.h>
+ #include <linux/netfilter_ipv6/ip6_tables.h>
+
++static const char *hook6names[] = {
++ [NF_IP6_PRE_ROUTING] "PREROUTING",
++ [NF_IP6_LOCAL_IN] "INPUT",
++ [NF_IP6_FORWARD] "FORWARD",
++ [NF_IP6_LOCAL_OUT] "OUTPUT",
++ [NF_IP6_POST_ROUTING] "POSTROUTING",
++};
++
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+ MODULE_DESCRIPTION("IPv6 packet filter");
+@@ -403,6 +413,12 @@
+
+ t = ip6t_get_target(e);
+ IP_NF_ASSERT(t->u.kernel.target);
++
++ /* The packet traced and the rule isn't an unconditional return/END. */
++ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
++ nf_log_packet(AF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
++ table->name, e->chainname, e->rulenum);
++ }
+ /* Standard target? */
+ if (!t->u.kernel.target->target) {
+ int v;
+@@ -556,6 +572,29 @@
+ return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
+ }
+
++static inline int
++find_error_target(struct ip6t_entry *s,
++ struct ip6t_entry *e,
++ char **chainname)
++{
++ struct ip6t_entry_target *t;
++ static struct ip6t_entry *found = NULL;
++
++ if (s == e) {
++ if (!found)
++ return 0;
++ t = ip6t_get_target(found);
++ if (strcmp(t->u.user.name,
++ IP6T_ERROR_TARGET) == 0) {
++ *chainname = t->data;
++ return 1;
++ }
++ } else
++ found = s;
++
++ return 0;
++}
++
+ /* All zeroes == unconditional rule. */
+ static inline int
+ unconditional(const struct ip6t_ip6 *ipv6)
+@@ -575,6 +614,8 @@
+ mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
+ {
+ unsigned int hook;
++ char *chainname = NULL;
++ u_int32_t rulenum;
+
+ /* No recursion; use packet counter to save back ptrs (reset
+ to 0 as we leave), and comefrom to save source hook bitmask */
+@@ -588,6 +629,8 @@
+
+ /* Set initial back pointer. */
+ e->counters.pcnt = pos;
++ rulenum = 1;
++ chainname = (char *) hook6names[hook];
+
+ for (;;) {
+ struct ip6t_standard_target *t
+@@ -600,6 +643,8 @@
+ }
+ e->comefrom
+ |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
++ e->rulenum = rulenum++;
++ e->chainname = chainname;
+
+ /* Unconditional return/END. */
+ if (e->target_offset == sizeof(struct ip6t_entry)
+@@ -609,6 +654,10 @@
+ && unconditional(&e->ipv6)) {
+ unsigned int oldpos, size;
+
++ /* Set unconditional rulenum to zero. */
++ e->rulenum = 0;
++ e->counters.bcnt = 0;
++
+ /* Return: backtrack through the last
+ big jump. */
+ do {
+@@ -634,6 +683,11 @@
+ (newinfo->entries + pos);
+ } while (oldpos == pos + e->next_offset);
+
++ /* Restore chainname, rulenum. */
++ chainname = e->chainname;
++ rulenum = e->counters.bcnt;
++ e->counters.bcnt = 0;
++
+ /* Move along one */
+ size = e->next_offset;
+ e = (struct ip6t_entry *)
+@@ -649,6 +703,17 @@
+ /* This a jump; chase it. */
+ duprintf("Jump rule %u -> %u\n",
+ pos, newpos);
++ e->counters.bcnt = rulenum++;
++ rulenum = 1;
++ e = (struct ip6t_entry *)
++ (newinfo->entries + newpos);
++ if (IP6T_ENTRY_ITERATE(newinfo->entries,
++ newinfo->size,
++ find_error_target,
++ e, &chainname) == 0) {
++ printk("ip6_tables: table screwed up!\n");
++ return 0;
++ }
+ } else {
+ /* ... this is a fallthru */
+ newpos = pos + e->next_offset;
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.0-test7/net/ipv6/netfilter/ip6t_LOG.c
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/ip6t_LOG.c 2003-10-08 21:24:03.000000000 +0200
++++ linux-2.6.0-test7/net/ipv6/netfilter/ip6t_LOG.c 2003-10-10 11:52:57.000000000 +0200
+@@ -3,18 +3,24 @@
+ */
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
++#include <linux/socket.h>
+ #include <linux/ip.h>
+ #include <linux/spinlock.h>
+ #include <linux/icmpv6.h>
+ #include <net/udp.h>
+ #include <net/tcp.h>
+ #include <net/ipv6.h>
++#include <linux/netfilter.h>
+ #include <linux/netfilter_ipv6/ip6_tables.h>
+
+ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
+ MODULE_DESCRIPTION("IP6 tables LOG target module");
+ MODULE_LICENSE("GPL");
+
++static unsigned int nflog = 1;
++MODULE_PARM(nflog, "i");
++MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
++
+ struct in_device;
+ #include <net/route.h>
+ #include <linux/netfilter_ipv6/ip6t_LOG.h>
+@@ -256,40 +262,38 @@
+ }
+ }
+
+-static unsigned int
+-ip6t_log_target(struct sk_buff **pskb,
+- unsigned int hooknum,
+- const struct net_device *in,
+- const struct net_device *out,
+- const void *targinfo,
+- void *userinfo)
++static void
++ip6t_log_packet(unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const struct ip6t_log_info *loginfo,
++ const char *level_string,
++ const char *prefix)
+ {
+- struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
+- const struct ip6t_log_info *loginfo = targinfo;
+- char level_string[4] = "< >";
++ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+
+- level_string[1] = '0' + (loginfo->level % 8);
+ spin_lock_bh(&log_lock);
+ printk(level_string);
+ printk("%sIN=%s OUT=%s ",
+- loginfo->prefix,
++ prefix == NULL ? loginfo->prefix : prefix,
+ in ? in->name : "",
+ out ? out->name : "");
+ if (in && !out) {
+ /* MAC logging for input chain only. */
+ printk("MAC=");
+- if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
+- if ((*pskb)->dev->type != ARPHRD_SIT){
++ if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
++ if (skb->dev->type != ARPHRD_SIT){
+ int i;
+- unsigned char *p = (*pskb)->mac.raw;
+- for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
++ unsigned char *p = skb->mac.raw;
++ for (i = 0; i < skb->dev->hard_header_len; i++,p++)
+ printk("%02x%c", *p,
+- i==(*pskb)->dev->hard_header_len - 1
++ i==skb->dev->hard_header_len - 1
+ ? ' ':':');
+ } else {
+ int i;
+- unsigned char *p = (*pskb)->mac.raw;
+- if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
++ unsigned char *p = skb->mac.raw;
++ if ( p - (ETH_ALEN*2+2) > skb->head ){
+ p -= (ETH_ALEN+2);
+ for (i = 0; i < (ETH_ALEN); i++,p++)
+ printk("%02x%s", *p,
+@@ -300,10 +304,10 @@
+ i == ETH_ALEN-1 ? ' ' : ':');
+ }
+
+- if (((*pskb)->dev->addr_len == 4) &&
+- (*pskb)->dev->hard_header_len > 20){
++ if ((skb->dev->addr_len == 4) &&
++ skb->dev->hard_header_len > 20){
+ printk("TUNNEL=");
+- p = (*pskb)->mac.raw + 12;
++ p = skb->mac.raw + 12;
+ for (i = 0; i < 4; i++,p++)
+ printk("%3d%s", *p,
+ i == 3 ? "->" : ".");
+@@ -319,10 +323,41 @@
+ dump_packet(loginfo, ipv6h, 1);
+ printk("\n");
+ spin_unlock_bh(&log_lock);
++}
++
++static unsigned int
++ip6t_log_target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ const struct ip6t_log_info *loginfo = targinfo;
++ char level_string[4] = "< >";
++
++ level_string[1] = '0' + (loginfo->level % 8);
++ ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
+
+ return IP6T_CONTINUE;
+ }
+
++static void
++ip6t_logfn(unsigned int hooknum,
++ const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const char *prefix)
++{
++ struct ip6t_log_info loginfo = {
++ .level = 0,
++ .logflags = IP6T_LOG_MASK,
++ .prefix = ""
++ };
++
++ ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
++}
++
+ static int ip6t_log_checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+@@ -359,12 +394,17 @@
+ {
+ if (ip6t_register_target(&ip6t_log_reg))
+ return -EINVAL;
++ if (nflog)
++ nf_log_register(PF_INET6, &ip6t_logfn);
+
+ return 0;
+ }
+
+ static void __exit fini(void)
+ {
++ if (nflog)
++ nf_log_register(PF_INET6, &ip6t_logfn);
++
+ ip6t_unregister_target(&ip6t_log_reg);
+ }
+
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.0-test7/net/ipv6/netfilter/ip6t_TRACE.c
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/net/ipv6/netfilter/ip6t_TRACE.c 2003-10-10 11:53:18.000000000 +0200
+@@ -0,0 +1,69 @@
++/* This is a module which is used for setting
++ * the NFC_TRACE flag in the nfcache field of an skb.
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++
++#include <linux/netfilter_ipv6/ip6_tables.h>
++
++static unsigned int
++target(struct sk_buff **pskb,
++ unsigned int hooknum,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *targinfo,
++ void *userinfo)
++{
++ (*pskb)->nfcache |= NFC_TRACE;
++ return IP6T_CONTINUE;
++}
++
++static int
++checkentry(const char *tablename,
++ const struct ip6t_entry *e,
++ void *targinfo,
++ unsigned int targinfosize,
++ unsigned int hook_mask)
++{
++ if (targinfosize != 0) {
++ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
++ targinfosize);
++ return 0;
++ }
++
++ if (strcmp(tablename, "raw") != 0) {
++ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
++ return 0;
++ }
++
++ return 1;
++}
++
++static struct ip6t_target ip6t_trace_reg = {
++ .name = "TRACE",
++ .target = target,
++ .checkentry = checkentry,
++ .destroy = NULL,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ if (ip6t_register_target(&ip6t_trace_reg))
++ return -EINVAL;
++
++ return 0;
++}
++
++static void __exit fini(void)
++{
++ ip6t_unregister_target(&ip6t_trace_reg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
++MODULE_DESCRIPTION("IPv6 TRACE target");
++
+\ No newline at end of file
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.0-test7/net/ipv6/netfilter/ip6table_filter.c
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/ip6table_filter.c 2003-10-08 21:24:01.000000000 +0200
++++ linux-2.6.0-test7/net/ipv6/netfilter/ip6table_filter.c 2003-10-10 11:53:18.000000000 +0200
+@@ -52,7 +52,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* FORWARD */
+@@ -60,7 +60,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_OUT */
+@@ -68,7 +68,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } }
+ },
+@@ -77,7 +77,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_error),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
+ { } },
+ "ERROR"
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.0-test7/net/ipv6/netfilter/ip6table_mangle.c
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/ip6table_mangle.c 2003-10-08 21:24:04.000000000 +0200
++++ linux-2.6.0-test7/net/ipv6/netfilter/ip6table_mangle.c 2003-10-10 11:53:18.000000000 +0200
+@@ -66,7 +66,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_IN */
+@@ -74,7 +74,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* FORWARD */
+@@ -82,7 +82,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* LOCAL_OUT */
+@@ -90,7 +90,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } },
+ /* POST_ROUTING */
+@@ -98,7 +98,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_standard),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+ -NF_ACCEPT - 1 } }
+ },
+@@ -107,7 +107,7 @@
+ 0,
+ sizeof(struct ip6t_entry),
+ sizeof(struct ip6t_error),
+- 0, { 0, 0 }, { } },
++ 0, NULL, 0, { 0, 0 }, { } },
+ { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
+ { } },
+ "ERROR"
+diff -Nur linux-2.6.0-test7.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.0-test7/net/ipv6/netfilter/ip6table_raw.c
+--- linux-2.6.0-test7.org/net/ipv6/netfilter/ip6table_raw.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/net/ipv6/netfilter/ip6table_raw.c 2003-10-10 11:53:18.000000000 +0200
+@@ -0,0 +1,158 @@
++/*
++ * IPv6 raw table, a port of the IPv4 raw table to IPv6
++ *
++ * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
++ */
++#include <linux/module.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++
++#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
++
++#if 0
++#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
++#else
++#define DEBUGP(x, args...)
++#endif
++
++/* Standard entry. */
++struct ip6t_standard
++{
++ struct ip6t_entry entry;
++ struct ip6t_standard_target target;
++};
++
++struct ip6t_error_target
++{
++ struct ip6t_entry_target target;
++ char errorname[IP6T_FUNCTION_MAXNAMELEN];
++};
++
++struct ip6t_error
++{
++ struct ip6t_entry entry;
++ struct ip6t_error_target target;
++};
++
++static struct
++{
++ struct ip6t_replace repl;
++ struct ip6t_standard entries[2];
++ struct ip6t_error term;
++} initial_table __initdata
++= { { "raw", RAW_VALID_HOOKS, 3,
++ sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
++ { [NF_IP6_PRE_ROUTING] 0,
++ [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
++ { [NF_IP6_PRE_ROUTING] 0,
++ [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
++ 0, NULL, { } },
++ {
++ /* PRE_ROUTING */
++ { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
++ 0,
++ sizeof(struct ip6t_entry),
++ sizeof(struct ip6t_standard),
++ 0, NULL, 0, { 0, 0 }, { } },
++ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
++ -NF_ACCEPT - 1 } },
++ /* LOCAL_OUT */
++ { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
++ 0,
++ sizeof(struct ip6t_entry),
++ sizeof(struct ip6t_standard),
++ 0, NULL, 0, { 0, 0 }, { } },
++ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
++ -NF_ACCEPT - 1 } },
++ },
++ /* ERROR */
++ { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
++ 0,
++ sizeof(struct ip6t_entry),
++ sizeof(struct ip6t_error),
++ 0, NULL, 0, { 0, 0 }, { } },
++ { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
++ { } },
++ "ERROR"
++ }
++ }
++};
++
++static struct ip6t_table packet_raw = {
++ .name = "raw",
++ .table = &initial_table.repl,
++ .valid_hooks = RAW_VALID_HOOKS,
++ .lock = RW_LOCK_UNLOCKED,
++ .me = THIS_MODULE
++};
++
++/* The work comes in here from netfilter.c. */
++static unsigned int
++ip6t_hook(unsigned int hook,
++ struct sk_buff **pskb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
++}
++
++static struct nf_hook_ops ip6t_ops[] = {
++ { /* PRE_ROUTING */
++ .hook = ip6t_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET6,
++ .hooknum = NF_IP6_PRE_ROUTING,
++ .priority = NF_IP6_PRI_FIRST,
++ },
++ { /* LOCAL_OUT */
++ .hook = ip6t_hook,
++ .owner = THIS_MODULE,
++ .pf = PF_INET6,
++ .hooknum = NF_IP6_LOCAL_OUT,
++ .priority = NF_IP6_PRI_FIRST,
++ },
++};
++
++static int __init init(void)
++{
++ int ret;
++
++ /* Register table */
++ ret = ip6t_register_table(&packet_raw);
++ if (ret < 0)
++ return ret;
++
++ /* Register hooks */
++ ret = nf_register_hook(&ip6t_ops[0]);
++ if (ret < 0)
++ goto cleanup_table;
++
++ ret = nf_register_hook(&ip6t_ops[1]);
++ if (ret < 0)
++ goto cleanup_hook0;
++
++ return ret;
++
++ cleanup_hook0:
++ nf_unregister_hook(&ip6t_ops[0]);
++ cleanup_table:
++ ip6t_unregister_table(&packet_raw);
++
++ return ret;
++}
++
++static void __exit fini(void)
++{
++ unsigned int i;
++
++ for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
++ nf_unregister_hook(&ip6t_ops[i]);
++
++ ip6t_unregister_table(&packet_raw);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
++MODULE_DESCRIPTION("IPv6 raw table");
+diff -Nur linux-2.6.0-test7.org/netfilter-patch-o-matic/patches linux-2.6.0-test7/netfilter-patch-o-matic/patches
+--- linux-2.6.0-test7.org/netfilter-patch-o-matic/patches 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.0-test7/netfilter-patch-o-matic/patches 2003-10-10 11:54:22.000000000 +0200
+@@ -0,0 +1,23 @@
++./base/01_sctp_match.patch
++./pending/23_REJECT-headroom-tcprst.patch
++./pending/24_rcu.patch
++./pending/25-err-ptr.patch
++./pending/26-memsets.patch
++./pending/40_nf-log.patch
++./pending/70_expect-evict-order.patch
++./pending/71_raw.patch
++./submitted/02_REJECT-headroom-tcprst.patch
++./submitted/03_260t4-mirror-remove.patch
++./submitted/03_physdev_bridged.patch
++./submitted/04_260t4-unclean-remove.patch
++./submitted/04_config-fix.patch
++./submitted/75_nathelper-udp-csum.patch
++./submitted/76_mangle_udp-sizecheck.patch
++./submitted/77_destroy-conntrack.patch
++./submitted/78_reject-localout.patch
++./submitted/80_ip_conntrack-proc.patch
++./submitted/82_irc-conntrack-mirc-serverlookup.patch
++./submitted/83_nolocalout.patch
++./submitted/84_local-nullbinding.patch
++./submitted/85_ipv6header.patch
++./submitted/86_getorigdst-tuple-zero.patch