summaryrefslogtreecommitdiff
path: root/linux/net/ipsec/ipcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/net/ipsec/ipcomp.c')
-rw-r--r--linux/net/ipsec/ipcomp.c725
1 files changed, 0 insertions, 725 deletions
diff --git a/linux/net/ipsec/ipcomp.c b/linux/net/ipsec/ipcomp.c
deleted file mode 100644
index ff12f2cdd..000000000
--- a/linux/net/ipsec/ipcomp.c
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * IPCOMP zlib interface code.
- * Copyright (C) 2000 Svenning Soerensen <svenning@post5.tele.dk>
- * Copyright (C) 2000, 2001 Richard Guy Briggs <rgb@conscoop.ottawa.on.ca>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.2 2004/06/13 19:57:49 as Exp $";
-
-/* SSS */
-
-#include <linux/config.h>
-#include <linux/version.h>
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/kernel.h> /* printk() */
-
-#include "freeswan/ipsec_param.h"
-
-#ifdef MALLOC_SLAB
-# include <linux/slab.h> /* kmalloc() */
-#else /* MALLOC_SLAB */
-# include <linux/malloc.h> /* kmalloc() */
-#endif /* MALLOC_SLAB */
-#include <linux/errno.h> /* error codes */
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-
-#include <linux/netdevice.h> /* struct device, and other headers */
-#include <linux/etherdevice.h> /* eth_type_trans */
-#include <linux/ip.h> /* struct iphdr */
-#include <linux/skbuff.h>
-
-#include <freeswan.h>
-
-#ifdef NET_21
-# include <net/dst.h>
-# include <asm/uaccess.h>
-# include <linux/in6.h>
-# define proto_priv cb
-#endif /* NET21 */
-#include <asm/checksum.h>
-#include <net/ip.h>
-
-#include "freeswan/radij.h"
-#include "freeswan/ipsec_encap.h"
-#include "freeswan/ipsec_sa.h"
-
-#include "freeswan/ipsec_xform.h"
-#include "freeswan/ipsec_tunnel.h"
-#include "freeswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */
-#include "freeswan/ipcomp.h"
-#include "zlib/zlib.h"
-#include "zlib/zutil.h"
-
-#include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */
-
-#ifdef CONFIG_IPSEC_DEBUG
-int sysctl_ipsec_debug_ipcomp = 0;
-#endif /* CONFIG_IPSEC_DEBUG */
-
-static
-struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask);
-
-static
-voidpf my_zcalloc(voidpf opaque, uInt items, uInt size)
-{
- return (voidpf) kmalloc(items*size, GFP_ATOMIC);
-}
-
-static
-void my_zfree(voidpf opaque, voidpf address)
-{
- kfree(address);
-}
-
-struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags)
-{
- struct iphdr *iph;
- unsigned int iphlen, pyldsz, cpyldsz;
- unsigned char *buffer;
- z_stream zs;
- int zresult;
-
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: .\n");
-
- if(skb == NULL) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "passed in NULL skb, returning ERROR.\n");
- if(flags != NULL) {
- *flags |= IPCOMP_PARMERROR;
- }
- return skb;
- }
-
- if(ips == NULL) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n");
- if(flags) {
- *flags |= IPCOMP_PARMERROR;
- }
- return skb;
- }
-
- if (flags == NULL) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "passed in NULL flags, returning ERROR.\n");
- ipsec_kfree_skb(skb);
- return NULL;
- }
-
-#ifdef NET_21
- iph = skb->nh.iph;
-#else /* NET_21 */
- iph = skb->ip_hdr;
-#endif /* NET_21 */
-
- switch (iph->protocol) {
- case IPPROTO_COMP:
- case IPPROTO_AH:
- case IPPROTO_ESP:
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "skipping compression of packet with ip protocol %d.\n",
- iph->protocol);
- *flags |= IPCOMP_UNCOMPRESSABLE;
- return skb;
- }
-
- /* Don't compress packets already fragmented */
- if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "skipping compression of fragmented packet.\n");
- *flags |= IPCOMP_UNCOMPRESSABLE;
- return skb;
- }
-
- iphlen = iph->ihl << 2;
- pyldsz = ntohs(iph->tot_len) - iphlen;
-
- /* Don't compress less than 90 bytes (rfc 2394) */
- if (pyldsz < 90) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "skipping compression of tiny packet, len=%d.\n",
- pyldsz);
- *flags |= IPCOMP_UNCOMPRESSABLE;
- return skb;
- }
-
- /* Adaptive decision */
- if (ips->ips_comp_adapt_skip) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "skipping compression: ips_comp_adapt_skip=%d.\n",
- ips->ips_comp_adapt_skip);
- ips->ips_comp_adapt_skip--;
- *flags |= IPCOMP_UNCOMPRESSABLE;
- return skb;
- }
-
- zs.zalloc = my_zcalloc;
- zs.zfree = my_zfree;
- zs.opaque = 0;
-
- /* We want to use deflateInit2 because we don't want the adler
- header. */
- zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11,
- DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
- if (zresult != Z_OK) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_compress: "
- "deflateInit2() returned error %d (%s), "
- "skipping compression.\n",
- zresult,
- zs.msg ? zs.msg : zError(zresult));
- *flags |= IPCOMP_COMPRESSIONERROR;
- return skb;
- }
-
-
- /* Max output size. Result should be max this size.
- * Implementation specific tweak:
- * If it's not at least 32 bytes and 6.25% smaller than
- * the original packet, it's probably not worth wasting
- * the receiver's CPU cycles decompressing it.
- * Your mileage may vary.
- */
- cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4);
-
- buffer = kmalloc(cpyldsz, GFP_ATOMIC);
- if (!buffer) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_compress: "
- "unable to kmalloc(%d, GFP_ATOMIC), "
- "skipping compression.\n",
- cpyldsz);
- *flags |= IPCOMP_COMPRESSIONERROR;
- deflateEnd(&zs);
- return skb;
- }
-
-#ifdef CONFIG_IPSEC_DEBUG
- if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
- __u8 *c;
- int i;
-
- c = (__u8*)iph + iphlen;
- for(i = 0; i < pyldsz; i++, c++) {
- if(!(i % 16)) {
- printk(KERN_INFO "skb_compress: before:");
- }
- printk("%02x ", *c);
- if(!((i + 1) % 16)) {
- printk("\n");
- }
- }
- if(i % 16) {
- printk("\n");
- }
- }
-#endif /* CONFIG_IPSEC_DEBUG */
-
- zs.next_in = (char *) iph + iphlen; /* start of payload */
- zs.avail_in = pyldsz;
- zs.next_out = buffer; /* start of compressed payload */
- zs.avail_out = cpyldsz;
-
- /* Finish compression in one step */
- zresult = deflate(&zs, Z_FINISH);
-
- /* Free all dynamically allocated buffers */
- deflateEnd(&zs);
- if (zresult != Z_STREAM_END) {
- *flags |= IPCOMP_UNCOMPRESSABLE;
- kfree(buffer);
-
- /* Adjust adaptive counters */
- if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "first %d packets didn't compress, "
- "skipping next %d\n",
- IPCOMP_ADAPT_INITIAL_TRIES,
- IPCOMP_ADAPT_INITIAL_SKIP);
- ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP;
- }
- else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "next %d packets didn't compress, "
- "skipping next %d\n",
- IPCOMP_ADAPT_SUBSEQ_TRIES,
- IPCOMP_ADAPT_SUBSEQ_SKIP);
- ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP;
- ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES;
- }
-
- return skb;
- }
-
- /* resulting compressed size */
- cpyldsz -= zs.avail_out;
-
- /* Insert IPCOMP header */
- ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol;
- ((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0;
- /* use the bottom 16 bits of the spi for the cpi. The top 16 bits are
- for internal reference only. */
- ((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff));
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_compress: "
- "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n",
- ntohl(ips->ips_said.spi),
- ntohl(ips->ips_said.spi) & 0x0000ffff,
- ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi),
- pyldsz,
- cpyldsz);
-
- /* Update IP header */
- iph->protocol = IPPROTO_COMP;
- iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz);
-#if 1 /* XXX checksum is done by ipsec_tunnel ? */
- iph->check = 0;
- iph->check = ip_fast_csum((char *) iph, iph->ihl);
-#endif
-
- /* Copy compressed payload */
- memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr),
- buffer,
- cpyldsz);
- kfree(buffer);
-
- /* Update skb length/tail by "unputting" the shrinkage */
- skb_put(skb,
- cpyldsz + sizeof(struct ipcomphdr) - pyldsz);
-
-#ifdef CONFIG_IPSEC_DEBUG
- if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
- __u8 *c;
- int i;
-
- c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr);
- for(i = 0; i < cpyldsz; i++, c++) {
- if(!(i % 16)) {
- printk(KERN_INFO "skb_compress: result:");
- }
- printk("%02x ", *c);
- if(!((i + 1) % 16)) {
- printk("\n");
- }
- }
- if(i % 16) {
- printk("\n");
- }
- }
-#endif /* CONFIG_IPSEC_DEBUG */
-
- ips->ips_comp_adapt_skip = 0;
- ips->ips_comp_adapt_tries = 0;
-
- return skb;
-}
-
-struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags)
-{
- struct sk_buff *nskb = NULL;
-
- /* original ip header */
- struct iphdr *oiph, *iph;
- unsigned int iphlen, pyldsz, cpyldsz;
- z_stream zs;
- int zresult;
-
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_decompress: .\n");
-
- if(!skb) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "passed in NULL skb, returning ERROR.\n");
- if (flags) *flags |= IPCOMP_PARMERROR;
- return skb;
- }
-
- if(!ips && sysctl_ipsec_inbound_policy_check) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "passed in NULL ipsec_sa needed for comp alg, returning ERROR.\n");
- if (flags) *flags |= IPCOMP_PARMERROR;
- return skb;
- }
-
- if (!flags) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "passed in NULL flags, returning ERROR.\n");
- ipsec_kfree_skb(skb);
- return NULL;
- }
-
-#ifdef NET_21
- oiph = skb->nh.iph;
-#else /* NET_21 */
- oiph = skb->ip_hdr;
-#endif /* NET_21 */
-
- iphlen = oiph->ihl << 2;
-
- if (oiph->protocol != IPPROTO_COMP) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "called with non-IPCOMP packet (protocol=%d),"
- "skipping decompression.\n",
- oiph->protocol);
- *flags |= IPCOMP_PARMERROR;
- return skb;
- }
-
- if ( (((struct ipcomphdr*)((char*) oiph + iphlen))->ipcomp_flags != 0)
- || ((((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi
- != htons(SADB_X_CALG_DEFLATE))
- && sysctl_ipsec_inbound_policy_check
- && (!ips || (ips && (ips->ips_encalg != SADB_X_CALG_DEFLATE)))) ) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "called with incompatible IPCOMP packet (flags=%d, "
- "cpi=%d), ips-compalg=%d, skipping decompression.\n",
- ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_flags),
- ntohs(((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_cpi),
- ips ? ips->ips_encalg : 0);
- *flags |= IPCOMP_PARMERROR;
-
- return skb;
- }
-
- if (ntohs(oiph->frag_off) & ~0x4000) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "called with fragmented IPCOMP packet, "
- "skipping decompression.\n");
- *flags |= IPCOMP_PARMERROR;
- return skb;
- }
-
- /* original compressed payload size */
- cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr);
-
- zs.zalloc = my_zcalloc;
- zs.zfree = my_zfree;
- zs.opaque = 0;
-
- zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
- zs.avail_in = cpyldsz;
-
- /* Maybe we should be a bit conservative about memory
- requirements and use inflateInit2 */
- /* Beware, that this might make us unable to decompress packets
- from other implementations - HINT: check PGPnet source code */
- /* We want to use inflateInit2 because we don't want the adler
- header. */
- zresult = inflateInit2(&zs, -15);
- if (zresult != Z_OK) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "inflateInit2() returned error %d (%s), "
- "skipping decompression.\n",
- zresult,
- zs.msg ? zs.msg : zError(zresult));
- *flags |= IPCOMP_DECOMPRESSIONERROR;
-
- return skb;
- }
-
- /* We have no way of knowing the exact length of the resulting
- decompressed output before we have actually done the decompression.
- For now, we guess that the packet will not be bigger than the
- attached ipsec device's mtu or 16260, whichever is biggest.
- This may be wrong, since the sender's mtu may be bigger yet.
- XXX This must be dealt with later XXX
- */
-
- /* max payload size */
- pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu)
- : (65520 - iphlen);
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_decompress: "
- "max payload size: %d\n", pyldsz);
-
- while (pyldsz > (cpyldsz + sizeof(struct ipcomphdr)) &&
- (nskb = skb_copy_ipcomp(skb,
- pyldsz - cpyldsz - sizeof(struct ipcomphdr),
- GFP_ATOMIC)) == NULL) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "unable to skb_copy_ipcomp(skb, %d, GFP_ATOMIC), "
- "trying with less payload size.\n",
- (int)(pyldsz - cpyldsz - sizeof(struct ipcomphdr)));
- pyldsz >>=1;
- }
-
- if (!nskb) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "unable to allocate memory, dropping packet.\n");
- *flags |= IPCOMP_DECOMPRESSIONERROR;
- inflateEnd(&zs);
-
- return skb;
- }
-
-#ifdef CONFIG_IPSEC_DEBUG
- if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
- __u8 *c;
- int i;
-
- c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr);
- for(i = 0; i < cpyldsz; i++, c++) {
- if(!(i % 16)) {
- printk(KERN_INFO "skb_decompress: before:");
- }
- printk("%02x ", *c);
- if(!((i + 1) % 16)) {
- printk("\n");
- }
- }
- if(i % 16) {
- printk("\n");
- }
- }
-#endif /* CONFIG_IPSEC_DEBUG */
-
-#ifdef NET_21
- iph = nskb->nh.iph;
-#else /* NET_21 */
- iph = nskb->ip_hdr;
-#endif /* NET_21 */
- zs.next_out = (char *)iph + iphlen;
- zs.avail_out = pyldsz;
-
- zresult = inflate(&zs, Z_SYNC_FLUSH);
-
- /* work around a bug in zlib, which sometimes wants to taste an extra
- * byte when being used in the (undocumented) raw deflate mode.
- */
- if (zresult == Z_OK && !zs.avail_in && zs.avail_out) {
- __u8 zerostuff = 0;
-
- zs.next_in = &zerostuff;
- zs.avail_in = 1;
- zresult = inflate(&zs, Z_FINISH);
- }
-
- inflateEnd(&zs);
- if (zresult != Z_STREAM_END) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_error:skb_decompress: "
- "inflate() returned error %d (%s), "
- "skipping decompression.\n",
- zresult,
- zs.msg ? zs.msg : zError(zresult));
- *flags |= IPCOMP_DECOMPRESSIONERROR;
- ipsec_kfree_skb(nskb);
-
- return skb;
- }
-
- /* Update IP header */
- /* resulting decompressed size */
- pyldsz -= zs.avail_out;
- iph->tot_len = htons(iphlen + pyldsz);
- iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh;
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_decompress: "
- "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: comp=%d, raw=%d, nh=%d.\n",
- ips ? ntohl(ips->ips_said.spi) : 0,
- ips ? ntohl(ips->ips_said.spi) & 0x0000ffff : 0,
- ntohs(((struct ipcomphdr*)(((char*)oiph)+iphlen))->ipcomp_cpi),
- cpyldsz,
- pyldsz,
- iph->protocol);
-
-#if 1 /* XXX checksum is done by ipsec_rcv ? */
- iph->check = 0;
- iph->check = ip_fast_csum((char*) iph, iph->ihl);
-#endif
-
- /* Update skb length/tail by "unputting" the unused data area */
- skb_put(nskb, -zs.avail_out);
-
- ipsec_kfree_skb(skb);
-
- if (iph->protocol == IPPROTO_COMP)
- {
-#ifdef CONFIG_IPSEC_DEBUG
- if(sysctl_ipsec_debug_ipcomp)
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_decompress: "
- "Eh? inner packet is also compressed, dropping.\n");
-#endif /* CONFIG_IPSEC_DEBUG */
-
- ipsec_kfree_skb(nskb);
- return NULL;
- }
-
-#ifdef CONFIG_IPSEC_DEBUG
- if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
- __u8 *c;
- int i;
-
- c = (__u8*)iph + iphlen;
- for(i = 0; i < pyldsz; i++, c++) {
- if(!(i % 16)) {
- printk(KERN_INFO "skb_decompress: result:");
- }
- printk("%02x ", *c);
- if(!((i + 1) % 16)) {
- printk("\n");
- }
- }
- if(i % 16) {
- printk("\n");
- }
- }
-#endif /* CONFIG_IPSEC_DEBUG */
-
- return nskb;
-}
-
-
-/* this is derived from skb_copy() in linux 2.2.14 */
-/* May be incompatible with other kernel versions!! */
-static
-struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask)
-{
- struct sk_buff *n;
- struct iphdr *iph;
- unsigned long offset;
- unsigned int iphlen;
-
- if(!skb) {
- KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
- "klips_debug:skb_copy_ipcomp: "
- "passed in NULL skb, returning NULL.\n");
- return NULL;
- }
-
- /*
- * Allocate the copy buffer
- */
-
-#ifdef NET_21
- iph = skb->nh.iph;
-#else /* NET_21 */
- iph = skb->ip_hdr;
-#endif /* NET_21 */
- if (!iph) return NULL;
- iphlen = iph->ihl << 2;
-
- n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask);
- if(n==NULL)
- return NULL;
-
- /*
- * Shift between the two data areas in bytes
- */
-
- offset=n->head-skb->head;
-
- /* Set the data pointer */
- skb_reserve(n,skb->data-skb->head);
- /* Set the tail pointer and length */
- skb_put(n,skb->len+data_growth);
- /* Copy the bytes up to and including the ip header */
- memcpy(n->head,
- skb->head,
- ((char *)iph - (char *)skb->head) + iphlen);
- n->list=NULL;
- n->next=NULL;
- n->prev=NULL;
- n->sk=NULL;
- n->dev=skb->dev;
- if (skb->h.raw)
- n->h.raw=skb->h.raw+offset;
- else
- n->h.raw=NULL;
- n->protocol=skb->protocol;
-#ifdef NET_21
- n->csum = 0;
- n->priority=skb->priority;
- n->dst=dst_clone(skb->dst);
- n->nh.raw=skb->nh.raw+offset;
-#ifndef NETDEV_23
- n->is_clone=0;
-#endif /* NETDEV_23 */
- atomic_set(&n->users, 1);
- n->destructor = NULL;
- n->security=skb->security;
- memcpy(n->cb, skb->cb, sizeof(skb->cb));
-#ifdef CONFIG_IP_FIREWALL
- n->fwmark = skb->fwmark;
-#endif
-#else /* NET_21 */
- n->link3=NULL;
- n->when=skb->when;
- n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
- n->saddr=skb->saddr;
- n->daddr=skb->daddr;
- n->raddr=skb->raddr;
- n->seq=skb->seq;
- n->end_seq=skb->end_seq;
- n->ack_seq=skb->ack_seq;
- n->acked=skb->acked;
- n->free=1;
- n->arp=skb->arp;
- n->tries=0;
- n->lock=0;
- n->users=0;
- memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
-#endif /* NET_21 */
- if (skb->mac.raw)
- n->mac.raw=skb->mac.raw+offset;
- else
- n->mac.raw=NULL;
-#ifndef NETDEV_23
- n->used=skb->used;
-#endif /* !NETDEV_23 */
- n->pkt_type=skb->pkt_type;
-#ifndef NETDEV_23
- n->pkt_bridged=skb->pkt_bridged;
-#endif /* NETDEV_23 */
- n->ip_summed=0;
- n->stamp=skb->stamp;
-#ifndef NETDEV_23 /* this seems to have been removed in 2.4 */
-#if defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
- n->shapelatency=skb->shapelatency; /* Latency on frame */
- n->shapeclock=skb->shapeclock; /* Time it should go out */
- n->shapelen=skb->shapelen; /* Frame length in clocks */
- n->shapestamp=skb->shapestamp; /* Stamp for shaper */
- n->shapepend=skb->shapepend; /* Pending */
-#endif /* defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) */
-#endif /* NETDEV_23 */
-#ifdef CONFIG_HIPPI
- n->private.ifield=skb->private.ifield;
-#endif /* CONFIG_HIPPI */
-
- return n;
-}