]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/ppp_deflate.c
xnu-1699.26.8.tar.gz
[apple/xnu.git] / bsd / net / ppp_deflate.c
CommitLineData
1c79356b 1/*
6d2010ae 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * ppp_deflate.c - interface the zlib procedures for Deflate compression
30 * and decompression (as used by gzip) to the PPP code.
31 * This version is for use with mbufs on BSD-derived systems.
32 *
33 * Copyright (c) 1994 The Australian National University.
34 * All rights reserved.
35 *
36 * Permission to use, copy, modify, and distribute this software and its
37 * documentation is hereby granted, provided that the above copyright
38 * notice appears in all copies. This software is provided without any
39 * warranty, express or implied. The Australian National University
40 * makes no representations about the suitability of this software for
41 * any purpose.
42 *
43 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
44 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
45 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
46 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
47 * OF SUCH DAMAGE.
48 *
49 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
50 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
51 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
52 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
53 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
54 * OR MODIFICATIONS.
55 */
2d21ac55
A
56/*
57 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
58 * support for mandatory and extensible security protections. This notice
59 * is included in support of clause 2.2 (b) of the Apple Public License,
60 * Version 2.0.
61 */
1c79356b
A
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/malloc.h>
66#include <sys/mbuf.h>
67#include <net/ppp_defs.h>
2d21ac55 68#include <libkern/zlib.h>
1c79356b
A
69
70#define PACKETPTR struct mbuf *
71#include <net/ppp_comp.h>
72
2d21ac55
A
73#if CONFIG_MACF_NET
74#include <security/mac_framework.h>
75#endif
76
1c79356b
A
77#if DO_DEFLATE
78
79#define DEFLATE_DEBUG 1
80
81/*
82 * State for a Deflate (de)compressor.
83 */
84struct deflate_state {
85 int seqno;
86 int w_size;
87 int unit;
88 int hdrlen;
89 int mru;
90 int debug;
91 z_stream strm;
92 struct compstat stats;
93};
94
95#define DEFLATE_OVHD 2 /* Deflate overhead/packet */
96
91447636
A
97static void *z_alloc(void *, u_int items, u_int size);
98static void z_free(void *, void *ptr);
99static void *z_comp_alloc(u_char *options, int opt_len);
100static void *z_decomp_alloc(u_char *options, int opt_len);
101static void z_comp_free(void *state);
102static void z_decomp_free(void *state);
103static int z_comp_init(void *state, u_char *options, int opt_len,
104 int unit, int hdrlen, int debug);
105static int z_decomp_init(void *state, u_char *options, int opt_len,
106 int unit, int hdrlen, int mru, int debug);
107static int z_compress(void *state, struct mbuf **mret,
108 struct mbuf *mp, int slen, int maxolen);
109static void z_incomp(void *state, struct mbuf *dmsg);
110static int z_decompress(void *state, struct mbuf *cmp, struct mbuf **dmpp);
111static void z_comp_reset(void *state);
112static void z_decomp_reset(void *state);
113static void z_comp_stats(void *state, struct compstat *stats);
1c79356b
A
114
115/*
116 * Procedures exported to if_ppp.c.
117 */
118struct compressor ppp_deflate = {
119 CI_DEFLATE, /* compress_proto */
120 z_comp_alloc, /* comp_alloc */
121 z_comp_free, /* comp_free */
122 z_comp_init, /* comp_init */
123 z_comp_reset, /* comp_reset */
124 z_compress, /* compress */
125 z_comp_stats, /* comp_stat */
126 z_decomp_alloc, /* decomp_alloc */
127 z_decomp_free, /* decomp_free */
128 z_decomp_init, /* decomp_init */
129 z_decomp_reset, /* decomp_reset */
130 z_decompress, /* decompress */
131 z_incomp, /* incomp */
132 z_comp_stats, /* decomp_stat */
133};
134
135struct compressor ppp_deflate_draft = {
136 CI_DEFLATE_DRAFT, /* compress_proto */
137 z_comp_alloc, /* comp_alloc */
138 z_comp_free, /* comp_free */
139 z_comp_init, /* comp_init */
140 z_comp_reset, /* comp_reset */
141 z_compress, /* compress */
142 z_comp_stats, /* comp_stat */
143 z_decomp_alloc, /* decomp_alloc */
144 z_decomp_free, /* decomp_free */
145 z_decomp_init, /* decomp_init */
146 z_decomp_reset, /* decomp_reset */
147 z_decompress, /* decompress */
148 z_incomp, /* incomp */
149 z_comp_stats, /* decomp_stat */
150};
151
152/*
153 * Space allocation and freeing routines for use by zlib routines.
154 */
155void *
156z_alloc(notused, items, size)
157 void *notused;
158 u_int items, size;
159{
160 void *ptr;
161
162 MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT);
163 return ptr;
164}
165
166void
167z_free(notused, ptr)
168 void *notused;
169 void *ptr;
170{
171 FREE(ptr, M_DEVBUF);
172}
173
174/*
175 * Allocate space for a compressor.
176 */
177static void *
178z_comp_alloc(options, opt_len)
179 u_char *options;
180 int opt_len;
181{
182 struct deflate_state *state;
183 int w_size;
184
185 if (opt_len != CILEN_DEFLATE
186 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
187 || options[1] != CILEN_DEFLATE
188 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
189 || options[3] != DEFLATE_CHK_SEQUENCE)
190 return NULL;
191 w_size = DEFLATE_SIZE(options[2]);
192 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
193 return NULL;
194
195 MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
196 M_DEVBUF, M_NOWAIT);
197 if (state == NULL)
198 return NULL;
199
200 state->strm.next_in = NULL;
201 state->strm.zalloc = z_alloc;
202 state->strm.zfree = z_free;
203 if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
204 -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
205 FREE(state, M_DEVBUF);
206 return NULL;
207 }
208
209 state->w_size = w_size;
210 bzero(&state->stats, sizeof(state->stats));
211 return (void *) state;
212}
213
214static void
215z_comp_free(arg)
216 void *arg;
217{
218 struct deflate_state *state = (struct deflate_state *) arg;
219
220 deflateEnd(&state->strm);
221 FREE(state, M_DEVBUF);
222}
223
224static int
225z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
226 void *arg;
227 u_char *options;
228 int opt_len, unit, hdrlen, debug;
229{
230 struct deflate_state *state = (struct deflate_state *) arg;
231
232 if (opt_len < CILEN_DEFLATE
233 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
234 || options[1] != CILEN_DEFLATE
235 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
236 || DEFLATE_SIZE(options[2]) != state->w_size
237 || options[3] != DEFLATE_CHK_SEQUENCE)
238 return 0;
239
240 state->seqno = 0;
241 state->unit = unit;
242 state->hdrlen = hdrlen;
243 state->debug = debug;
244
245 deflateReset(&state->strm);
246
247 return 1;
248}
249
250static void
251z_comp_reset(arg)
252 void *arg;
253{
254 struct deflate_state *state = (struct deflate_state *) arg;
255
256 state->seqno = 0;
257 deflateReset(&state->strm);
258}
259
260int
261z_compress(arg, mret, mp, orig_len, maxolen)
262 void *arg;
263 struct mbuf **mret; /* compressed packet (out) */
264 struct mbuf *mp; /* uncompressed packet (in) */
265 int orig_len, maxolen;
266{
267 struct deflate_state *state = (struct deflate_state *) arg;
268 u_char *rptr, *wptr;
269 int proto, olen, wspace, r, flush;
270 struct mbuf *m;
271
272 /*
273 * Check that the protocol is in the range we handle.
274 */
275 rptr = mtod(mp, u_char *);
276 proto = PPP_PROTOCOL(rptr);
277 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
278 *mret = NULL;
279 return orig_len;
280 }
281
282 /* Allocate one mbuf initially. */
283 if (maxolen > orig_len)
284 maxolen = orig_len;
285 MGET(m, M_DONTWAIT, MT_DATA);
286 *mret = m;
287 if (m != NULL) {
288 m->m_len = 0;
289 if (maxolen + state->hdrlen > MLEN)
290 MCLGET(m, M_DONTWAIT);
291 wspace = M_TRAILINGSPACE(m);
292 if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
293 m->m_data += state->hdrlen;
294 wspace -= state->hdrlen;
295 }
296 wptr = mtod(m, u_char *);
297
298 /*
299 * Copy over the PPP header and store the 2-byte sequence number.
300 */
301 wptr[0] = PPP_ADDRESS(rptr);
302 wptr[1] = PPP_CONTROL(rptr);
303 wptr[2] = PPP_COMP >> 8;
304 wptr[3] = PPP_COMP;
305 wptr += PPP_HDRLEN;
306 wptr[0] = state->seqno >> 8;
307 wptr[1] = state->seqno;
308 wptr += 2;
309 state->strm.next_out = wptr;
310 state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
311 } else {
312 state->strm.next_out = NULL;
313 state->strm.avail_out = 1000000;
314 wptr = NULL;
315 wspace = 0;
316 }
317 ++state->seqno;
318
6d2010ae 319 rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */
1c79356b
A
320 state->strm.next_in = rptr;
321 state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
322 mp = mp->m_next;
323 flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
324 olen = 0;
325 for (;;) {
326 r = deflate(&state->strm, flush);
327 if (r != Z_OK) {
328 printf("z_compress: deflate returned %d (%s)\n",
329 r, (state->strm.msg? state->strm.msg: ""));
330 break;
331 }
332 if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
333 break; /* all done */
334 if (state->strm.avail_in == 0 && mp != NULL) {
335 state->strm.next_in = mtod(mp, u_char *);
336 state->strm.avail_in = mp->m_len;
337 mp = mp->m_next;
338 if (mp == NULL)
339 flush = Z_PACKET_FLUSH;
340 }
341 if (state->strm.avail_out == 0) {
342 if (m != NULL) {
343 m->m_len = wspace;
344 olen += wspace;
345 MGET(m->m_next, M_DONTWAIT, MT_DATA);
346 m = m->m_next;
347 if (m != NULL) {
348 m->m_len = 0;
349 if (maxolen - olen > MLEN)
350 MCLGET(m, M_DONTWAIT);
351 state->strm.next_out = mtod(m, u_char *);
352 state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
353 }
354 }
355 if (m == NULL) {
356 state->strm.next_out = NULL;
357 state->strm.avail_out = 1000000;
358 }
359 }
360 }
361 if (m != NULL)
362 olen += (m->m_len = wspace - state->strm.avail_out);
363
364 /*
365 * See if we managed to reduce the size of the packet.
366 */
367 if (m != NULL && olen < orig_len) {
368 state->stats.comp_bytes += olen;
369 state->stats.comp_packets++;
370 } else {
371 if (*mret != NULL) {
372 m_freem(*mret);
373 *mret = NULL;
374 }
375 state->stats.inc_bytes += orig_len;
376 state->stats.inc_packets++;
377 olen = orig_len;
378 }
379 state->stats.unc_bytes += orig_len;
380 state->stats.unc_packets++;
381
382 return olen;
383}
384
385static void
386z_comp_stats(arg, stats)
387 void *arg;
388 struct compstat *stats;
389{
390 struct deflate_state *state = (struct deflate_state *) arg;
391 u_int out;
392
393 *stats = state->stats;
394 stats->ratio = stats->unc_bytes;
395 out = stats->comp_bytes + stats->inc_bytes;
396 if (stats->ratio <= 0x7ffffff)
397 stats->ratio <<= 8;
398 else
399 out >>= 8;
400 if (out != 0)
401 stats->ratio /= out;
402}
403
404/*
405 * Allocate space for a decompressor.
406 */
407static void *
408z_decomp_alloc(options, opt_len)
409 u_char *options;
410 int opt_len;
411{
412 struct deflate_state *state;
413 int w_size;
414
415 if (opt_len != CILEN_DEFLATE
416 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
417 || options[1] != CILEN_DEFLATE
418 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
419 || options[3] != DEFLATE_CHK_SEQUENCE)
420 return NULL;
421 w_size = DEFLATE_SIZE(options[2]);
422 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
423 return NULL;
424
425 MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
426 M_DEVBUF, M_NOWAIT);
427 if (state == NULL)
428 return NULL;
429
430 state->strm.next_out = NULL;
431 state->strm.zalloc = z_alloc;
432 state->strm.zfree = z_free;
433 if (inflateInit2(&state->strm, -w_size) != Z_OK) {
434 FREE(state, M_DEVBUF);
435 return NULL;
436 }
437
438 state->w_size = w_size;
439 bzero(&state->stats, sizeof(state->stats));
440 return (void *) state;
441}
442
443static void
444z_decomp_free(arg)
445 void *arg;
446{
447 struct deflate_state *state = (struct deflate_state *) arg;
448
449 inflateEnd(&state->strm);
450 FREE(state, M_DEVBUF);
451}
452
453static int
454z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
455 void *arg;
456 u_char *options;
457 int opt_len, unit, hdrlen, mru, debug;
458{
459 struct deflate_state *state = (struct deflate_state *) arg;
460
461 if (opt_len < CILEN_DEFLATE
462 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
463 || options[1] != CILEN_DEFLATE
464 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
465 || DEFLATE_SIZE(options[2]) != state->w_size
466 || options[3] != DEFLATE_CHK_SEQUENCE)
467 return 0;
468
469 state->seqno = 0;
470 state->unit = unit;
471 state->hdrlen = hdrlen;
472 state->debug = debug;
473 state->mru = mru;
474
475 inflateReset(&state->strm);
476
477 return 1;
478}
479
480static void
481z_decomp_reset(arg)
482 void *arg;
483{
484 struct deflate_state *state = (struct deflate_state *) arg;
485
486 state->seqno = 0;
487 inflateReset(&state->strm);
488}
489
490/*
491 * Decompress a Deflate-compressed packet.
492 *
493 * Because of patent problems, we return DECOMP_ERROR for errors
494 * found by inspecting the input data and for system problems, but
495 * DECOMP_FATALERROR for any errors which could possibly be said to
496 * be being detected "after" decompression. For DECOMP_ERROR,
497 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
498 * infringing a patent of Motorola's if we do, so we take CCP down
499 * instead.
500 *
501 * Given that the frame has the correct sequence number and a good FCS,
502 * errors such as invalid codes in the input most likely indicate a
503 * bug, so we return DECOMP_FATALERROR for them in order to turn off
504 * compression, even though they are detected by inspecting the input.
505 */
506int
507z_decompress(arg, mi, mop)
508 void *arg;
509 struct mbuf *mi, **mop;
510{
511 struct deflate_state *state = (struct deflate_state *) arg;
512 struct mbuf *mo, *mo_head;
513 u_char *rptr, *wptr;
514 int rlen, olen, ospace;
515 int seq, i, flush, r, decode_proto;
516 u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
517
518 *mop = NULL;
519 rptr = mtod(mi, u_char *);
520 rlen = mi->m_len;
521 for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
522 while (rlen <= 0) {
523 mi = mi->m_next;
524 if (mi == NULL)
525 return DECOMP_ERROR;
526 rptr = mtod(mi, u_char *);
527 rlen = mi->m_len;
528 }
529 hdr[i] = *rptr++;
530 --rlen;
531 }
532
533 /* Check the sequence number. */
534 seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
535 if (seq != state->seqno) {
536 if (state->debug)
537 printf("z_decompress%d: bad seq # %d, expected %d\n",
538 state->unit, seq, state->seqno);
539 return DECOMP_ERROR;
540 }
541 ++state->seqno;
542
543 /* Allocate an output mbuf. */
544 MGETHDR(mo, M_DONTWAIT, MT_DATA);
545 if (mo == NULL)
546 return DECOMP_ERROR;
547 mo_head = mo;
548 mo->m_len = 0;
549 mo->m_next = NULL;
550 MCLGET(mo, M_DONTWAIT);
551 ospace = M_TRAILINGSPACE(mo);
552 if (state->hdrlen + PPP_HDRLEN < ospace) {
553 mo->m_data += state->hdrlen;
554 ospace -= state->hdrlen;
555 }
2d21ac55
A
556#if CONFIG_MACF_NET
557 mac_mbuf_label_copy(mi, mo);
558#endif
1c79356b
A
559
560 /*
561 * Fill in the first part of the PPP header. The protocol field
562 * comes from the decompressed data.
563 */
564 wptr = mtod(mo, u_char *);
565 wptr[0] = PPP_ADDRESS(hdr);
566 wptr[1] = PPP_CONTROL(hdr);
567 wptr[2] = 0;
568
569 /*
570 * Set up to call inflate. We set avail_out to 1 initially so we can
571 * look at the first byte of the output and decide whether we have
572 * a 1-byte or 2-byte protocol field.
573 */
574 state->strm.next_in = rptr;
575 state->strm.avail_in = rlen;
576 mi = mi->m_next;
577 flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
578 rlen += PPP_HDRLEN + DEFLATE_OVHD;
579 state->strm.next_out = wptr + 3;
580 state->strm.avail_out = 1;
581 decode_proto = 1;
582 olen = PPP_HDRLEN;
583
584 /*
585 * Call inflate, supplying more input or output as needed.
586 */
587 for (;;) {
588 r = inflate(&state->strm, flush);
589 if (r != Z_OK) {
590#if !DEFLATE_DEBUG
591 if (state->debug)
592#endif
593 printf("z_decompress%d: inflate returned %d (%s)\n",
594 state->unit, r, (state->strm.msg? state->strm.msg: ""));
595 m_freem(mo_head);
596 return DECOMP_FATALERROR;
597 }
598 if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
599 break; /* all done */
600 if (state->strm.avail_in == 0 && mi != NULL) {
601 state->strm.next_in = mtod(mi, u_char *);
602 state->strm.avail_in = mi->m_len;
603 rlen += mi->m_len;
604 mi = mi->m_next;
605 if (mi == NULL)
606 flush = Z_PACKET_FLUSH;
607 }
608 if (state->strm.avail_out == 0) {
609 if (decode_proto) {
610 state->strm.avail_out = ospace - PPP_HDRLEN;
611 if ((wptr[3] & 1) == 0) {
612 /* 2-byte protocol field */
613 wptr[2] = wptr[3];
614 --state->strm.next_out;
615 ++state->strm.avail_out;
616 --olen;
617 }
618 decode_proto = 0;
619 } else {
620 mo->m_len = ospace;
621 olen += ospace;
622 MGET(mo->m_next, M_DONTWAIT, MT_DATA);
623 mo = mo->m_next;
624 if (mo == NULL) {
625 m_freem(mo_head);
626 return DECOMP_ERROR;
627 }
628 MCLGET(mo, M_DONTWAIT);
629 state->strm.next_out = mtod(mo, u_char *);
630 state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
631 }
632 }
633 }
634 if (decode_proto) {
635 m_freem(mo_head);
636 return DECOMP_ERROR;
637 }
638 olen += (mo->m_len = ospace - state->strm.avail_out);
639#if DEFLATE_DEBUG
640 if (state->debug && olen > state->mru + PPP_HDRLEN)
641 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
642 state->unit, olen, state->mru + PPP_HDRLEN);
643#endif
644
645 state->stats.unc_bytes += olen;
646 state->stats.unc_packets++;
647 state->stats.comp_bytes += rlen;
648 state->stats.comp_packets++;
649
650 *mop = mo_head;
651 return DECOMP_OK;
652}
653
654/*
655 * Incompressible data has arrived - add it to the history.
656 */
657static void
658z_incomp(arg, mi)
659 void *arg;
660 struct mbuf *mi;
661{
662 struct deflate_state *state = (struct deflate_state *) arg;
663 u_char *rptr;
664 int rlen, proto, r;
665
666 /*
667 * Check that the protocol is one we handle.
668 */
669 rptr = mtod(mi, u_char *);
670 proto = PPP_PROTOCOL(rptr);
671 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
672 return;
673
674 ++state->seqno;
675
676 /*
677 * Iterate through the mbufs, adding the characters in them
678 * to the decompressor's history. For the first mbuf, we start
679 * at the either the 1st or 2nd byte of the protocol field,
680 * depending on whether the protocol value is compressible.
681 */
682 rlen = mi->m_len;
683 state->strm.next_in = rptr + 3;
684 state->strm.avail_in = rlen - 3;
685 if (proto > 0xff) {
686 --state->strm.next_in;
687 ++state->strm.avail_in;
688 }
689 for (;;) {
690 r = inflateIncomp(&state->strm);
691 if (r != Z_OK) {
692 /* gak! */
693#if !DEFLATE_DEBUG
694 if (state->debug)
695#endif
696 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
697 state->unit, r, (state->strm.msg? state->strm.msg: ""));
698 return;
699 }
700 mi = mi->m_next;
701 if (mi == NULL)
702 break;
703 state->strm.next_in = mtod(mi, u_char *);
704 state->strm.avail_in = mi->m_len;
705 rlen += mi->m_len;
706 }
707
708 /*
709 * Update stats.
710 */
711 state->stats.inc_bytes += rlen;
712 state->stats.inc_packets++;
713 state->stats.unc_bytes += rlen;
714 state->stats.unc_packets++;
715}
716
717#endif /* DO_DEFLATE */