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>
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>.
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
17 char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.28 2002/01/29 17:17:54 mcr Exp $";
21 #include <linux/config.h>
22 #include <linux/version.h>
24 #define __NO_VERSION__
25 #include <linux/module.h>
26 #include <linux/kernel.h> /* printk() */
28 #define IPSEC_KLIPS1_COMPAT
29 #include "ipsec_param.h"
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>
40 #include <linux/skbuff.h>
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>
50 # include <asm/uaccess.h>
51 # include <linux/in6.h>
52 # define proto_priv cb
54 #include <asm/checksum.h>
58 #include "ipsec_encap.h"
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 */
66 #include "zlib/zlib.h"
67 #include "zlib/zutil.h"
69 #include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */
71 #ifdef CONFIG_IPSEC_DEBUG
72 int sysctl_ipsec_debug_ipcomp = 0;
73 #endif /* CONFIG_IPSEC_DEBUG */
75 #ifdef CONFIG_IPSEC_IPCOMP_LZS
77 * Allow for both hardware and software driven lzs compressors.
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);
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))
95 struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask);
98 voidpf my_zcalloc(voidpf opaque, uInt items, uInt size)
100 return (voidpf) kmalloc(items*size, GFP_ATOMIC);
104 void my_zfree(voidpf opaque, voidpf address)
109 struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags)
112 unsigned int iphlen, pyldsz, cpyldsz;
113 unsigned char *buffer;
117 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
118 "klips_debug:skb_compress: .\n");
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;
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;
137 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
138 "klips_debug:skb_compress: "
139 "passed in NULL flags, returning ERROR.\n");
143 dev_kfree_skb(skb, FREE_WRITE);
154 switch (iph->protocol) {
158 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
159 "klips_debug:skb_compress: "
160 "skipping compression of packet with ip protocol %d.\n",
162 *flags |= IPCOMP_UNCOMPRESSABLE;
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;
175 iphlen = iph->ihl << 2;
176 pyldsz = ntohs(iph->tot_len) - iphlen;
178 /* Don't compress less than 90 bytes (rfc 2394) */
180 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
181 "klips_debug:skb_compress: "
182 "skipping compression of tiny packet, len=%d.\n",
184 *flags |= IPCOMP_UNCOMPRESSABLE;
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;
199 if (tdb->tdb_encalg != SADB_X_CALG_LZS) {
200 zs.zalloc = my_zcalloc;
204 /* We want to use deflateInit2 because we don't want the adler
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",
214 zs.msg ? zs.msg : zError(zresult));
215 *flags |= IPCOMP_COMPRESSIONERROR;
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.
227 cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4);
229 buffer = kmalloc(cpyldsz, GFP_ATOMIC);
231 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
232 "klips_error:skb_compress: "
233 "unable to kmalloc(%d, GFP_ATOMIC), "
234 "skipping compression.\n",
236 *flags |= IPCOMP_COMPRESSIONERROR;
241 #ifdef CONFIG_IPSEC_DEBUG
242 if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
246 c = (__u8*)iph + iphlen;
247 for(i = 0; i < pyldsz; i++, c++) {
249 printk(KERN_INFO "skb_compress: before:");
252 if(!((i + 1) % 16)) {
260 #endif /* CONFIG_IPSEC_DEBUG */
262 #ifdef CONFIG_IPSEC_IPCOMP_LZS
263 if (tdb->tdb_encalg == SADB_X_CALG_LZS) {
267 inbuf = (char *) iph + iphlen; /* start of payload */
268 if ((rc = _lzs_compress(inbuf, pyldsz, buffer, cpyldsz)) < 0)
272 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
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;
279 /* Finish compression in one step */
280 zresult = deflate(&zs, Z_FINISH);
282 /* Free all dynamically allocated buffers */
284 if (zresult != Z_STREAM_END) {
286 *flags |= IPCOMP_UNCOMPRESSABLE;
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;
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;
313 /* resulting compressed size */
314 cpyldsz -= zs.avail_out;
316 #ifdef CONFIG_IPSEC_IPCOMP_LZS
318 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
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),
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 ? */
340 iph->check = ip_fast_csum((char *) iph, iph->ihl);
343 /* Copy compressed payload */
344 memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr),
349 /* Update skb length/tail by "unputting" the shrinkage */
351 cpyldsz + sizeof(struct ipcomphdr) - pyldsz);
353 #ifdef CONFIG_IPSEC_DEBUG
354 if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
358 c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr);
359 for(i = 0; i < cpyldsz; i++, c++) {
361 printk(KERN_INFO "skb_compress: result:");
364 if(!((i + 1) % 16)) {
372 #endif /* CONFIG_IPSEC_DEBUG */
374 tdb->tdb_comp_adapt_skip = 0;
375 tdb->tdb_comp_adapt_tries = 0;
380 struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *tdb, unsigned int *flags)
382 struct sk_buff *nskb = NULL;
384 /* original ip header */
385 struct iphdr *oiph, *iph;
386 unsigned int iphlen, pyldsz, cpyldsz, avail_out;
390 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
391 "klips_debug:skb_decompress: .\n");
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;
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;
410 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
411 "klips_error:skb_decompress: "
412 "passed in NULL flags, returning ERROR.\n");
416 dev_kfree_skb(skb, FREE_WRITE);
427 iphlen = oiph->ihl << 2;
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",
435 *flags |= IPCOMP_PARMERROR;
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
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;
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;
467 /* original compressed payload size */
468 cpyldsz = ntohs(oiph->tot_len) - iphlen - sizeof(struct ipcomphdr);
470 if (tdb->tdb_encalg != SADB_X_CALG_LZS) {
471 zs.zalloc = my_zcalloc;
475 zs.next_in = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
476 zs.avail_in = cpyldsz;
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
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",
491 zs.msg ? zs.msg : zError(zresult));
492 *flags |= IPCOMP_DECOMPRESSIONERROR;
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
506 /* max payload size */
507 pyldsz = skb->dev ? (skb->dev->mtu < 16260 ? 16260 : skb->dev->mtu)
509 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
510 "klips_debug:skb_decompress: "
511 "max payload size: %d\n", pyldsz);
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));
526 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
527 "klips_error:skb_decompress: "
528 "unable to allocate memory, dropping packet.\n");
529 *flags |= IPCOMP_DECOMPRESSIONERROR;
535 #ifdef CONFIG_IPSEC_DEBUG
536 if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
540 c = (__u8*)oiph + iphlen + sizeof(struct ipcomphdr);
541 for(i = 0; i < cpyldsz; i++, c++) {
543 printk(KERN_INFO "skb_decompress: before:");
546 if(!((i + 1) % 16)) {
554 #endif /* CONFIG_IPSEC_DEBUG */
562 #ifdef CONFIG_IPSEC_IPCOMP_LZS
563 if (tdb->tdb_encalg == SADB_X_CALG_LZS) {
564 void *inbuf, *outbuf;
567 inbuf = (char *) oiph + iphlen + sizeof(struct ipcomphdr);
568 outbuf = (char *)iph + iphlen;
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;
579 dev_kfree_skb(nskb, FREE_WRITE);
585 avail_out = pyldsz - rc;
587 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
589 zs.next_out = (char *)iph + iphlen;
590 zs.avail_out = pyldsz;
592 zresult = inflate(&zs, Z_SYNC_FLUSH);
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.
597 if (zresult == Z_OK && !zs.avail_in && zs.avail_out) {
600 zs.next_in = &zerostuff;
602 zresult = inflate(&zs, Z_FINISH);
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",
612 zs.msg ? zs.msg : zError(zresult));
613 *flags |= IPCOMP_DECOMPRESSIONERROR;
617 dev_kfree_skb(nskb, FREE_WRITE);
623 avail_out = zs.avail_out;
625 #ifdef CONFIG_IPSEC_IPCOMP_LZS
627 #endif /* CONFIG_IPSEC_IPCOMP_LZS */
629 /* Update IP header */
630 /* resulting decompressed size */
632 iph->tot_len = htons(iphlen + pyldsz);
633 iph->protocol = ((struct ipcomphdr*) ((char*) oiph + iphlen))->ipcomp_nh;
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),
645 #if 1 /* XXX checksum is done by ipsec_rcv ? */
647 iph->check = ip_fast_csum((char*) iph, iph->ihl);
650 /* Update skb length/tail by "unputting" the unused data area */
651 skb_put(nskb, -avail_out);
656 dev_kfree_skb(skb, FREE_WRITE);
659 if (iph->protocol == IPPROTO_COMP)
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 */
671 dev_kfree_skb(nskb, FREE_WRITE);
676 #ifdef CONFIG_IPSEC_DEBUG
677 if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {
681 c = (__u8*)iph + iphlen;
682 for(i = 0; i < pyldsz; i++, c++) {
684 printk(KERN_INFO "skb_decompress: result:");
687 if(!((i + 1) % 16)) {
695 #endif /* CONFIG_IPSEC_DEBUG */
701 /* this is derived from skb_copy() in linux 2.2.14 */
702 /* May be incompatible with other kernel versions!! */
704 struct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask)
708 unsigned long offset;
712 KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,
713 "klips_debug:skb_copy_ipcomp: "
714 "passed in NULL skb, returning NULL.\n");
719 * Allocate the copy buffer
727 if (!iph) return NULL;
728 iphlen = iph->ihl << 2;
730 n=alloc_skb(skb->end - skb->head + data_growth, gfp_mask);
735 * Shift between the two data areas in bytes
738 offset=n->head-skb->head;
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 */
747 ((char *)iph - (char *)skb->head) + iphlen);
754 n->h.raw=skb->h.raw+offset;
757 n->protocol=skb->protocol;
760 n->priority=skb->priority;
761 n->dst=dst_clone(skb->dst);
762 n->nh.raw=skb->nh.raw+offset;
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;
776 n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);
781 n->end_seq=skb->end_seq;
782 n->ack_seq=skb->ack_seq;
789 memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
792 n->mac.raw=skb->mac.raw+offset;
797 #endif /* !NETDEV_23 */
798 n->pkt_type=skb->pkt_type;
800 n->pkt_bridged=skb->pkt_bridged;
801 #endif /* NETDEV_23 */
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 */
814 n->private.ifield=skb->private.ifield;
815 #endif /* CONFIG_HIPPI */