[Openswan dev]
ESP fragments with zero packet id cause reassembly errors
Peter Lenci
peterlenci at yahoo.ca
Wed Jul 27 17:40:50 CEST 2005
Hi all
In klips/net/ipsec/ipsec_tunnel.c:ipsec_tunnel_start_xmit() Openswan
builds IP packets and then sends them off using include/net/ip.h:ip_send().
Unfortunately the id in the ip header (skb->nh.iph->id) is not set for ESP
nor IKE packets which may cause faulty packet reassembly on the receiver
side (especially with lots of peers and fast links).
There are two things I don't understand (does anybody?):
1. There is one single(!) invocation of ip_select_ident() in ipsec_tunnel.c
but that section is only called if tdbp->tdb_encalg == IPPROTO_IPIP which
is not the case for IKE or ESP packets. Therefore the packet id always
remains set to zero which is very bad for packets to be fragmented.
try: tcpdump -v 'ip[4]=0' and 'ip[5]=0'
2. When the code reaches ip_send() the DF (do not fragment) bit is always
set even if the packet size is huge (like 20000 bytes)!
try: tcpdump -v \( 'ip[6]&0x20=0x20' or 'ip[6]&0x1f!=0' or 'ip[7]!=0' \)
I have written an ugly patch as an immediate fix to my problem. Works fine
but probably is not done right as I haven't spent much time understanding
Openswan source code:
/usr/src/openswan-1.0.10rc1/klips/net/ipsec]# diff -c ipsec_tunnel.c.orig
ipsec_tunnel.c
*** ipsec_tunnel.c.orig Tue Feb 22 01:37:18 2005
--- ipsec_tunnel.c Wed Jul 27 22:24:21 2005
***************
*** 2145,2150 ****
--- 2145,2169 ----
"With hard_header, final head,tailroom: %d,%d\n",
skb_headroom(skb), skb_tailroom(skb));
+ /* hack: always enforce a packet id by temporary */
+ /* deleting the DF bit and calling the id creation routine. The */
+ /* original code always resulted in a zero id even when the packet */
+ /* was fragmented later on which caused reassembly errors on the */
+ /* receiver side */
+ if(skb->nh.iph->id == 0 ) {
+ struct iphdr *ipp = skb->nh.iph;
+ __u16 frag_save = ipp->frag_off;
+ ipp->frag_off = ipp->frag_off - (ipp->frag_off &
__constant_htons(IP_DF));
+ #ifdef IP_SELECT_IDENT_NEW
+ ip_select_ident(ipp, skb->dst, skb->sk);
+ #else /* IP_SELECT_IDENT_NEW */
+ ip_select_ident(ipp, skb->dst);
+ #endif /* IP_SELECT_IDENT_NEW */
+ ipp->frag_off = ipp->frag_off | frag_save;
+ ipp->check = 0;
+ ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl);
+ }
+
#ifdef NET_21 /* 2.2 and 2.4 kernels */
/* new route/dst cache code from James Morris */
skb->dev = physdev;
Oh, BTW the above code is for openswan-1.0.10rc1. The same problem existed
for openswan v2 so I figured it would be better to investigate and patch the
more mature v1 code.
Regards
Peter
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
More information about the Dev
mailing list