OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / net / ipsec / ipcomp.c
1 /*
2  * IPCOMP zlib interface code.
3  * Copyright (C) 2000  Svenning Soerensen <svenning@post5.tele.dk>
4  * Copyright (C) 2000, 2001  Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
5  * 
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or (at your
9  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
10  * 
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * for more details.
15  */
16
17 char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.28 2002/01/29 17:17:54 mcr Exp $";
18
19 /* SSS */
20
21 #include <linux/config.h>
22 #include <linux/version.h>
23
24 #define __NO_VERSION__
25 #include <linux/module.h>
26 #include <linux/kernel.h> /* printk() */
27
28 #define IPSEC_KLIPS1_COMPAT
29 #include "ipsec_param.h"
30
31 #ifdef MALLOC_SLAB
32 # include <linux/slab.h> /* kmalloc() */
33 #else /* MALLOC_SLAB */
34 # include <linux/malloc.h> /* kmalloc() */
35 #endif /* MALLOC_SLAB */
36 #include <linux/errno.h>  /* error codes */
37 #include <linux/types.h>
38 #include <linux/netdevice.h>
39 #include <linux/ip.h>
40 #include <linux/skbuff.h>
41
42 #include <linux/netdevice.h>   /* struct device, and other headers */
43 #include <linux/etherdevice.h> /* eth_type_trans */
44 #include <linux/ip.h>          /* struct iphdr */
45 #include <linux/skbuff.h>
46
47 #include <freeswan.h>
48 #ifdef NET_21
49 # include <net/dst.h>
50 # include <asm/uaccess.h>
51 # include <linux/in6.h>
52 # define proto_priv cb
53 #endif /* NET21 */
54 #include <asm/checksum.h>
55 #include <net/ip.h>
56
57 #include "radij.h"
58 #include "ipsec_encap.h"
59 #include "ipsec_sa.h"
60
61 #include "ipsec_netlink.h"
62 #include "ipsec_xform.h"
63 #include "ipsec_tunnel.h"
64 #include "ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */
65 #include "ipcomp.h"
66 #include "zlib/zlib.h"
67 #include "zlib/zutil.h"
68
69 #include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */
70
71 #ifdef CONFIG_IPSEC_DEBUG
72 int sysctl_ipsec_debug_ipcomp = 0;
73 #endif /* CONFIG_IPSEC_DEBUG */
74
75 #ifdef CONFIG_IPSEC_IPCOMP_LZS
76 /*
77  *      Allow for both hardware and software driven lzs compressors.
78  */
79 extern unsigned int     (*hw_lzs_compress)(unsigned char *in, int ilen,
80                                 unsigned char *out, int olen);
81 extern unsigned int     (*hw_lzs_decompress)(unsigned char *in, int ilen,
82                                 unsigned char *out, int olen);
83 extern unsigned int     lzs_compress(unsigned char *in, int ilen,
84                                 unsigned char *out, int olen);
85 extern unsigned int     lzs_decompress(unsigned char *in, int ilen,
86                                 unsigned char *out, int olen);
87
88 #define _lzs_compress(a,b,c,d) \
89         (hw_lzs_compress ? (*hw_lzs_compress)(a,b,c,d) : lzs_compress(a,b,c,d))
90 #define _lzs_decompress(a,b,c,d) \
91         (hw_lzs_decompress ? (*hw_lzs_decompress)(a,b,c,d) : lzs_decompress(a,b,c,d))
92 #endif
93
94 static
95 struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask);
96
97 static
98 voidpf my_zcalloc(voidpf opaque, uInt items, uInt size)
99 {
100         return (voidpf) kmalloc(items*size, GFP_ATOMIC);
101 }
102
103 static
104 void my_zfree(voidpf opaque, voidpf address)
105 {
106         kfree(address);
107 }
108
109 struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags)
110 {
111         struct iphdr *iph;
112         unsigned int iphlen, pyldsz, cpyldsz;
113         unsigned char *buffer;
114         z_stream zs={0,};
115         int zresult;
116         
117         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
118                     "klips_debug:skb_compress: .\n");
119
120         if(!skb) {
121                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
122                             "klips_debug:skb_compress: "
123                             "passed in NULL skb, returning ERROR.\n");
124                 if (flags) *flags |= IPCOMP_PARMERROR;
125                 return skb;
126         }
127
128         if(!tdb) {
129                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
130                             "klips_debug:skb_compress: "
131                             "passed in NULL tdb needed for cpi, returning ERROR.\n");
132                 if (flags) *flags |= IPCOMP_PARMERROR;
133                 return skb;
134         }
135
136         if (!flags) {
137                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
138                             "klips_debug:skb_compress: "
139                             "passed in NULL flags, returning ERROR.\n");
140 #ifdef NET_21
141                 kfree_skb(skb);
142 #else /* NET_21 */
143                 dev_kfree_skb(skb, FREE_WRITE);
144 #endif /* NET_21 */
145                 return NULL;
146         }
147         
148 #ifdef NET_21
149         iph = skb->nh.iph;
150 #else /* NET_21 */
151         iph = skb->ip_hdr;
152 #endif /* NET_21 */
153
154         switch (iph->protocol) {
155         case IPPROTO_COMP:
156         case IPPROTO_AH:
157         case IPPROTO_ESP:
158                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
159                             "klips_debug:skb_compress: "
160                             "skipping compression of packet with ip protocol %d.\n",
161                             iph->protocol);
162                 *flags |= IPCOMP_UNCOMPRESSABLE;
163                 return skb;
164         }
165         
166         /* Don't compress packets already fragmented */
167         if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) {
168                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
169                             "klips_debug:skb_compress: "
170                             "skipping compression of fragmented packet.\n");
171                 *flags |= IPCOMP_UNCOMPRESSABLE;
172                 return skb;
173         }
174         
175         iphlen = iph->ihl << 2;
176         pyldsz = ntohs(iph->tot_len) - iphlen;
177
178         /* Don't compress less than 90 bytes (rfc 2394) */
179         if (pyldsz < 90) {
180                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
181                             "klips_debug:skb_compress: "
182                             "skipping compression of tiny packet, len=%d.\n",
183                             pyldsz);
184                 *flags |= IPCOMP_UNCOMPRESSABLE;
185                 return skb;
186         }
187         
188         /* Adaptive decision */
189         if (tdb->tdb_comp_adapt_skip) {
190                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
191                             "klips_debug:skb_compress: "
192                             "skipping compression: tdb_comp_adapt_skip=%d.\n",
193                             tdb->tdb_comp_adapt_skip);
194                 tdb->tdb_comp_adapt_skip--;
195                 *flags |= IPCOMP_UNCOMPRESSABLE;
196                 return skb;
197         }
198
199         if (tdb->tdb_encalg != SADB_X_CALG_LZS) {
200                 zs.zalloc = my_zcalloc;
201                 zs.zfree = my_zfree;
202                 zs.opaque = 0;
203         
204                 /* We want to use deflateInit2 because we don't want the adler
205                   header. */
206                 zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11,
207                                 DEF_MEM_LEVEL,  Z_DEFAULT_STRATEGY);
208                 if (zresult != Z_OK) {
209                         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
210                             "klips_error:skb_compress: "
211                             "deflateInit2() returned error %d (%s), "
212                             "skipping compression.\n",
213                             zresult,
214                             zs.msg ? zs.msg : zError(zresult));
215                         *flags |= IPCOMP_COMPRESSIONERROR;
216                         return skb;
217                 }
218         }
219
220         /* Max output size. Result should be max this size.
221          * Implementation specific tweak:
222          * If it's not at least 32 bytes and 6.25% smaller than
223          * the original packet, it's probably not worth wasting
224          * the receiver's CPU cycles decompressing it.
225          * Your mileage may vary.
226          */
227         cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4);
228
229         buffer = kmalloc(cpyldsz, GFP_ATOMIC);
230         if (!buffer) {
231                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
232                             "klips_error:skb_compress: "
233                             "unable to kmalloc(%d, GFP_ATOMIC), "
234                             "skipping compression.\n",
235                             cpyldsz);
236                 *flags |= IPCOMP_COMPRESSIONERROR;
237                 deflateEnd(&zs);
238                 return skb;
239         }
240         
241 #ifdef CONFIG_IPSEC_DEBUG
242         if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
243                 __u8 *c;
244                 int i;
245
246                 c = (__u8*)iph + iphlen;
247                 for(i = 0; i < pyldsz; i++, c++) {
248                         if(!(i % 16)) {
249                                 printk(KERN_INFO "skb_compress:   before:");
250                         }
251                         printk("%02x ", *c);
252                         if(!((i + 1) % 16)) {
253                                 printk("\n");
254                         }
255                 }
256                 if(i % 16) {
257                         printk("\n");
258                 }
259         }
260 #endif /* CONFIG_IPSEC_DEBUG */
261
262 #ifdef CONFIG_IPSEC_IPCOMP_LZS
263         if (tdb->tdb_encalg == SADB_X_CALG_LZS) {
264                 void *inbuf;
265                 int rc;
266
267                 inbuf = (char *) iph + iphlen; /* start of payload */
268                 if ((rc = _lzs_compress(inbuf, pyldsz, buffer, cpyldsz)) < 0)
269                         goto badcompress;
270                 cpyldsz = rc;
271         } else {
272 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
273
274                 zs.next_in = (char *) iph + iphlen; /* start of payload */
275                 zs.avail_in = pyldsz;
276                 zs.next_out = buffer;     /* start of compressed payload */
277                 zs.avail_out = cpyldsz;
278         
279                 /* Finish compression in one step */
280                 zresult = deflate(&zs, Z_FINISH);
281
282                 /* Free all dynamically allocated buffers */
283                 deflateEnd(&zs);
284                 if (zresult != Z_STREAM_END) {
285 badcompress:
286                         *flags |= IPCOMP_UNCOMPRESSABLE;
287                         kfree(buffer);
288
289                         /* Adjust adaptive counters */
290                         if (++(tdb->tdb_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) {
291                                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
292                                     "klips_debug:skb_compress: "
293                                     "first %d packets didn't compress, "
294                                     "skipping next %d\n",
295                                     IPCOMP_ADAPT_INITIAL_TRIES,
296                                     IPCOMP_ADAPT_INITIAL_SKIP);
297                                 tdb->tdb_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP;
298                         }
299                         else if (tdb->tdb_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) {
300                                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
301                                     "klips_debug:skb_compress: "
302                                     "next %d packets didn't compress, "
303                                     "skipping next %d\n",
304                                     IPCOMP_ADAPT_SUBSEQ_TRIES,
305                                     IPCOMP_ADAPT_SUBSEQ_SKIP);
306                                 tdb->tdb_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP;
307                                 tdb->tdb_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES;
308                         }
309
310                         return skb;
311                 }
312         
313                 /* resulting compressed size */
314                 cpyldsz -= zs.avail_out;
315
316 #ifdef CONFIG_IPSEC_IPCOMP_LZS
317         }
318 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
319         
320         /* Insert IPCOMP header */
321         ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol;
322         ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0;
323         /* use the bottom 16 bits of the spi for the cpi.  The top 16 bits are
324            for internal reference only. */
325         ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(tdb->tdb_said.spi) & 0x0000ffff));
326         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
327                     "klips_debug:skb_compress: "
328                     "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n",
329                     ntohl(tdb->tdb_said.spi),
330                     ntohl(tdb->tdb_said.spi) & 0x0000ffff,
331                     ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi),
332                     pyldsz,
333                     cpyldsz);
334         
335         /* Update IP header */
336         iph->protocol = IPPROTO_COMP;
337         iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz);
338 #if 1 /* XXX checksum is done by ipsec_tunnel ? */
339         iph->check = 0;
340         iph->check = ip_fast_csum((char *) iph, iph->ihl);
341 #endif
342         
343         /* Copy compressed payload */
344         memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr),
345                buffer,
346                cpyldsz);
347         kfree(buffer);
348         
349         /* Update skb length/tail by "unputting" the shrinkage */
350         skb_put(skb,
351                 cpyldsz + sizeof(struct ipcomphdr) - pyldsz);
352         
353 #ifdef CONFIG_IPSEC_DEBUG
354         if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
355                 __u8 *c;
356                 int i;
357                 
358                 c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr);
359                 for(i = 0; i < cpyldsz; i++, c++) {
360                         if(!(i % 16)) {
361                                 printk(KERN_INFO "skb_compress:   result:");
362                         }
363                         printk("%02x ", *c);
364                         if(!((i + 1) % 16)) {
365                                 printk("\n");
366                         }
367                 }
368                 if(i % 16) {
369                         printk("\n");
370                 }
371         }
372 #endif /* CONFIG_IPSEC_DEBUG */
373         
374         tdb->tdb_comp_adapt_skip = 0;
375         tdb->tdb_comp_adapt_tries = 0;
376         
377         return skb;
378 }
379
380 struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags)
381 {
382         struct sk_buff *nskb = NULL;
383
384         /* original ip header */
385         struct iphdr *oiph, *iph;
386         unsigned int iphlen, pyldsz, cpyldsz, avail_out;
387         z_stream zs;
388         int zresult;
389
390         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
391                     "klips_debug:skb_decompress: .\n");
392
393         if(!skb) {
394                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
395                             "klips_error:skb_decompress: "
396                             "passed in NULL skb, returning ERROR.\n");
397                 if (flags) *flags |= IPCOMP_PARMERROR;
398                 return skb;
399         }
400
401         if(!tdb && sysctl_ipsec_inbound_policy_check) {
402                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
403                             "klips_error:skb_decompress: "
404                             "passed in NULL tdb needed for comp alg, returning ERROR.\n");
405                 if (flags) *flags |= IPCOMP_PARMERROR;
406                 return skb;
407         }
408
409         if (!flags) {
410                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
411                             "klips_error:skb_decompress: "
412                             "passed in NULL flags, returning ERROR.\n");
413 #ifdef NET_21
414                 kfree_skb(skb);
415 #else /* NET_21 */
416                 dev_kfree_skb(skb, FREE_WRITE);
417 #endif /* NET_21 */
418                 return NULL;
419         }
420         
421 #ifdef NET_21
422         oiph = skb->nh.iph;
423 #else /* NET_21 */
424         oiph = skb->ip_hdr;
425 #endif /* NET_21 */
426         
427         iphlen = oiph->ihl << 2;
428         
429         if (oiph->protocol != IPPROTO_COMP) {
430                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
431                             "klips_error:skb_decompress: "
432                             "called with non-IPCOMP packet (protocol=%d),"
433                             "skipping decompression.\n",
434                             oiph->protocol);
435                 *flags |= IPCOMP_PARMERROR;
436                 return skb;
437         }
438         
439         if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0)
440              || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi
441                 != htons(SADB_X_CALG_DEFLATE))
442                  && sysctl_ipsec_inbound_policy_check
443                  && (!tdb || (tdb && 
444                    ((tdb->tdb_encalg != SADB_X_CALG_DEFLATE)
445                    && (tdb->tdb_encalg != SADB_X_CALG_LZS)) ))) ) {
446                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
447                             "klips_error:skb_decompress: "
448                             "called with incompatible IPCOMP packet (flags=%d, "
449                             "cpi=%d), tdb-compalg=%d, skipping decompression.\n",
450                             ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags),
451                             ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi),
452                             tdb ? tdb->tdb_encalg : 0);
453                 *flags |= IPCOMP_PARMERROR;
454                 
455                 return skb;
456         }
457         
458         if (ntohs(oiph->frag_off) & ~0x4000) {
459                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
460                             "klips_error:skb_decompress: "
461                             "called with fragmented IPCOMP packet, "
462                             "skipping decompression.\n");
463                 *flags |= IPCOMP_PARMERROR;
464                 return skb;
465         }
466         
467         /* original compressed payload size */
468         cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr);
469
470         if (tdb->tdb_encalg != SADB_X_CALG_LZS) {
471                 zs.zalloc = my_zcalloc;
472                 zs.zfree = my_zfree;
473                 zs.opaque = 0;
474         
475                 zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
476                 zs.avail_in = cpyldsz;
477         
478                 /* Maybe we should be a bit conservative about memory
479                    requirements and use inflateInit2 */
480                 /* Beware, that this might make us unable to decompress packets
481                    from other implementations - HINT: check PGPnet source code */
482                 /* We want to use inflateInit2 because we don't want the adler
483                    header. */
484                 zresult = inflateInit2(&zs, -15); 
485                 if (zresult != Z_OK) {
486                         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
487                             "klips_error:skb_decompress: "
488                             "inflateInit2() returned error %d (%s), "
489                             "skipping decompression.\n",
490                             zresult,
491                             zs.msg ? zs.msg : zError(zresult));
492                         *flags |= IPCOMP_DECOMPRESSIONERROR;
493
494                         return skb;
495                 }
496         }
497         
498         /* We have no way of knowing the exact length of the resulting
499            decompressed output before we have actually done the decompression.
500            For now, we guess that the packet will not be bigger than the
501            attached ipsec device's mtu or 16260, whichever is biggest.
502            This may be wrong, since the sender's mtu may be bigger yet.
503            XXX This must be dealt with later XXX
504         */
505         
506         /* max payload size */
507         pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu)
508                           : (65520 - iphlen);
509         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
510                     "klips_debug:skb_decompress: "
511                     "max payload size: %d\n", pyldsz);
512         
513         while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) && 
514                (nskb = skb_copy_ipcomp(skb,
515                                        pyldsz - cpyldsz - sizeof(struct ipcomphdr),
516                                        GFP_ATOMIC)) == NULL) {
517                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
518                             "klips_error:skb_decompress: "
519                             "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), "
520                             "trying with less payload size.\n",
521                             pyldsz - cpyldsz - sizeof(struct ipcomphdr));
522                 pyldsz >>=1;
523         }
524         
525         if (!nskb) {
526                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
527                             "klips_error:skb_decompress: "
528                             "unable to allocate memory, dropping packet.\n");
529                 *flags |= IPCOMP_DECOMPRESSIONERROR;
530                 inflateEnd(&zs);
531
532                 return skb;
533         }
534         
535 #ifdef CONFIG_IPSEC_DEBUG
536         if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
537                 __u8 *c;
538                 int i;
539                 
540                 c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr);
541                 for(i = 0; i < cpyldsz; i++, c++) {
542                         if(!(i % 16)) {
543                                 printk(KERN_INFO "skb_decompress:   before:");
544                         }
545                         printk("%02x ", *c);
546                         if(!((i + 1) % 16)) {
547                                 printk("\n");
548                         }
549                 }
550                 if(i % 16) {
551                         printk("\n");
552                 }
553         }
554 #endif /* CONFIG_IPSEC_DEBUG */
555
556 #ifdef NET_21
557         iph = nskb->nh.iph;
558 #else /* NET_21 */
559         iph = nskb->ip_hdr;
560 #endif /* NET_21 */
561
562 #ifdef CONFIG_IPSEC_IPCOMP_LZS
563         if (tdb->tdb_encalg == SADB_X_CALG_LZS) {
564                 void *inbuf, *outbuf;
565                 int rc;
566         
567                 inbuf = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
568                 outbuf = (char *)iph + iphlen;
569
570                 if ((rc = _lzs_decompress(inbuf, cpyldsz, outbuf, pyldsz)) < 0) {
571                         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
572                                     "klips_error:skb_decompress: "
573                                     "lzs_decompress() returned error %d, "
574                                     "skipping decompression.\n", rc);
575                         *flags |= IPCOMP_DECOMPRESSIONERROR;
576 #ifdef NET_21
577                         kfree_skb(nskb);
578 #else /* NET_21 */
579                         dev_kfree_skb(nskb, FREE_WRITE);
580 #endif /* NET_21 */
581
582                         return skb;
583                 }
584
585                 avail_out = pyldsz - rc;
586         } else {
587 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
588
589                 zs.next_out = (char *)iph + iphlen;
590                 zs.avail_out = pyldsz;
591
592                 zresult = inflate(&zs, Z_SYNC_FLUSH);
593
594                 /* work around a bug in zlib, which sometimes wants to taste an extra
595                  * byte when being used in the (undocumented) raw deflate mode.
596                  */
597                 if (zresult == Z_OK && !zs.avail_in && zs.avail_out) {
598                         __u8 zerostuff = 0;
599                 
600                         zs.next_in = &zerostuff;
601                         zs.avail_in = 1;
602                         zresult = inflate(&zs, Z_FINISH);
603                 }
604
605                 inflateEnd(&zs);
606                 if (zresult != Z_STREAM_END) {
607                         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
608                             "klips_error:skb_decompress: "
609                             "inflate() returned error %d (%s), "
610                             "skipping decompression.\n",
611                             zresult,
612                             zs.msg ? zs.msg : zError(zresult));
613                         *flags |= IPCOMP_DECOMPRESSIONERROR;
614 #ifdef NET_21
615                         kfree_skb(nskb);
616 #else /* NET_21 */
617                         dev_kfree_skb(nskb, FREE_WRITE);
618 #endif /* NET_21 */
619
620                         return skb;
621                 }
622
623                 avail_out = zs.avail_out;
624
625 #ifdef CONFIG_IPSEC_IPCOMP_LZS
626         }
627 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
628         
629         /* Update IP header */
630         /* resulting decompressed size */
631         pyldsz -= avail_out;
632         iph->tot_len = htons(iphlen + pyldsz);
633         iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh;
634
635         KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
636                     "klips_debug:skb_decompress: "
637                     "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n",
638                     tdb ? ntohl(tdb->tdb_said.spi) : 0,
639                     tdb ? ntohl(tdb->tdb_said.spi) & 0x0000ffff : 0,
640                     ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi),
641                     cpyldsz,
642                     pyldsz,
643                     iph->protocol);
644         
645 #if 1 /* XXX checksum is done by ipsec_rcv ? */
646         iph->check = 0;
647         iph->check = ip_fast_csum((char*) iph, iph->ihl);
648 #endif
649         
650         /* Update skb length/tail by "unputting" the unused data area */
651         skb_put(nskb, -avail_out);
652         
653 #ifdef NET_21
654         kfree_skb(skb);
655 #else /* NET_21 */
656         dev_kfree_skb(skb, FREE_WRITE);
657 #endif /* NET_21 */
658         
659         if (iph->protocol == IPPROTO_COMP)
660         {
661 #ifdef CONFIG_IPSEC_DEBUG
662                 if(sysctl_ipsec_debug_ipcomp)
663                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
664                             "klips_debug:skb_decompress: "
665                             "Eh? inner packet is also compressed, dropping.\n");
666 #endif /* CONFIG_IPSEC_DEBUG */
667                 
668 #ifdef NET_21
669                 kfree_skb(nskb);
670 #else /* NET_21 */
671                 dev_kfree_skb(nskb, FREE_WRITE);
672 #endif /* NET_21 */
673                 return NULL;
674         }
675         
676 #ifdef CONFIG_IPSEC_DEBUG
677         if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
678                 __u8 *c;
679                 int i;
680                 
681                 c = (__u8*)iph + iphlen;
682                 for(i = 0; i < pyldsz; i++, c++) {
683                         if(!(i % 16)) {
684                                 printk(KERN_INFO "skb_decompress:   result:");
685                         }
686                         printk("%02x ", *c);
687                         if(!((i + 1) % 16)) {
688                                 printk("\n");
689                         }
690                 }
691                 if(i % 16) {
692                         printk("\n");
693                 }
694         }
695 #endif /* CONFIG_IPSEC_DEBUG */
696         
697         return nskb;
698 }
699
700
701 /* this is derived from skb_copy() in linux 2.2.14 */
702 /* May be incompatible with other kernel versions!! */
703 static
704 struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask)
705 {
706         struct sk_buff *n;
707         struct iphdr *iph;
708         unsigned long offset;
709         unsigned int iphlen;
710         
711         if(!skb) {
712                 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
713                             "klips_debug:skb_copy_ipcomp: "
714                             "passed in NULL skb, returning NULL.\n");
715                 return NULL;
716         }
717
718         /*
719          *      Allocate the copy buffer
720          */
721         
722 #ifdef NET_21
723         iph = skb->nh.iph;
724 #else /* NET_21 */
725         iph = skb->ip_hdr;
726 #endif /* NET_21 */
727         if (!iph) return NULL;
728         iphlen = iph->ihl << 2;
729         
730         n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask);
731         if(n==NULL)
732                 return NULL;
733         
734         /*
735          *      Shift between the two data areas in bytes
736          */
737         
738         offset=n->head-skb->head;
739
740         /* Set the data pointer */
741         skb_reserve(n,skb->data-skb->head);
742         /* Set the tail pointer and length */
743         skb_put(n,skb->len+data_growth);
744         /* Copy the bytes up to and including the ip header */
745         memcpy(n->head,
746                skb->head,
747                ((char *)iph - (char *)skb->head) + iphlen);
748         n->list=NULL;
749         n->next=NULL;
750         n->prev=NULL;
751         n->sk=NULL;
752         n->dev=skb->dev;
753         if (skb->h.raw)
754                 n->h.raw=skb->h.raw+offset;
755         else
756                 n->h.raw=NULL;
757         n->protocol=skb->protocol;
758 #ifdef NET_21
759         n->csum = 0;
760         n->priority=skb->priority;
761         n->dst=dst_clone(skb->dst);
762         n->nh.raw=skb->nh.raw+offset;
763 #ifndef NETDEV_23
764         n->is_clone=0;
765 #endif /* NETDEV_23 */
766         atomic_set(&n->users, 1);
767         n->destructor = NULL;
768         n->security=skb->security;
769         memcpy(n->cb, skb->cb, sizeof(skb->cb));
770 #ifdef CONFIG_IP_FIREWALL
771         n->fwmark = skb->fwmark;
772 #endif
773 #else /* NET_21 */
774         n->link3=NULL;
775         n->when=skb->when;
776         n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
777         n->saddr=skb->saddr;
778         n->daddr=skb->daddr;
779         n->raddr=skb->raddr;
780         n->seq=skb->seq;
781         n->end_seq=skb->end_seq;
782         n->ack_seq=skb->ack_seq;
783         n->acked=skb->acked;
784         n->free=1;
785         n->arp=skb->arp;
786         n->tries=0;
787         n->lock=0;
788         n->users=0;
789         memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
790 #endif /* NET_21 */
791         if (skb->mac.raw)
792                 n->mac.raw=skb->mac.raw+offset;
793         else
794                 n->mac.raw=NULL;
795 #ifndef NETDEV_23
796         n->used=skb->used;
797 #endif /* !NETDEV_23 */
798         n->pkt_type=skb->pkt_type;
799 #ifndef NETDEV_23
800         n->pkt_bridged=skb->pkt_bridged;
801 #endif /* NETDEV_23 */
802         n->ip_summed=0;
803         n->stamp=skb->stamp;
804 #ifndef NETDEV_23 /* this seems to have been removed in 2.4 */
805 #if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
806         n->shapelatency=skb->shapelatency;       /* Latency on frame */
807         n->shapeclock=skb->shapeclock;           /* Time it should go out */
808         n->shapelen=skb->shapelen;               /* Frame length in clocks */
809         n->shapestamp=skb->shapestamp;           /* Stamp for shaper    */
810         n->shapepend=skb->shapepend;             /* Pending */
811 #endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */
812 #endif /* NETDEV_23 */
813 #ifdef CONFIG_HIPPI
814         n->private.ifield=skb->private.ifield;
815 #endif /* CONFIG_HIPPI */
816
817         return n;
818 }