Line data Source code
1 : /* $OpenBSD: ppp-deflate.c,v 1.14 2017/09/08 05:36:53 deraadt Exp $ */
2 : /* $NetBSD: ppp-deflate.c,v 1.1 1996/03/15 02:28:09 paulus Exp $ */
3 :
4 : /*
5 : * ppp_deflate.c - interface the zlib procedures for Deflate compression
6 : * and decompression (as used by gzip) to the PPP code.
7 : * This version is for use with mbufs on BSD-derived systems.
8 : *
9 : * Copyright (c) 1989-2002 Paul Mackerras. All rights reserved.
10 : *
11 : * Redistribution and use in source and binary forms, with or without
12 : * modification, are permitted provided that the following conditions
13 : * are met:
14 : *
15 : * 1. Redistributions of source code must retain the above copyright
16 : * notice, this list of conditions and the following disclaimer.
17 : *
18 : * 2. Redistributions in binary form must reproduce the above copyright
19 : * notice, this list of conditions and the following disclaimer in
20 : * the documentation and/or other materials provided with the
21 : * distribution.
22 : *
23 : * 3. The name(s) of the authors of this software must not be used to
24 : * endorse or promote products derived from this software without
25 : * prior written permission.
26 : *
27 : * 4. Redistributions of any form whatsoever must retain the following
28 : * acknowledgment:
29 : * "This product includes software developed by Paul Mackerras
30 : * <paulus@samba.org>".
31 : *
32 : * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
33 : * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
34 : * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
35 : * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
36 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
37 : * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
38 : * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
39 : */
40 :
41 : #include <sys/param.h>
42 : #include <sys/systm.h>
43 : #include <sys/mbuf.h>
44 : #include <net/ppp_defs.h>
45 : #include <lib/libz/zlib.h>
46 :
47 : #define PACKETPTR struct mbuf *
48 : #include <net/ppp-comp.h>
49 :
50 : #if DO_DEFLATE
51 :
52 : /*
53 : * State for a Deflate (de)compressor.
54 : */
55 : struct deflate_state {
56 : int seqno;
57 : int w_size;
58 : int unit;
59 : int hdrlen;
60 : int mru;
61 : int debug;
62 : z_stream strm;
63 : struct compstat stats;
64 : };
65 :
66 : #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
67 :
68 : static void *zcalloc(void *, u_int items, u_int size);
69 : static void zcfree(void *, void *ptr);
70 : static void *z_comp_alloc(u_char *options, int opt_len);
71 : static void *z_decomp_alloc(u_char *options, int opt_len);
72 : static void z_comp_free(void *state);
73 : static void z_decomp_free(void *state);
74 : static int z_comp_init(void *state, u_char *options, int opt_len,
75 : int unit, int hdrlen, int debug);
76 : static int z_decomp_init(void *state, u_char *options, int opt_len,
77 : int unit, int hdrlen, int mru, int debug);
78 : static int z_compress(void *state, struct mbuf **mret,
79 : struct mbuf *mp, int slen, int maxolen);
80 : static void z_incomp(void *state, struct mbuf *dmsg);
81 : static int z_decompress(void *state, struct mbuf *cmp,
82 : struct mbuf **dmpp);
83 : static void z_comp_reset(void *state);
84 : static void z_decomp_reset(void *state);
85 : static void z_comp_stats(void *state, struct compstat *stats);
86 :
87 : /*
88 : * Procedures exported to if_ppp.c.
89 : */
90 : struct compressor ppp_deflate = {
91 : CI_DEFLATE, /* compress_proto */
92 : z_comp_alloc, /* comp_alloc */
93 : z_comp_free, /* comp_free */
94 : z_comp_init, /* comp_init */
95 : z_comp_reset, /* comp_reset */
96 : z_compress, /* compress */
97 : z_comp_stats, /* comp_stat */
98 : z_decomp_alloc, /* decomp_alloc */
99 : z_decomp_free, /* decomp_free */
100 : z_decomp_init, /* decomp_init */
101 : z_decomp_reset, /* decomp_reset */
102 : z_decompress, /* decompress */
103 : z_incomp, /* incomp */
104 : z_comp_stats, /* decomp_stat */
105 : };
106 :
107 : struct compressor ppp_deflate_draft = {
108 : CI_DEFLATE_DRAFT, /* compress_proto */
109 : z_comp_alloc, /* comp_alloc */
110 : z_comp_free, /* comp_free */
111 : z_comp_init, /* comp_init */
112 : z_comp_reset, /* comp_reset */
113 : z_compress, /* compress */
114 : z_comp_stats, /* comp_stat */
115 : z_decomp_alloc, /* decomp_alloc */
116 : z_decomp_free, /* decomp_free */
117 : z_decomp_init, /* decomp_init */
118 : z_decomp_reset, /* decomp_reset */
119 : z_decompress, /* decompress */
120 : z_incomp, /* incomp */
121 : z_comp_stats, /* decomp_stat */
122 : };
123 : /*
124 : * Space allocation and freeing routines for use by zlib routines.
125 : */
126 : void *
127 0 : zcalloc(notused, items, size)
128 : void *notused;
129 : u_int items, size;
130 : {
131 : void *ptr;
132 :
133 0 : ptr = mallocarray(items, size, M_DEVBUF, M_NOWAIT);
134 0 : return ptr;
135 : }
136 :
137 : void
138 0 : zcfree(notused, ptr)
139 : void *notused;
140 : void *ptr;
141 : {
142 0 : free(ptr, M_DEVBUF, 0);
143 0 : }
144 :
145 : /*
146 : * Allocate space for a compressor.
147 : */
148 : static void *
149 0 : z_comp_alloc(options, opt_len)
150 : u_char *options;
151 : int opt_len;
152 : {
153 : struct deflate_state *state;
154 : int w_size;
155 :
156 0 : if (opt_len != CILEN_DEFLATE
157 0 : || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
158 0 : || options[1] != CILEN_DEFLATE
159 0 : || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
160 0 : || options[3] != DEFLATE_CHK_SEQUENCE)
161 0 : return NULL;
162 0 : w_size = DEFLATE_SIZE(options[2]);
163 0 : if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
164 0 : return NULL;
165 :
166 0 : state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT);
167 0 : if (state == NULL)
168 0 : return NULL;
169 :
170 0 : state->strm.next_in = NULL;
171 0 : state->strm.zalloc = zcalloc;
172 0 : state->strm.zfree = zcfree;
173 0 : if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
174 0 : -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
175 0 : free(state, M_DEVBUF, 0);
176 0 : return NULL;
177 : }
178 :
179 0 : state->w_size = w_size;
180 0 : bzero(&state->stats, sizeof(state->stats));
181 0 : return (void *) state;
182 0 : }
183 :
184 : static void
185 0 : z_comp_free(arg)
186 : void *arg;
187 : {
188 0 : struct deflate_state *state = (struct deflate_state *) arg;
189 :
190 0 : deflateEnd(&state->strm);
191 0 : free(state, M_DEVBUF, 0);
192 0 : }
193 :
194 : static int
195 0 : z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
196 : void *arg;
197 : u_char *options;
198 : int opt_len, unit, hdrlen, debug;
199 : {
200 0 : struct deflate_state *state = (struct deflate_state *) arg;
201 :
202 0 : if (opt_len < CILEN_DEFLATE
203 0 : || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
204 0 : || options[1] != CILEN_DEFLATE
205 0 : || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
206 0 : || DEFLATE_SIZE(options[2]) != state->w_size
207 0 : || options[3] != DEFLATE_CHK_SEQUENCE)
208 0 : return 0;
209 :
210 0 : state->seqno = 0;
211 0 : state->unit = unit;
212 0 : state->hdrlen = hdrlen;
213 0 : state->debug = debug;
214 :
215 0 : deflateReset(&state->strm);
216 :
217 0 : return 1;
218 0 : }
219 :
220 : static void
221 0 : z_comp_reset(arg)
222 : void *arg;
223 : {
224 0 : struct deflate_state *state = (struct deflate_state *) arg;
225 :
226 0 : state->seqno = 0;
227 0 : deflateReset(&state->strm);
228 0 : }
229 :
230 : int
231 0 : z_compress(arg, mret, mp, orig_len, maxolen)
232 : void *arg;
233 : struct mbuf **mret; /* compressed packet (out) */
234 : struct mbuf *mp; /* uncompressed packet (in) */
235 : int orig_len, maxolen;
236 : {
237 0 : struct deflate_state *state = (struct deflate_state *) arg;
238 : u_char *rptr, *wptr;
239 : int proto, olen, wspace, r, flush;
240 : struct mbuf *m;
241 :
242 : /*
243 : * Check that the protocol is in the range we handle.
244 : */
245 0 : rptr = mtod(mp, u_char *);
246 0 : proto = PPP_PROTOCOL(rptr);
247 0 : if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
248 0 : *mret = NULL;
249 0 : return orig_len;
250 : }
251 :
252 : /* Allocate one mbuf initially. */
253 0 : if (maxolen > orig_len)
254 0 : maxolen = orig_len;
255 0 : MGET(m, M_DONTWAIT, MT_DATA);
256 0 : *mret = m;
257 0 : if (m != NULL) {
258 0 : m->m_len = 0;
259 0 : if (maxolen + state->hdrlen > MLEN)
260 0 : MCLGET(m, M_DONTWAIT);
261 0 : wspace = M_TRAILINGSPACE(m);
262 0 : if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
263 0 : m->m_data += state->hdrlen;
264 0 : wspace -= state->hdrlen;
265 0 : }
266 0 : wptr = mtod(m, u_char *);
267 :
268 : /*
269 : * Copy over the PPP header and store the 2-byte sequence number.
270 : */
271 0 : wptr[0] = PPP_ADDRESS(rptr);
272 0 : wptr[1] = PPP_CONTROL(rptr);
273 0 : wptr[2] = PPP_COMP >> 8;
274 0 : wptr[3] = PPP_COMP;
275 0 : wptr += PPP_HDRLEN;
276 0 : wptr[0] = state->seqno >> 8;
277 0 : wptr[1] = state->seqno;
278 0 : wptr += 2;
279 0 : state->strm.next_out = wptr;
280 0 : state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
281 0 : } else {
282 0 : state->strm.next_out = NULL;
283 0 : state->strm.avail_out = 1000000;
284 : wptr = NULL;
285 : wspace = 0;
286 : }
287 0 : ++state->seqno;
288 :
289 0 : rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */
290 0 : state->strm.next_in = rptr;
291 0 : state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
292 0 : mp = mp->m_next;
293 0 : flush = (mp == NULL)? Z_SYNC_FLUSH: Z_NO_FLUSH;
294 : olen = 0;
295 0 : for (;;) {
296 0 : r = deflate(&state->strm, flush);
297 0 : if (r != Z_OK) {
298 0 : printf("z_compress: deflate returned %d (%s)\n",
299 0 : r, (state->strm.msg? state->strm.msg: ""));
300 0 : break;
301 : }
302 0 : if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
303 : break; /* all done */
304 0 : if (state->strm.avail_in == 0 && mp != NULL) {
305 0 : state->strm.next_in = mtod(mp, u_char *);
306 0 : state->strm.avail_in = mp->m_len;
307 0 : mp = mp->m_next;
308 0 : if (mp == NULL)
309 0 : flush = Z_SYNC_FLUSH;
310 : }
311 0 : if (state->strm.avail_out == 0) {
312 0 : if (m != NULL) {
313 0 : m->m_len = wspace;
314 0 : olen += wspace;
315 0 : MGET(m->m_next, M_DONTWAIT, MT_DATA);
316 : m = m->m_next;
317 0 : if (m != NULL) {
318 0 : m->m_len = 0;
319 0 : if (maxolen - olen > MLEN)
320 0 : MCLGET(m, M_DONTWAIT);
321 0 : state->strm.next_out = mtod(m, u_char *);
322 0 : state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
323 0 : }
324 : }
325 0 : if (m == NULL) {
326 0 : state->strm.next_out = NULL;
327 0 : state->strm.avail_out = 1000000;
328 0 : }
329 : }
330 : }
331 0 : if (m != NULL)
332 0 : olen += (m->m_len = wspace - state->strm.avail_out);
333 :
334 : /*
335 : * See if we managed to reduce the size of the packet.
336 : * If the compressor just gave us a single zero byte, it means
337 : * the packet was incompressible.
338 : */
339 0 : if (m != NULL && olen < orig_len
340 0 : && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
341 0 : state->stats.comp_bytes += olen;
342 0 : state->stats.comp_packets++;
343 0 : } else {
344 0 : m_freemp(mret);
345 :
346 0 : state->stats.inc_bytes += orig_len;
347 0 : state->stats.inc_packets++;
348 : olen = orig_len;
349 : }
350 0 : state->stats.unc_bytes += orig_len;
351 0 : state->stats.unc_packets++;
352 :
353 0 : return olen;
354 0 : }
355 :
356 : static void
357 0 : z_comp_stats(arg, stats)
358 : void *arg;
359 : struct compstat *stats;
360 : {
361 0 : struct deflate_state *state = (struct deflate_state *) arg;
362 : u_int out;
363 :
364 0 : *stats = state->stats;
365 0 : stats->ratio = stats->unc_bytes;
366 0 : out = stats->comp_bytes + stats->inc_bytes;
367 0 : if (stats->ratio <= 0x7ffffff)
368 0 : stats->ratio <<= 8;
369 : else
370 0 : out >>= 8;
371 0 : if (out != 0)
372 0 : stats->ratio /= out;
373 0 : }
374 :
375 : /*
376 : * Allocate space for a decompressor.
377 : */
378 : static void *
379 0 : z_decomp_alloc(options, opt_len)
380 : u_char *options;
381 : int opt_len;
382 : {
383 : struct deflate_state *state;
384 : int w_size;
385 :
386 0 : if (opt_len != CILEN_DEFLATE
387 0 : || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
388 0 : || options[1] != CILEN_DEFLATE
389 0 : || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
390 0 : || options[3] != DEFLATE_CHK_SEQUENCE)
391 0 : return NULL;
392 0 : w_size = DEFLATE_SIZE(options[2]);
393 0 : if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
394 0 : return NULL;
395 :
396 0 : state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT);
397 0 : if (state == NULL)
398 0 : return NULL;
399 :
400 0 : state->strm.next_out = NULL;
401 0 : state->strm.zalloc = zcalloc;
402 0 : state->strm.zfree = zcfree;
403 0 : if (inflateInit2(&state->strm, -w_size) != Z_OK) {
404 0 : free(state, M_DEVBUF, 0);
405 0 : return NULL;
406 : }
407 :
408 0 : state->w_size = w_size;
409 0 : bzero(&state->stats, sizeof(state->stats));
410 0 : return (void *) state;
411 0 : }
412 :
413 : static void
414 0 : z_decomp_free(arg)
415 : void *arg;
416 : {
417 0 : struct deflate_state *state = (struct deflate_state *) arg;
418 :
419 0 : inflateEnd(&state->strm);
420 0 : free(state, M_DEVBUF, 0);
421 0 : }
422 :
423 : static int
424 0 : z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
425 : void *arg;
426 : u_char *options;
427 : int opt_len, unit, hdrlen, mru, debug;
428 : {
429 0 : struct deflate_state *state = (struct deflate_state *) arg;
430 :
431 0 : if (opt_len < CILEN_DEFLATE
432 0 : || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
433 0 : || options[1] != CILEN_DEFLATE
434 0 : || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
435 0 : || DEFLATE_SIZE(options[2]) != state->w_size
436 0 : || options[3] != DEFLATE_CHK_SEQUENCE)
437 0 : return 0;
438 :
439 0 : state->seqno = 0;
440 0 : state->unit = unit;
441 0 : state->hdrlen = hdrlen;
442 0 : state->debug = debug;
443 0 : state->mru = mru;
444 :
445 0 : inflateReset(&state->strm);
446 :
447 0 : return 1;
448 0 : }
449 :
450 : static void
451 0 : z_decomp_reset(arg)
452 : void *arg;
453 : {
454 0 : struct deflate_state *state = (struct deflate_state *) arg;
455 :
456 0 : state->seqno = 0;
457 0 : inflateReset(&state->strm);
458 0 : }
459 :
460 : /*
461 : * Decompress a Deflate-compressed packet.
462 : *
463 : * Because of patent problems, we return DECOMP_ERROR for errors
464 : * found by inspecting the input data and for system problems, but
465 : * DECOMP_FATALERROR for any errors which could possibly be said to
466 : * be being detected "after" decompression. For DECOMP_ERROR,
467 : * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
468 : * infringing a patent of Motorola's if we do, so we take CCP down
469 : * instead.
470 : *
471 : * Given that the frame has the correct sequence number and a good FCS,
472 : * errors such as invalid codes in the input most likely indicate a
473 : * bug, so we return DECOMP_FATALERROR for them in order to turn off
474 : * compression, even though they are detected by inspecting the input.
475 : */
476 : int
477 0 : z_decompress(arg, mi, mop)
478 : void *arg;
479 : struct mbuf *mi, **mop;
480 : {
481 0 : struct deflate_state *state = (struct deflate_state *) arg;
482 : struct mbuf *mo, *mo_head;
483 : u_char *rptr, *wptr;
484 : int rlen, olen, ospace;
485 : int seq, i, flush, r, decode_proto;
486 0 : u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
487 :
488 0 : *mop = NULL;
489 0 : rptr = mtod(mi, u_char *);
490 0 : rlen = mi->m_len;
491 0 : for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
492 0 : while (rlen <= 0) {
493 0 : mi = mi->m_next;
494 0 : if (mi == NULL)
495 0 : return DECOMP_ERROR;
496 0 : rptr = mtod(mi, u_char *);
497 0 : rlen = mi->m_len;
498 : }
499 0 : hdr[i] = *rptr++;
500 0 : --rlen;
501 : }
502 :
503 : /* Check the sequence number. */
504 0 : seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
505 0 : if (seq != state->seqno) {
506 0 : if (state->debug)
507 0 : printf("z_decompress%d: bad seq # %d, expected %d\n",
508 0 : state->unit, seq, state->seqno);
509 0 : return DECOMP_ERROR;
510 : }
511 0 : ++state->seqno;
512 :
513 : /* Allocate an output mbuf. */
514 0 : MGETHDR(mo, M_DONTWAIT, MT_DATA);
515 0 : if (mo == NULL)
516 0 : return DECOMP_ERROR;
517 : mo_head = mo;
518 0 : mo->m_len = 0;
519 0 : mo->m_next = NULL;
520 0 : MCLGET(mo, M_DONTWAIT);
521 0 : ospace = M_TRAILINGSPACE(mo);
522 0 : if (state->hdrlen + PPP_HDRLEN < ospace) {
523 0 : mo->m_data += state->hdrlen;
524 0 : ospace -= state->hdrlen;
525 0 : }
526 :
527 : /*
528 : * Fill in the first part of the PPP header. The protocol field
529 : * comes from the decompressed data.
530 : */
531 0 : wptr = mtod(mo, u_char *);
532 0 : wptr[0] = PPP_ADDRESS(hdr);
533 0 : wptr[1] = PPP_CONTROL(hdr);
534 0 : wptr[2] = 0;
535 :
536 : /*
537 : * Set up to call inflate. We set avail_out to 1 initially so we can
538 : * look at the first byte of the output and decide whether we have
539 : * a 1-byte or 2-byte protocol field.
540 : */
541 0 : state->strm.next_in = rptr;
542 0 : state->strm.avail_in = rlen;
543 0 : mi = mi->m_next;
544 0 : flush = (mi == NULL)? Z_SYNC_FLUSH: Z_NO_FLUSH;
545 0 : rlen += PPP_HDRLEN + DEFLATE_OVHD;
546 0 : state->strm.next_out = wptr + 3;
547 0 : state->strm.avail_out = 1;
548 : decode_proto = 1;
549 : olen = PPP_HDRLEN;
550 :
551 : /*
552 : * Call inflate, supplying more input or output as needed.
553 : */
554 0 : for (;;) {
555 0 : r = inflate(&state->strm, flush);
556 0 : if (r != Z_OK) {
557 : #ifndef DEFLATE_DEBUG
558 0 : if (state->debug)
559 : #endif
560 0 : printf("z_decompress%d: inflate returned %d (%s)\n",
561 0 : state->unit, r, (state->strm.msg? state->strm.msg: ""));
562 0 : m_freem(mo_head);
563 0 : return DECOMP_FATALERROR;
564 : }
565 0 : if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
566 : break; /* all done */
567 0 : if (state->strm.avail_in == 0 && mi != NULL) {
568 0 : state->strm.next_in = mtod(mi, u_char *);
569 0 : state->strm.avail_in = mi->m_len;
570 0 : rlen += mi->m_len;
571 0 : mi = mi->m_next;
572 0 : if (mi == NULL)
573 0 : flush = Z_SYNC_FLUSH;
574 : }
575 0 : if (state->strm.avail_out == 0) {
576 0 : if (decode_proto) {
577 0 : state->strm.avail_out = ospace - PPP_HDRLEN;
578 0 : if ((wptr[3] & 1) == 0) {
579 : /* 2-byte protocol field */
580 0 : wptr[2] = wptr[3];
581 0 : --state->strm.next_out;
582 0 : ++state->strm.avail_out;
583 0 : --olen;
584 0 : }
585 : decode_proto = 0;
586 0 : } else {
587 0 : mo->m_len = ospace;
588 0 : olen += ospace;
589 0 : MGET(mo->m_next, M_DONTWAIT, MT_DATA);
590 : mo = mo->m_next;
591 0 : if (mo == NULL) {
592 0 : m_freem(mo_head);
593 0 : return DECOMP_ERROR;
594 : }
595 0 : MCLGET(mo, M_DONTWAIT);
596 0 : state->strm.next_out = mtod(mo, u_char *);
597 0 : state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
598 : }
599 : }
600 : }
601 0 : if (decode_proto) {
602 0 : m_freem(mo_head);
603 0 : return DECOMP_ERROR;
604 : }
605 0 : olen += (mo->m_len = ospace - state->strm.avail_out);
606 : #ifdef DEFLATE_DEBUG
607 : if (olen > state->mru + PPP_HDRLEN)
608 : printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
609 : state->unit, olen, state->mru + PPP_HDRLEN);
610 : #endif
611 :
612 0 : state->stats.unc_bytes += olen;
613 0 : state->stats.unc_packets++;
614 0 : state->stats.comp_bytes += rlen;
615 0 : state->stats.comp_packets++;
616 :
617 0 : *mop = mo_head;
618 0 : return DECOMP_OK;
619 0 : }
620 :
621 : /*
622 : * Incompressible data has arrived - add it to the history.
623 : */
624 : static void
625 0 : z_incomp(arg, mi)
626 : void *arg;
627 : struct mbuf *mi;
628 : {
629 0 : struct deflate_state *state = (struct deflate_state *) arg;
630 : u_char *rptr;
631 : int rlen, proto, r;
632 :
633 : /*
634 : * Check that the protocol is one we handle.
635 : */
636 0 : rptr = mtod(mi, u_char *);
637 0 : proto = PPP_PROTOCOL(rptr);
638 0 : if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
639 0 : return;
640 :
641 0 : ++state->seqno;
642 :
643 : /*
644 : * Iterate through the mbufs, adding the characters in them
645 : * to the decompressor's history. For the first mbuf, we start
646 : * at the either the 1st or 2nd byte of the protocol field,
647 : * depending on whether the protocol value is compressible.
648 : */
649 0 : rlen = mi->m_len;
650 0 : state->strm.next_in = rptr + 3;
651 0 : state->strm.avail_in = rlen - 3;
652 0 : if (proto > 0xff) {
653 0 : --state->strm.next_in;
654 0 : ++state->strm.avail_in;
655 0 : }
656 0 : for (;;) {
657 0 : r = inflateInit(&state->strm);
658 0 : if (r != Z_OK) {
659 : /* gak! */
660 : #ifndef DEFLATE_DEBUG
661 0 : if (state->debug)
662 : #endif
663 0 : printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
664 0 : state->unit, r, (state->strm.msg? state->strm.msg: ""));
665 0 : return;
666 : }
667 0 : mi = mi->m_next;
668 0 : if (mi == NULL)
669 : break;
670 0 : state->strm.next_in = mtod(mi, u_char *);
671 0 : state->strm.avail_in = mi->m_len;
672 0 : rlen += mi->m_len;
673 : }
674 :
675 : /*
676 : * Update stats.
677 : */
678 0 : state->stats.inc_bytes += rlen;
679 0 : state->stats.inc_packets++;
680 0 : state->stats.unc_bytes += rlen;
681 0 : state->stats.unc_packets++;
682 0 : }
683 :
684 : #endif /* DO_DEFLATE */
|