[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