Sogor Laszlo <sogor@xxxxxxxxxxxxxxxxxxxxx> writes:
> We do a SIIT (Stateless IP/ICMP Translator) for the Linux kernel (2.2.14).
[...]
> The another problem is: if we "ping" the IPv6 only host from the IPv4 only
> host over the SIIT, the packet the IPv6 only host receives has IPv4 MAPPED
> IPv6 source address, and it doesn't response for it.
If you follow the RFC-2765(SIIT) then the translated ping requests has
a fragmentation header added.
Kernel 2.2.14 (and 2.2.15 for that matter) doesn't handle
nonfragmented IPv6 packets, that contains a fragmentation header.
Alexey has found that bug i Kernel 2.3.99-pre5, and sent me a
patch.
I've extrapolated a patch to Kernel 2.2.14 that also fixes the bug.
I'll append that patch below.
Regards,
Richard Jørgensen
---------------------------------------------------------------------------
diff -ur linux-2.2.14_orig/net/ipv6/ip6_input.c
/usr/src/linux-2.2.14/net/ipv6/ip6_input.c
--- linux-2.2.14_orig/net/ipv6/ip6_input.c Thu Aug 26 02:29:53 1999
+++ /usr/src/linux-2.2.14/net/ipv6/ip6_input.c Fri Apr 28 09:49:11 2000
@@ -99,7 +99,7 @@
struct raw6_opt *opt;
opt = &sk->tp_pinfo.tp_raw;
- icmph = (struct icmp6hdr *) (skb->nh.ipv6h + 1);
+ icmph = (struct icmp6hdr *) skb->h.raw;
return test_bit(icmph->icmp6_type, &opt->filter);
}
diff -ur linux-2.2.14_orig/net/ipv6/ip6_output.c
/usr/src/linux-2.2.14/net/ipv6/ip6_output.c
--- linux-2.2.14_orig/net/ipv6/ip6_output.c Fri Apr 23 04:45:20 1999
+++ /usr/src/linux-2.2.14/net/ipv6/ip6_output.c Fri Apr 28 10:00:04 2000
@@ -121,7 +121,7 @@
if (skb_headroom(skb) < head_room) {
struct sk_buff *skb2 = skb_realloc_headroom(skb,
head_room);
- kfree(skb);
+ kfree_skb(skb);
skb = skb2;
if (skb == NULL)
return -ENOBUFS;
diff -ur linux-2.2.14_orig/net/ipv6/reassembly.c
/usr/src/linux-2.2.14/net/ipv6/reassembly.c
--- linux-2.2.14_orig/net/ipv6/reassembly.c Fri Aug 28 04:33:09 1998
+++ /usr/src/linux-2.2.14/net/ipv6/reassembly.c Thu Apr 27 12:38:52 2000
@@ -160,6 +160,15 @@
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
return NULL;
}
+
+ if (!(fhdr->frag_off & __constant_htons(0xFFF9))) {
+ /* It is not a fragmnted frame */
+ skb->h.raw += sizeof(struct frag_hdr);
+ ipv6_statistics.Ip6ReasmOKs++;
+
+ return &fhdr->nexthdr;
+ }
+
if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
frag_prune();
|