PF or "traceroute -e -P TCP" bug?

Rostislav Krasny rosti.bsd at gmail.com
Fri Aug 18 20:58:24 UTC 2006


Hi,

I've tried the new "-e" traceroute option on today's RELENG_6 and
found following problem:

> traceroute -nq 1 -e -P TCP -p 80 216.136.204.117
traceroute to 216.136.204.117 (216.136.204.117), 64 hops max, 52 bytepackets
 1  192.168.1.1  0.619 ms
 2  10.0.0.138  2.108 ms
 3  192.168.1.1  0.481 ms !H
> 

The 192.168.1.1 is other 6.1-STABLE machine which is used as a NAT
router. It's one or two days older RELENG_6. The NATing is done by PF.
The 10.0.0.138 is my ADSL modem which I use in "DHCP spoofing" mode,
i.e. it gives to the router an external IP address from my ISP.

I've fixed the bug by following patch:

--- traceroute.c.orig	Fri Aug 18 19:19:23 2006
+++ traceroute.c	Fri Aug 18 22:05:08 2006
@@ -1355,7 +1355,7 @@
 {
 	struct tcphdr *const tcp = (struct tcphdr *) outp;
 
-	tcp->th_sport = htons(ident);
+	tcp->th_sport = htons(ident + (fixedPort ? outdata->seq : 0));
 	tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
 	tcp->th_seq = (tcp->th_sport << 16) | (tcp->th_dport +
 	    (fixedPort ? outdata->seq : 0));
@@ -1375,7 +1375,7 @@
 {
 	struct tcphdr *const tcp = (struct tcphdr *) data;
 
-	return (ntohs(tcp->th_sport) == ident
+	return (ntohs(tcp->th_sport) == ident + (fixedPort ? seq : 0)
 	    && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq))
 	    && tcp->th_seq == (ident << 16) | (port + seq);
 }

However this patch isn't complete or it is just a workaround of
completely different bug in the router, because sometimes the new
traceroute produced a similar problem:

> traceroute -nq 1 -e -P TCP -p 12345 216.136.204.117
traceroute to 216.136.204.117 (216.136.204.117), 64 hops max, 52 byte packets
 1  192.168.1.1  1.414 ms
 2  10.0.0.138  4.584 ms
 3  212.143.208.128  203.325 ms
 4  212.143.208.126  101.073 ms
 5  212.143.10.65  175.442 ms
^C
> traceroute -nq 1 -e -P TCP -p 12345 216.136.204.117
traceroute to 216.136.204.117 (216.136.204.117), 64 hops max, 52 byte packets
 1  192.168.1.1  0.740 ms
 2  192.168.1.1  0.718 ms !H
> traceroute -nq 1 -e -P TCP -p 12345 216.136.204.117
traceroute to 216.136.204.117 (216.136.204.117), 64 hops max, 52 byte packets
 1  192.168.1.1  0.692 ms
 2  192.168.1.1  0.770 ms !H
> 

After waiting enough time I can successfully repeat the command.
Is it actually a PF bug?

Finally I made other version of my patch:

--- traceroute.c.orig	Fri Aug 18 19:19:23 2006
+++ traceroute.c	Fri Aug 18 23:40:43 2006
@@ -471,6 +471,7 @@
 	register int lsrr = 0;
 	register u_short off = 0;
 	struct ifaddrlist *al;
+	struct timespec time_sp;
 	char errbuf[132];
 	int requestPort = -1;
 	int sump = 0;
@@ -721,7 +722,8 @@
 		outip->ip_dst = to->sin_addr;
 
 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
-	ident = (getpid() & 0xffff) | 0x8000;
+	clock_gettime(CLOCK_REALTIME, &time_sp);
+	ident = ((u_short)time_sp.tv_nsec & 0xffff) | 0x8000;
 
 	if (pe == NULL) {
 		Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
@@ -1355,7 +1357,7 @@
 {
 	struct tcphdr *const tcp = (struct tcphdr *) outp;
 
-	tcp->th_sport = htons(ident);
+	tcp->th_sport = htons(ident + (fixedPort ? outdata->seq : 0));
 	tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
 	tcp->th_seq = (tcp->th_sport << 16) | (tcp->th_dport +
 	    (fixedPort ? outdata->seq : 0));
@@ -1375,7 +1377,7 @@
 {
 	struct tcphdr *const tcp = (struct tcphdr *) data;
 
-	return (ntohs(tcp->th_sport) == ident
+	return (ntohs(tcp->th_sport) == ident + (fixedPort ? seq : 0)
 	    && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq))
 	    && tcp->th_seq == (ident << 16) | (port + seq);
 }


Now traceroute works fine. But I'm still suspecting PF.


More information about the freebsd-net mailing list