diff options
Diffstat (limited to 'net')
33 files changed, 8289 insertions, 62 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 95501e40100..b7d13a4fff4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -336,6 +336,9 @@ void __kfree_skb(struct sk_buff *skb) } #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + nf_conntrack_put_reasm(skb->nfct_reasm); +#endif #ifdef CONFIG_BRIDGE_NETFILTER nf_bridge_put(skb->nf_bridge); #endif @@ -414,9 +417,17 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) C(nfct); nf_conntrack_get(skb->nfct); C(nfctinfo); +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + C(nfct_reasm); + nf_conntrack_get_reasm(skb->nfct_reasm); +#endif #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) C(ipvs_property); #endif +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + C(nfct_reasm); + nf_conntrack_get_reasm(skb->nfct_reasm); +#endif #ifdef CONFIG_BRIDGE_NETFILTER C(nf_bridge); nf_bridge_get(skb->nf_bridge); @@ -474,6 +485,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->nfct = old->nfct; nf_conntrack_get(old->nfct); new->nfctinfo = old->nfctinfo; +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) + new->nfct_reasm = old->nfct_reasm; + nf_conntrack_get_reasm(old->nfct_reasm); +#endif #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) new->ipvs_property = old->ipvs_property; #endif diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 7d917e4ce1d..9d3c8b5f327 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -5,6 +5,20 @@ menu "IP: Netfilter Configuration" depends on INET && NETFILTER +config NF_CONNTRACK_IPV4 + tristate "IPv4 support for new connection tracking (EXPERIMENTAL)" + depends on EXPERIMENTAL && NF_CONNTRACK + ---help--- + Connection tracking keeps a record of what packets have passed + through your machine, in order to figure out how they are related + into connections. + + This is IPv4 support on Layer 3 independent connection tracking. + Layer 3 independent connection tracking is experimental scheme + which generalize ip_conntrack to support other layer 3 protocols. + + To compile it as a module, choose M here. If unsure, say N. + # connection tracking, helpers and protocols config IP_NF_CONNTRACK tristate "Connection tracking (required for masq/NAT)" @@ -209,8 +223,8 @@ config IP_NF_MATCH_PKTTYPE tristate "Packet type match support" depends on IP_NF_IPTABLES help - Packet type matching allows you to match a packet by - its "class", eg. BROADCAST, MULTICAST, ... + Packet type matching allows you to match a packet by + its "class", eg. BROADCAST, MULTICAST, ... Typical usage: iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG @@ -317,7 +331,8 @@ config IP_NF_MATCH_TCPMSS config IP_NF_MATCH_HELPER tristate "Helper match support" - depends on IP_NF_CONNTRACK && IP_NF_IPTABLES + depends on IP_NF_IPTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 help Helper matching allows you to match packets in dynamic connections tracked by a conntrack-helper, ie. ip_conntrack_ftp @@ -326,7 +341,8 @@ config IP_NF_MATCH_HELPER config IP_NF_MATCH_STATE tristate "Connection state match support" - depends on IP_NF_CONNTRACK && IP_NF_IPTABLES + depends on IP_NF_IPTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 help Connection state matching allows you to match packets based on their relationship to a tracked connection (ie. previous packets). This @@ -336,7 +352,8 @@ config IP_NF_MATCH_STATE config IP_NF_MATCH_CONNTRACK tristate "Connection tracking match support" - depends on IP_NF_CONNTRACK && IP_NF_IPTABLES + depends on IP_NF_IPTABLES + depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 help This is a general conntrack match module, a superset of the state match. @@ -422,7 +439,8 @@ config IP_NF_MATCH_COMMENT config IP_NF_MATCH_CONNMARK tristate 'Connection mark match support' - depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES + depends on IP_NF_IPTABLES + depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) help This option adds a `connmark' match, which allows you to match the connection mark value previously set for the session by `CONNMARK'. @@ -433,7 +451,8 @@ config IP_NF_MATCH_CONNMARK config IP_NF_MATCH_CONNBYTES tristate 'Connection byte/packet counter match support' - depends on IP_NF_CT_ACCT && IP_NF_IPTABLES + depends on IP_NF_IPTABLES + depends on IP_NF_CT_ACCT || (NF_CT_ACCT && NF_CONNTRACK_IPV4) help This option adds a `connbytes' match, which allows you to match the number of bytes and/or packets for each direction within a connection. @@ -747,7 +766,8 @@ config IP_NF_TARGET_TTL config IP_NF_TARGET_CONNMARK tristate 'CONNMARK target support' - depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE + depends on IP_NF_MANGLE + depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) help This option adds a `CONNMARK' target, which allows one to manipulate the connection mark value. Similar to the MARK target, but @@ -759,7 +779,8 @@ config IP_NF_TARGET_CONNMARK config IP_NF_TARGET_CLUSTERIP tristate "CLUSTERIP target support (EXPERIMENTAL)" - depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES && EXPERIMENTAL + depends on IP_NF_IPTABLES && EXPERIMENTAL + depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) help The CLUSTERIP target allows you to build load-balancing clusters of network servers without having a dedicated load-balancing @@ -782,7 +803,7 @@ config IP_NF_RAW config IP_NF_TARGET_NOTRACK tristate 'NOTRACK target support' depends on IP_NF_RAW - depends on IP_NF_CONNTRACK + depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 help The NOTRACK target allows a select rule to specify which packets *not* to enter the conntrack/NAT diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index dab4b58dd31..058c48e258f 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -103,3 +103,9 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o + +# objects for l3 independent conntrack +nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o + +# l3 independent conntrack +obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 5c1c0a3d1c4..d2a4fec2286 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1376,7 +1376,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, ip_conntrack_expect_put(exp); } } - write_unlock(&ip_conntrack_lock); + write_unlock_bh(&ip_conntrack_lock); } else { /* This basically means we have to flush everything*/ write_lock_bh(&ip_conntrack_lock); diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 9bcb398fbc1..45c52d8f4d9 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -29,7 +29,7 @@ #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> -#include <linux/netfilter_ipv4/ip_conntrack.h> +#include <net/netfilter/nf_conntrack_compat.h> #define CLUSTERIP_VERSION "0.8" @@ -316,14 +316,14 @@ target(struct sk_buff **pskb, { const struct ipt_clusterip_tgt_info *cipinfo = targinfo; enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); - u_int32_t hash; + u_int32_t *mark, hash; /* don't need to clusterip_config_get() here, since refcount * is only decremented by destroy() - and ip_tables guarantees * that the ->target() function isn't called after ->destroy() */ - if (!ct) { + mark = nf_ct_get_mark((*pskb), &ctinfo); + if (mark == NULL) { printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); /* FIXME: need to drop invalid ones, since replies * to outgoing connections of other nodes will be @@ -346,7 +346,7 @@ target(struct sk_buff **pskb, switch (ctinfo) { case IP_CT_NEW: - ct->mark = hash; + *mark = hash; break; case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: @@ -363,7 +363,7 @@ target(struct sk_buff **pskb, #ifdef DEBUG_CLUSTERP DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); #endif - DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark); + DEBUGP("hash=%u ct_hash=%u ", hash, *mark); if (!clusterip_responsible(cipinfo->config, hash)) { DEBUGP("not responsible\n"); return NF_DROP; diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/ipv4/netfilter/ipt_CONNMARK.c index 05d66ab5942..8acac5a40a9 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/ipv4/netfilter/ipt_CONNMARK.c @@ -29,7 +29,7 @@ MODULE_LICENSE("GPL"); #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_CONNMARK.h> -#include <linux/netfilter_ipv4/ip_conntrack.h> +#include <net/netfilter/nf_conntrack_compat.h> static unsigned int target(struct sk_buff **pskb, @@ -43,24 +43,24 @@ target(struct sk_buff **pskb, u_int32_t diff; u_int32_t nfmark; u_int32_t newmark; + u_int32_t ctinfo; + u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo); - enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); - if (ct) { + if (ctmark) { switch(markinfo->mode) { case IPT_CONNMARK_SET: - newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; - if (newmark != ct->mark) - ct->mark = newmark; + newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; + if (newmark != *ctmark) + *ctmark = newmark; break; case IPT_CONNMARK_SAVE: - newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); - if (ct->mark != newmark) - ct->mark = newmark; + newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); + if (*ctmark != newmark) + *ctmark = newmark; break; case IPT_CONNMARK_RESTORE: nfmark = (*pskb)->nfmark; - diff = (ct->mark ^ nfmark) & markinfo->mask; + diff = (*ctmark ^ nfmark) & markinfo->mask; if (diff != 0) (*pskb)->nfmark = nfmark ^ diff; break; diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/ipv4/netfilter/ipt_NOTRACK.c index a4bb9b3bc29..e3c69d072c6 100644 --- a/net/ipv4/netfilter/ipt_NOTRACK.c +++ b/net/ipv4/netfilter/ipt_NOTRACK.c @@ -5,7 +5,7 @@ #include <linux/skbuff.h> #include <linux/netfilter_ipv4/ip_tables.h> -#include <linux/netfilter_ipv4/ip_conntrack.h> +#include <net/netfilter/nf_conntrack_compat.h> static unsigned int target(struct sk_buff **pskb, @@ -23,7 +23,7 @@ target(struct sk_buff **pskb, 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.ct_general; + nf_ct_untrack(*pskb); (*pskb)->nfctinfo = IP_CT_NEW; nf_conntrack_get((*pskb)->nfct); diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/ipv4/netfilter/ipt_connbytes.c index df4a42c6da2..d68a048b717 100644 --- a/net/ipv4/netfilter/ipt_connbytes.c +++ b/net/ipv4/netfilter/ipt_connbytes.c @@ -10,7 +10,7 @@ */ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ip_conntrack.h> +#include <net/netfilter/nf_conntrack_compat.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_connbytes.h> @@ -46,60 +46,59 @@ match(const struct sk_buff *skb, int *hotdrop) { const struct ipt_connbytes_info *sinfo = matchinfo; - enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct; u_int64_t what = 0; /* initialize to make gcc happy */ + const struct ip_conntrack_counter *counters; - if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo))) + if (!(counters = nf_ct_get_counters(skb))) return 0; /* no match */ switch (sinfo->what) { case IPT_CONNBYTES_PKTS: switch (sinfo->direction) { case IPT_CONNBYTES_DIR_ORIGINAL: - what = ct->counters[IP_CT_DIR_ORIGINAL].packets; + what = counters[IP_CT_DIR_ORIGINAL].packets; break; case IPT_CONNBYTES_DIR_REPLY: - what = ct->counters[IP_CT_DIR_REPLY].packets; + what = counters[IP_CT_DIR_REPLY].packets; break; case IPT_CONNBYTES_DIR_BOTH: - what = ct->counters[IP_CT_DIR_ORIGINAL].packets; - what += ct->counters[IP_CT_DIR_REPLY].packets; + what = counters[IP_CT_DIR_ORIGINAL].packets; + what += counters[IP_CT_DIR_REPLY].packets; break; } break; case IPT_CONNBYTES_BYTES: switch (sinfo->direction) { case IPT_CONNBYTES_DIR_ORIGINAL: - what = ct->counters[IP_CT_DIR_ORIGINAL].bytes; + what = counters[IP_CT_DIR_ORIGINAL].bytes; break; case IPT_CONNBYTES_DIR_REPLY: - what = ct->counters[IP_CT_DIR_REPLY].bytes; + what = counters[IP_CT_DIR_REPLY].bytes; break; case IPT_CONNBYTES_DIR_BOTH: - what = ct->counters[IP_CT_DIR_ORIGINAL].bytes; - what += ct->counters[IP_CT_DIR_REPLY].bytes; + what = counters[IP_CT_DIR_ORIGINAL].bytes; + what += counters[IP_CT_DIR_REPLY].bytes; break; } break; case IPT_CONNBYTES_AVGPKT: switch (sinfo->direction) { case IPT_CONNBYTES_DIR_ORIGINAL: - what = div64_64(ct->counters[IP_CT_DIR_ORIGINAL].bytes, - ct->counters[IP_CT_DIR_ORIGINAL].packets); + what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, + counters[IP_CT_DIR_ORIGINAL].packets); break; case IPT_CONNBYTES_DIR_REPLY: - what = div64_64(ct->counters[IP_CT_DIR_REPLY].bytes, - ct->counters[IP_CT_DIR_REPLY].packets); + what = div64_64(counters[IP_CT_DIR_REPLY].bytes, + counters[IP_CT_DIR_REPLY].packets); break; case IPT_CONNBYTES_DIR_BOTH: { u_int64_t bytes; u_int64_t pkts; - bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes + - ct->counters[IP_CT_DIR_REPLY].bytes; - pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets+ - ct->counters[IP_CT_DIR_REPLY].packets; + bytes = counters[IP_CT_DIR_ORIGINAL].bytes + + counters[IP_CT_DIR_REPLY].bytes; + pkts = counters[IP_CT_DIR_ORIGINAL].packets+ + counters[IP_CT_DIR_REPLY].packets; /* FIXME_THEORETICAL: what to do if sum * overflows ? */ diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/ipv4/netfilter/ipt_connmark.c index bf8de47ce00..5306ef293b9 100644 --- a/net/ipv4/netfilter/ipt_connmark.c +++ b/net/ipv4/netfilter/ipt_connmark.c @@ -28,7 +28,7 @@ MODULE_LICENSE("GPL"); #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_connmark.h> -#include <linux/netfilter_ipv4/ip_conntrack.h> +#include <net/netfilter/nf_conntrack_compat.h> static int match(const struct sk_buff *skb, @@ -39,12 +39,12 @@ match(const struct sk_buff *skb, int *hotdrop) { const struct ipt_connmark_info *info = matchinfo; - enum ip_conntrack_info ctinfo; - struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); - if (!ct) + u_int32_t ctinfo; + const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); + if (!ctmark) return 0; - return ((ct->mark & info->mask) == info->mark) ^ info->invert; + return (((*ctmark) & info->mask) == info->mark) ^ info->invert; } static int diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/ipv4/netfilter/ipt_conntrack.c index c1d22801b7c..c8d18705469 100644 --- a/net/ipv4/netfilter/ipt_conntrack.c +++ b/net/ipv4/netfilter/ipt_conntrack.c @@ -10,7 +10,14 @@ #include <linux/module.h> #include <linux/skbuff.h> + +#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) #include <linux/netfilter_ipv4/ip_conntrack.h> +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h> +#else +#include <net/netfilter/nf_conntrack.h> +#endif + #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_conntrack.h> @@ -18,6 +25,8 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); MODULE_DESCRIPTION("iptables connection tracking match module"); +#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) + static int match(const struct sk_buff *skb, const struct net_device *in, @@ -102,6 +111,93 @@ match(const struct sk_buff *skb, return 1; } +#else /* CONFIG_IP_NF_CONNTRACK */ +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_conntrack_info *sinfo = matchinfo; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + unsigned int statebit; + + ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); + +#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) + + if (ct == &nf_conntrack_untracked) + 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.u3.ip != + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) + statebit |= IPT_CONNTRACK_STATE_SNAT; + + if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != + ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) + statebit |= IPT_CONNTRACK_STATE_DNAT; + } + + if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_REPLDST) { + if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) + return 0; + } + + if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { + unsigned long expires; + + if(!ct) + return 0; + + expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; + + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) + return 0; + } + + return 1; +} + +#endif /* CONFIG_NF_IP_CONNTRACK */ + static int check(const char *tablename, const struct ipt_ip *ip, void *matchinfo, diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c index 3e7dd014de4..bf14e1c7798 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/ipv4/netfilter/ipt_helper.c @@ -13,9 +13,15 @@ #include <linux/module.h> #include <linux/skbuff.h> #include <linux/netfilter.h> +#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h> +#else +#include <net/netfilter/nf_conntrack.h> +#include <net/netfilter/nf_conntrack_core.h> +#include <net/netfilter/nf_conntrack_helper.h> +#endif #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_helper.h> @@ -29,6 +35,7 @@ MODULE_DESCRIPTION("iptables helper match module"); #define DEBUGP(format, args...) #endif +#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) static int match(const struct sk_buff *skb, const struct net_device *in, @@ -73,6 +80,53 @@ out_unlock: return ret; } +#else /* CONFIG_IP_NF_CONNTRACK */ + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + int *hotdrop) +{ + const struct ipt_helper_info *info = matchinfo; + struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + int ret = info->invert; + + ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); + if (!ct) { + DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); + return ret; + } + + if (!ct->master) { + DEBUGP("ipt_helper: conntrack %p has no master\n", ct); + return ret; + } + + read_lock_bh(&nf_conntrack_lock); + if (!ct->master->helper) { + DEBUGP("ipt_helper: master ct %p has no helper\n", + exp->expectant); + goto out_unlock; + } + + DEBUGP("master's name = %s , info->name = %s\n", + ct->master->helper->name, info->name); + + if (info->name[0] == '\0') + ret ^= 1; + else + ret ^= !strncmp(ct->master->helper->name, info->name, + strlen(ct->master->helper->name)); +out_unlock: + read_unlock_bh(&nf_conntrack_lock); + return ret; +} +#endif + static int check(const char *tablename, const struct ipt_ip *ip, void *matchinfo, diff --git a/net/ipv4/netfilter/ipt_state.c b/net/ipv4/netfilter/ipt_state.c index b1511b97ea5..4d7f16b70ce 100644 --- a/net/ipv4/netfilter/ipt_state.c +++ b/net/ipv4/netfilter/ipt_state.c @@ -10,7 +10,7 @@ #include <linux/module.h> #include <linux/skbuff.h> -#include <linux/netfilter_ipv4/ip_conntrack.h> +#include <net/netfilter/nf_conntrack_compat.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_state.h> @@ -30,9 +30,9 @@ match(const struct sk_buff *skb, enum ip_conntrack_info ctinfo; unsigned int statebit; - if (skb->nfct == &ip_conntrack_untracked.ct_general) + if (nf_ct_is_untracked(skb)) statebit = IPT_STATE_UNTRACKED; - else if (!ip_conntrack_get(skb, &ctinfo)) + else if (!nf_ct_get_ctinfo(skb, &ctinfo)) statebit = IPT_STATE_INVALID; else statebit = IPT_STATE_BIT(ctinfo); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c new file mode 100644 index 00000000000..8202c1c0afa --- /dev/null +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -0,0 +1,571 @@ +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> + * - move L3 protocol dependent part to this file. + * 23 Mar 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> + * - add get_features() to support various size of conntrack + * structures. + * + * Derived from net/ipv4/netfilter/ip_conntrack_standalone.c + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/ip.h> +#include <linux/netfilter.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/icmp.h> +#include <linux/sysctl.h> +#include <net/ip.h> + +#include <linux/netfilter_ipv4.h> +#include <net/netfilter/nf_conntrack.h> +#include <net/netfilter/nf_conntrack_helper.h> +#include <net/netfilter/nf_conntrack_protocol.h> +#include <net/netfilter/nf_conntrack_l3proto.h> +#include <net/netfilter/nf_conntrack_core.h> +#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat); + +static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, + struct nf_conntrack_tuple *tuple) +{ + u_int32_t _addrs[2], *ap; + ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), + sizeof(u_int32_t) * 2, _addrs); + if (ap == NULL) + return 0; + + tuple->src.u3.ip = ap[0]; + tuple->dst.u3.ip = ap[1]; + + return 1; +} + +static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_tuple *orig) +{ + tuple->src.u3.ip = orig->dst.u3.ip; + tuple->dst.u3.ip = orig->src.u3.ip; + + return 1; +} + +static int ipv4_print_tuple(struct seq_file *s, + const struct nf_conntrack_tuple *tuple) +{ + return seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", + NIPQUAD(tuple->src.u3.ip), + NIPQUAD(tuple->dst.u3.ip)); +} + +static int ipv4_print_conntrack(struct seq_file *s, + const struct nf_conn *conntrack) +{ + return 0; +} + +/* Returns new sk_buff, or NULL */ +static struct sk_buff * +nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) +{ + skb_orphan(skb); + + local_bh_disable(); + skb = ip_defrag(skb, user); + local_bh_enable(); + + if (skb) + ip_send_check(skb->nh.iph); + + return skb; +} + +static int +ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, + u_int8_t *protonum) +{ + /* Never happen */ + if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) { + if (net_ratelimit()) { + printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", + (*pskb)->nh.iph->protocol, hooknum); + } + return -NF_DROP; + } + + *dataoff = (*pskb)->nh.raw - (*pskb)->data + (*pskb)->nh.iph->ihl*4; + *protonum = (*pskb)->nh.iph->protocol; + + return NF_ACCEPT; +} + +int nat_module_is_loaded = 0; +static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) |