From: Jo-Philipp Wich Date: Fri, 19 Feb 2010 01:36:47 +0000 (+0000) Subject: netfilter: add support for raw table and NOTRACK target (#5504) X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=15c4e22d31c1d46a5fd19823499b812c2629dbaa;p=openwrt%2Fstaging%2Fmkresin.git netfilter: add support for raw table and NOTRACK target (#5504) SVN-Revision: 19721 --- diff --git a/include/netfilter.mk b/include/netfilter.mk index 9eeee4f6e1..c8347936d4 100644 --- a/include/netfilter.mk +++ b/include/netfilter.mk @@ -91,6 +91,7 @@ $(eval $(if $(NF_KMOD),$(call nf_add,IPT_CONNTRACK,CONFIG_NF_CONNTRACK_IPV4, $(P $(eval $(call nf_add,IPT_CONNTRACK,CONFIG_IP_NF_MATCH_STATE, $(P_V4)ipt_state)) $(eval $(call nf_add,IPT_CONNTRACK,CONFIG_NETFILTER_XT_MATCH_STATE, $(P_XT)xt_state)) $(eval $(call nf_add,IPT_CONNTRACK,CONFIG_IP_NF_RAW, $(P_V4)iptable_raw)) +$(eval $(call nf_add,IPT_CONNTRACK,CONFIG_IP_NF_TARGET_NOTRACK, $(P_V4)ipt_NOTRACK)) $(eval $(call nf_add,IPT_CONNTRACK,CONFIG_NETFILTER_XT_TARGET_NOTRACK, $(P_XT)xt_NOTRACK)) diff --git a/target/linux/generic-2.4/config-default b/target/linux/generic-2.4/config-default index 869e4f4cc4..5dce4279cd 100644 --- a/target/linux/generic-2.4/config-default +++ b/target/linux/generic-2.4/config-default @@ -203,6 +203,7 @@ CONFIG_IP6_NF_MATCH_OWNER=m CONFIG_IP6_NF_MATCH_RANDOM=m # CONFIG_IP6_NF_MATCH_RT is not set # CONFIG_IP6_NF_QUEUE is not set +CONFIG_IP6_NF_RAW=m CONFIG_IP6_NF_TARGET_IMQ=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_MARK=m @@ -277,6 +278,7 @@ CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_TFTP=m CONFIG_IP_NF_PPTP=m CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_RAW=m CONFIG_IP_NF_RTSP=m CONFIG_IP_NF_SET_HASHSIZE=1024 CONFIG_IP_NF_SET_IPHASH=m @@ -297,6 +299,7 @@ CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_MIRROR=m CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_SET=m diff --git a/target/linux/generic-2.4/patches/628-netfilter_raw.patch b/target/linux/generic-2.4/patches/628-netfilter_raw.patch new file mode 100644 index 0000000000..419fb01e58 --- /dev/null +++ b/target/linux/generic-2.4/patches/628-netfilter_raw.patch @@ -0,0 +1,707 @@ +--- a/Documentation/Configure.help ++++ b/Documentation/Configure.help +@@ -3057,6 +3057,34 @@ + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + ++raw table support (required for NOTRACK/TRACE) ++CONFIG_IP_NF_RAW ++ This option adds a `raw' table to iptables. This table is the very ++ first in the netfilter framework and hooks in at the PREROUTING ++ and OUTPUT chains. ++ ++ If you want to compile it as a module, say M here and read ++ . If unsure, say `N'. ++ ++NOTRACK target support ++CONFIG_IP_NF_TARGET_NOTRACK ++ The NOTRACK target allows a select rule to specify ++ which packets *not* to enter the conntrack/NAT ++ subsystem with all the consequences (no ICMP error tracking, ++ no protocol helpers for the selected packets). ++ ++ If you want to compile it as a module, say M here and read ++ . If unsure, say `N'. ++ ++raw table support (required for TRACE) ++CONFIG_IP6_NF_RAW ++ This option adds a `raw' table to ip6tables. This table is the very ++ first in the netfilter framework and hooks in at the PREROUTING ++ and OUTPUT chains. ++ ++ If you want to compile it as a module, say M here and read ++ . If unsure, say `N'. ++ + REJECT target support + CONFIG_IP_NF_TARGET_REJECT + The REJECT target allows a filtering rule to specify that an ICMP +--- a/include/linux/netfilter_ipv4/ip_conntrack.h ++++ b/include/linux/netfilter_ipv4/ip_conntrack.h +@@ -286,6 +286,9 @@ + /* Call me when a conntrack is destroyed. */ + extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); + ++/* Fake conntrack entry for untracked connections */ ++extern struct ip_conntrack ip_conntrack_untracked; ++ + /* Returns new sk_buff, or NULL */ + struct sk_buff * + ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user); +--- a/include/linux/netfilter_ipv4/ipt_conntrack.h ++++ b/include/linux/netfilter_ipv4/ipt_conntrack.h +@@ -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 +--- a/include/linux/netfilter_ipv4/ipt_state.h ++++ b/include/linux/netfilter_ipv4/ipt_state.h +@@ -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; +--- a/include/linux/netfilter_ipv4.h ++++ b/include/linux/netfilter_ipv4.h +@@ -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_MANGLE = -150, + NF_IP_PRI_NAT_DST = -100, +--- a/net/ipv4/netfilter/Config.in ++++ b/net/ipv4/netfilter/Config.in +@@ -153,6 +153,15 @@ + dep_tristate ' TTL target support' CONFIG_IP_NF_TARGET_TTL $CONFIG_IP_NF_IPTABLES + dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES + dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES ++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then ++ tristate ' raw table support (required for NOTRACK/TRACE)' CONFIG_IP_NF_RAW $CONFIG_IP_NF_IPTABLES ++ fi ++ if [ "$CONFIG_IP_NF_RAW" != "n" ]; then ++ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then ++ dep_tristate ' NOTRACK target support' CONFIG_IP_NF_TARGET_NOTRACK $CONFIG_IP_NF_RAW ++ fi ++ # Marker for TRACE target ++ fi + fi + + tristate 'ARP tables support' CONFIG_IP_NF_ARPTABLES +--- a/net/ipv4/netfilter/ip_conntrack_core.c ++++ b/net/ipv4/netfilter/ip_conntrack_core.c +@@ -64,6 +64,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; + static LIST_HEAD(unconfirmed); + + extern struct ip_conntrack_protocol ip_conntrack_generic_protocol; +@@ -834,6 +835,15 @@ + int set_reply; + int ret; + ++ /* Never happen */ ++ if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) { ++ if (net_ratelimit()) { ++ printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n", ++ (*pskb)->nh.iph->protocol, hooknum); ++ } ++ return NF_DROP; ++ } ++ + /* FIXME: Do this right please. --RR */ + (*pskb)->nfcache |= NFC_UNKNOWN; + +@@ -1489,6 +1499,18 @@ + + /* 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 REJECT/NAT. */ ++ ip_conntrack_untracked.infos[IP_CT_NEW].master = ++ ip_conntrack_untracked.infos[IP_CT_RELATED].master = ++ ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master = ++ &ip_conntrack_untracked.ct_general; ++ + return ret; + + err_free_hash: +--- a/net/ipv4/netfilter/ip_conntrack_standalone.c ++++ b/net/ipv4/netfilter/ip_conntrack_standalone.c +@@ -218,6 +218,29 @@ + 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, ++ hooknum == NF_IP_PRE_ROUTING ? ++ IP_DEFRAG_CONNTRACK_IN : ++ IP_DEFRAG_CONNTRACK_OUT); ++ 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, +@@ -259,9 +282,15 @@ + + /* Connection tracking may drop packets, but never alters them, so + make it the first hook. */ ++static struct nf_hook_ops ip_conntrack_defrag_ops ++= { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_PRE_ROUTING, ++ NF_IP_PRI_CONNTRACK_DEFRAG }; + static struct nf_hook_ops ip_conntrack_in_ops + = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING, + NF_IP_PRI_CONNTRACK }; ++static struct nf_hook_ops ip_conntrack_defrag_local_out_ops ++= { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_LOCAL_OUT, ++ NF_IP_PRI_CONNTRACK_DEFRAG }; + static struct nf_hook_ops ip_conntrack_local_out_ops + = { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT, + NF_IP_PRI_CONNTRACK }; +@@ -382,10 +411,20 @@ + 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 defrag hook.\n"); ++ goto cleanup_proc; ++ } ++ ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops); ++ if (ret < 0) { ++ printk("ip_conntrack: can't register local_out defrag hook.\n"); ++ goto cleanup_defragops; ++ } + 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_defraglocalops; + } + ret = nf_register_hook(&ip_conntrack_local_out_ops); + if (ret < 0) { +@@ -423,6 +462,10 @@ + nf_unregister_hook(&ip_conntrack_local_out_ops); + cleanup_inops: + nf_unregister_hook(&ip_conntrack_in_ops); ++ cleanup_defraglocalops: ++ nf_unregister_hook(&ip_conntrack_defrag_local_out_ops); ++ cleanup_defragops: ++ nf_unregister_hook(&ip_conntrack_defrag_ops); + cleanup_proc: + proc_net_remove("ip_conntrack"); + cleanup_init: +@@ -512,5 +555,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); +--- a/net/ipv4/netfilter/ip_nat_core.c ++++ b/net/ipv4/netfilter/ip_nat_core.c +@@ -1023,6 +1023,10 @@ + /* FIXME: Man, this is a hack. */ + 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; + } +--- /dev/null ++++ b/net/ipv4/netfilter/iptable_raw.c +@@ -0,0 +1,149 @@ ++/* ++ * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT . ++ * ++ * Copyright (C) 2003 Jozsef Kadlecsik ++ */ ++#include ++#include ++ ++#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, { 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, { 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, { 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[] = { ++ { ++ .hook = ipt_hook, ++ .pf = PF_INET, ++ .hooknum = NF_IP_PRE_ROUTING, ++ .priority = NF_IP_PRI_RAW ++ }, ++ { ++ .hook = ipt_hook, ++ .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"); +--- a/net/ipv4/netfilter/ipt_conntrack.c ++++ b/net/ipv4/netfilter/ipt_conntrack.c +@@ -27,11 +27,13 @@ + + #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) + +- if (ct) +- statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); +- else +- statebit = IPT_CONNTRACK_STATE_INVALID; +- ++ 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; ++ + if(sinfo->flags & IPT_CONNTRACK_STATE) { + if (ct) { + if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != +--- /dev/null ++++ b/net/ipv4/netfilter/ipt_NOTRACK.c +@@ -0,0 +1,75 @@ ++/* 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 ++#include ++ ++#include ++#include ++ ++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) ++{ ++ /* 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, ++ .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"); +--- a/net/ipv4/netfilter/ipt_state.c ++++ b/net/ipv4/netfilter/ipt_state.c +@@ -21,7 +21,9 @@ + enum ip_conntrack_info ctinfo; + unsigned int statebit; + +- if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo)) ++ 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_INVALID; + else + statebit = IPT_STATE_BIT(ctinfo); +--- a/net/ipv4/netfilter/Makefile ++++ b/net/ipv4/netfilter/Makefile +@@ -77,6 +77,7 @@ + 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_HELPER) += ipt_helper.o +@@ -131,6 +132,7 @@ + obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.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 + + # generic ARP tables + obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o +--- a/net/ipv6/netfilter/Config.in ++++ b/net/ipv6/netfilter/Config.in +@@ -79,6 +79,10 @@ + dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE + fi + #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES ++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then ++ tristate ' raw table support (required for TRACE)' CONFIG_IP6_NF_RAW $CONFIG_IP6_NF_IPTABLES ++ fi ++ # Marker for TRACE target + fi + + endmenu +--- /dev/null ++++ b/net/ipv6/netfilter/ip6table_raw.c +@@ -0,0 +1,154 @@ ++/* ++ * IPv6 raw table, a port of the IPv4 raw table to IPv6 ++ * ++ * Copyright (C) 2003 Jozsef Kadlecsik ++ */ ++#include ++#include ++ ++#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, { 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, { 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, { 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[] = { ++ { ++ .hook = ip6t_hook, ++ .pf = PF_INET6, ++ .hooknum = NF_IP6_PRE_ROUTING, ++ .priority = NF_IP6_PRI_FIRST ++ }, ++ { ++ .hook = ip6t_hook, ++ .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"); +--- a/net/ipv6/netfilter/Makefile ++++ b/net/ipv6/netfilter/Makefile +@@ -32,6 +32,7 @@ + obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o + obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o + obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o ++obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o + obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o + obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o + obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o