Can't have TRACE target on vanilla Linux 2.4.30 and iptables 1.3.1

Artūras Šlajus x11 at kitas.arturas.net
Wed Apr 20 21:43:32 CEST 2005


Hello,

I've been struggling from morning with this (22:36 now :/) and can't 
make it work.

So I have 2.4.30 kernel. I try to apply raw patch, which is needed by 
TRACE. It fails with 3 rejects.

I ask for this on #netfilter. Guy named xkr47 helps me, and changes the 
patch (which i've attached).

So now it applies cleanly, I apply these patches:

./runme time CLASSIFY CONNMARK mport nf-log raw TRACE

Then I make kernel (using make-kpkg, if that matters).
i get this:

rm -f ipv4.o
ld -m elf_i386 -e stext  -r -o ipv4.o utils.o route.o inetpeer.o proc.o 
protocol.o ip_input.o ip_fragment.o ip_forward.o ip_options.o 
ip_output.o ip_sockglue.o tcp.o tcp_input.o tcp_output.o tcp_timer.o 
tcp_ipv4.o tcp_minisocks.o tcp_diag.o raw.o udp.o arp.o icmp.o devinet.o 
af_inet.o igmp.o sysctl_net_ipv4.o fib_frontend.o fib_semantics.o 
fib_hash.o fib_rules.o ip_nat_dumb.o syncookies.o
make[4]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4'
make[3]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4'
/usr/bin/make -C ipv4/netfilter
make[3]: Entering directory 
`/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
/usr/bin/make all_targets
make[4]: Entering directory 
`/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
gcc -D__KERNEL__ -I/usr/src/router/linux-2.4.30/include -Wall 
-Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common 
-fomit-frame-pointer -pipe -mpreferred-stack-boundary=2 -march=i486 
-nostdinc -iwithprefix include -DKBUILD_BASENAME=ip_conntrack_standalone 
  -DEXPORT_SYMTAB -c ip_conntrack_standalone.c
ip_conntrack_standalone.c: In function `ip_conntrack_defrag':
ip_conntrack_standalone.c:208: error: too few arguments to function 
`ip_ct_gather_frags'
make[4]: *** [ip_conntrack_standalone.o] Error 1
make[4]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
make[3]: *** [first_rule] Error 2
make[3]: Leaving directory `/usr/src/router/linux-2.4.30/net/ipv4/netfilter'
make[2]: *** [_subdir_ipv4/netfilter] Error 2
make[2]: Leaving directory `/usr/src/router/linux-2.4.30/net'
make[1]: *** [_dir_net] Error 2
make[1]: Leaving directory `/usr/src/router/linux-2.4.30'
make: *** [stamp-build] Error 2
22:23 fs:/usr/src/router/linux-2.4.30#

As far I figured it out, these extensions modify ip_conntrack_standalone.c:

22:42 fs:/usr/src/patch-o-matic-ng-20050419# grep 
ip_conntrack_standalone.c * -R | awk {'print $1'} | cut -d / -f 1 | uniq
CONNMARK
connrate
conntrack-acct
conntrack-event-api
conntrack_locking
conntrack_nonat
ctnetlink
ipsec-03-policy-lookup
netfilter-docbook
nf_conntrack
nfnetlink-ctnetlink-0.13
raw
tcp-window-tracking
tproxy

I tried bare minimum I need, but I guess raw patch makes irreversible 
changes.

I'd greatly appreciaty any help.
-------------- next part --------------
diff -Nru linuxor/include/linux/netfilter_ipv4/ip_conntrack.h linux/include/linux/netfilter_ipv4/ip_conntrack.h
--- linuxor/include/linux/netfilter_ipv4/ip_conntrack.h	2005-04-20 19:12:36.000000000 +0300
+++ linux/include/linux/netfilter_ipv4/ip_conntrack.h	2005-04-20 19:19:22.000000000 +0300
@@ -249,6 +249,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);
diff -Nru linuxor/include/linux/netfilter_ipv4/ipt_conntrack.h linux/include/linux/netfilter_ipv4/ipt_conntrack.h
--- linuxor/include/linux/netfilter_ipv4/ipt_conntrack.h	2004-02-20 20:49:49.000000000 +0200
+++ linux/include/linux/netfilter_ipv4/ipt_conntrack.h	2005-04-20 19:19:51.000000000 +0300
@@ -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 -Nru linuxor/include/linux/netfilter_ipv4/ipt_state.h linux/include/linux/netfilter_ipv4/ipt_state.h
--- linuxor/include/linux/netfilter_ipv4/ipt_state.h	2000-07-17 18:25:05.000000000 +0300
+++ linux/include/linux/netfilter_ipv4/ipt_state.h	2005-04-20 19:19:51.000000000 +0300
@@ -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 -Nru linuxor/include/linux/netfilter_ipv4.h linux/include/linux/netfilter_ipv4.h
--- linuxor/include/linux/netfilter_ipv4.h	2004-02-20 20:48:03.000000000 +0200
+++ linux/include/linux/netfilter_ipv4.h	2005-04-20 19:19:51.000000000 +0300
@@ -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,
diff -Nru linuxor/net/ipv4/netfilter/ip_conntrack_core.c linux/net/ipv4/netfilter/ip_conntrack_core.c
--- linuxor/net/ipv4/netfilter/ip_conntrack_core.c	2005-04-20 19:12:36.000000000 +0300
+++ linux/net/ipv4/netfilter/ip_conntrack_core.c	2005-04-20 19:17:24.000000000 +0300
@@ -65,6 +65,7 @@
 struct list_head *ip_conntrack_hash;
 static kmem_cache_t *ip_conntrack_cachep;
 static LIST_HEAD(unconfirmed);
+struct ip_conntrack ip_conntrack_untracked;
 
 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
 
@@ -823,6 +824,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;
 
@@ -841,21 +851,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,
-		                           hooknum == NF_IP_PRE_ROUTING ?
-		                           IP_DEFRAG_CONNTRACK_IN :
-		                           IP_DEFRAG_CONNTRACK_OUT);
-		if (!*pskb)
-			return NF_STOLEN;
-	}
-
 	proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
 
 	/* It may be an icmp error... */
@@ -1459,6 +1458,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:
diff -Nru linuxor/net/ipv4/netfilter/ip_conntrack_standalone.c linux/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linuxor/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-04-20 19:12:36.000000000 +0300
+++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-04-20 19:19:51.000000000 +0300
@@ -189,6 +189,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,
@@ -230,9 +250,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 };
@@ -353,10 +379,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) {
@@ -394,6 +430,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:
@@ -483,5 +523,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 -Nru linuxor/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c
--- linuxor/net/ipv4/netfilter/ip_nat_core.c	2005-04-20 19:12:36.000000000 +0300
+++ linux/net/ipv4/netfilter/ip_nat_core.c	2005-04-20 19:19:51.000000000 +0300
@@ -1023,6 +1023,10 @@
 	/* 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 -Nru linuxor/net/ipv4/netfilter/ipt_conntrack.c linux/net/ipv4/netfilter/ipt_conntrack.c
--- linuxor/net/ipv4/netfilter/ipt_conntrack.c	2004-02-20 20:52:45.000000000 +0200
+++ linux/net/ipv4/netfilter/ipt_conntrack.c	2005-04-20 19:19:51.000000000 +0300
@@ -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 !=
diff -Nru linuxor/net/ipv4/netfilter/ipt_state.c linux/net/ipv4/netfilter/ipt_state.c
--- linuxor/net/ipv4/netfilter/ipt_state.c	2004-02-20 20:52:45.000000000 +0200
+++ linux/net/ipv4/netfilter/ipt_state.c	2005-04-20 19:19:51.000000000 +0300
@@ -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);


More information about the netfilter mailing list