This source file includes following definitions.
- zalloc
- zfree
- z_comp_alloc
- z_comp_free
- z_comp_init
- z_comp_reset
- z_compress
- z_comp_stats
- z_decomp_alloc
- z_decomp_free
- z_decomp_init
- z_decomp_reset
- z_decompress
- z_incomp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <net/ppp_defs.h>
46 #include <net/zlib.h>
47
48 #define PACKETPTR struct mbuf *
49 #include <net/ppp-comp.h>
50
51 #if DO_DEFLATE
52
53
54
55
56 struct deflate_state {
57 int seqno;
58 int w_size;
59 int unit;
60 int hdrlen;
61 int mru;
62 int debug;
63 z_stream strm;
64 struct compstat stats;
65 };
66
67 #define DEFLATE_OVHD 2
68
69 static void *zalloc(void *, u_int items, u_int size);
70 static void zfree(void *, void *ptr, u_int nb);
71 static void *z_comp_alloc(u_char *options, int opt_len);
72 static void *z_decomp_alloc(u_char *options, int opt_len);
73 static void z_comp_free(void *state);
74 static void z_decomp_free(void *state);
75 static int z_comp_init(void *state, u_char *options, int opt_len,
76 int unit, int hdrlen, int debug);
77 static int z_decomp_init(void *state, u_char *options, int opt_len,
78 int unit, int hdrlen, int mru, int debug);
79 static int z_compress(void *state, struct mbuf **mret,
80 struct mbuf *mp, int slen, int maxolen);
81 static void z_incomp(void *state, struct mbuf *dmsg);
82 static int z_decompress(void *state, struct mbuf *cmp,
83 struct mbuf **dmpp);
84 static void z_comp_reset(void *state);
85 static void z_decomp_reset(void *state);
86 static void z_comp_stats(void *state, struct compstat *stats);
87
88
89
90
91 struct compressor ppp_deflate = {
92 CI_DEFLATE,
93 z_comp_alloc,
94 z_comp_free,
95 z_comp_init,
96 z_comp_reset,
97 z_compress,
98 z_comp_stats,
99 z_decomp_alloc,
100 z_decomp_free,
101 z_decomp_init,
102 z_decomp_reset,
103 z_decompress,
104 z_incomp,
105 z_comp_stats,
106 };
107
108 struct compressor ppp_deflate_draft = {
109 CI_DEFLATE_DRAFT,
110 z_comp_alloc,
111 z_comp_free,
112 z_comp_init,
113 z_comp_reset,
114 z_compress,
115 z_comp_stats,
116 z_decomp_alloc,
117 z_decomp_free,
118 z_decomp_init,
119 z_decomp_reset,
120 z_decompress,
121 z_incomp,
122 z_comp_stats,
123 };
124
125
126
127 void *
128 zalloc(notused, items, size)
129 void *notused;
130 u_int items, size;
131 {
132 void *ptr;
133
134 MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT);
135 return ptr;
136 }
137
138 void
139 zfree(notused, ptr, nbytes)
140 void *notused;
141 void *ptr;
142 u_int nbytes;
143 {
144 FREE(ptr, M_DEVBUF);
145 }
146
147
148
149
150 static void *
151 z_comp_alloc(options, opt_len)
152 u_char *options;
153 int opt_len;
154 {
155 struct deflate_state *state;
156 int w_size;
157
158 if (opt_len != CILEN_DEFLATE
159 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
160 || options[1] != CILEN_DEFLATE
161 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
162 || options[3] != DEFLATE_CHK_SEQUENCE)
163 return NULL;
164 w_size = DEFLATE_SIZE(options[2]);
165 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
166 return NULL;
167
168 MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
169 M_DEVBUF, M_NOWAIT);
170 if (state == NULL)
171 return NULL;
172
173 state->strm.next_in = NULL;
174 state->strm.zalloc = zalloc;
175 state->strm.zfree = zfree;
176 if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
177 -w_size, 8, Z_DEFAULT_STRATEGY, DEFLATE_OVHD+2) != Z_OK) {
178 FREE(state, M_DEVBUF);
179 return NULL;
180 }
181
182 state->w_size = w_size;
183 bzero(&state->stats, sizeof(state->stats));
184 return (void *) state;
185 }
186
187 static void
188 z_comp_free(arg)
189 void *arg;
190 {
191 struct deflate_state *state = (struct deflate_state *) arg;
192
193 deflateEnd(&state->strm);
194 FREE(state, M_DEVBUF);
195 }
196
197 static int
198 z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
199 void *arg;
200 u_char *options;
201 int opt_len, unit, hdrlen, debug;
202 {
203 struct deflate_state *state = (struct deflate_state *) arg;
204
205 if (opt_len < CILEN_DEFLATE
206 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
207 || options[1] != CILEN_DEFLATE
208 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
209 || DEFLATE_SIZE(options[2]) != state->w_size
210 || options[3] != DEFLATE_CHK_SEQUENCE)
211 return 0;
212
213 state->seqno = 0;
214 state->unit = unit;
215 state->hdrlen = hdrlen;
216 state->debug = debug;
217
218 deflateReset(&state->strm);
219
220 return 1;
221 }
222
223 static void
224 z_comp_reset(arg)
225 void *arg;
226 {
227 struct deflate_state *state = (struct deflate_state *) arg;
228
229 state->seqno = 0;
230 deflateReset(&state->strm);
231 }
232
233 int
234 z_compress(arg, mret, mp, orig_len, maxolen)
235 void *arg;
236 struct mbuf **mret;
237 struct mbuf *mp;
238 int orig_len, maxolen;
239 {
240 struct deflate_state *state = (struct deflate_state *) arg;
241 u_char *rptr, *wptr;
242 int proto, olen, wspace, r, flush;
243 struct mbuf *m;
244
245
246
247
248 rptr = mtod(mp, u_char *);
249 proto = PPP_PROTOCOL(rptr);
250 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
251 *mret = NULL;
252 return orig_len;
253 }
254
255
256 if (maxolen > orig_len)
257 maxolen = orig_len;
258 MGET(m, M_DONTWAIT, MT_DATA);
259 *mret = m;
260 if (m != NULL) {
261 m->m_len = 0;
262 if (maxolen + state->hdrlen > MLEN)
263 MCLGET(m, M_DONTWAIT);
264 wspace = M_TRAILINGSPACE(m);
265 if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
266 m->m_data += state->hdrlen;
267 wspace -= state->hdrlen;
268 }
269 wptr = mtod(m, u_char *);
270
271
272
273
274 wptr[0] = PPP_ADDRESS(rptr);
275 wptr[1] = PPP_CONTROL(rptr);
276 wptr[2] = PPP_COMP >> 8;
277 wptr[3] = PPP_COMP;
278 wptr += PPP_HDRLEN;
279 wptr[0] = state->seqno >> 8;
280 wptr[1] = state->seqno;
281 wptr += 2;
282 state->strm.next_out = wptr;
283 state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
284 } else {
285 state->strm.next_out = NULL;
286 state->strm.avail_out = 1000000;
287 wptr = NULL;
288 wspace = 0;
289 }
290 ++state->seqno;
291
292 rptr += (proto > 0xff)? 2: 3;
293 state->strm.next_in = rptr;
294 state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
295 mp = mp->m_next;
296 flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
297 olen = 0;
298 for (;;) {
299 r = deflate(&state->strm, flush);
300 if (r != Z_OK) {
301 printf("z_compress: deflate returned %d (%s)\n",
302 r, (state->strm.msg? state->strm.msg: ""));
303 break;
304 }
305 if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
306 break;
307 if (state->strm.avail_in == 0 && mp != NULL) {
308 state->strm.next_in = mtod(mp, u_char *);
309 state->strm.avail_in = mp->m_len;
310 mp = mp->m_next;
311 if (mp == NULL)
312 flush = Z_PACKET_FLUSH;
313 }
314 if (state->strm.avail_out == 0) {
315 if (m != NULL) {
316 m->m_len = wspace;
317 olen += wspace;
318 MGET(m->m_next, M_DONTWAIT, MT_DATA);
319 m = m->m_next;
320 if (m != NULL) {
321 m->m_len = 0;
322 if (maxolen - olen > MLEN)
323 MCLGET(m, M_DONTWAIT);
324 state->strm.next_out = mtod(m, u_char *);
325 state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
326 }
327 }
328 if (m == NULL) {
329 state->strm.next_out = NULL;
330 state->strm.avail_out = 1000000;
331 }
332 }
333 }
334 if (m != NULL)
335 olen += (m->m_len = wspace - state->strm.avail_out);
336
337
338
339
340
341
342 if (m != NULL && olen < orig_len
343 && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
344 state->stats.comp_bytes += olen;
345 state->stats.comp_packets++;
346 } else {
347 if (*mret != NULL) {
348 m_freem(*mret);
349 *mret = NULL;
350 }
351 state->stats.inc_bytes += orig_len;
352 state->stats.inc_packets++;
353 olen = orig_len;
354 }
355 state->stats.unc_bytes += orig_len;
356 state->stats.unc_packets++;
357
358 return olen;
359 }
360
361 static void
362 z_comp_stats(arg, stats)
363 void *arg;
364 struct compstat *stats;
365 {
366 struct deflate_state *state = (struct deflate_state *) arg;
367 u_int out;
368
369 *stats = state->stats;
370 stats->ratio = stats->unc_bytes;
371 out = stats->comp_bytes + stats->inc_bytes;
372 if (stats->ratio <= 0x7ffffff)
373 stats->ratio <<= 8;
374 else
375 out >>= 8;
376 if (out != 0)
377 stats->ratio /= out;
378 }
379
380
381
382
383 static void *
384 z_decomp_alloc(options, opt_len)
385 u_char *options;
386 int opt_len;
387 {
388 struct deflate_state *state;
389 int w_size;
390
391 if (opt_len != CILEN_DEFLATE
392 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
393 || options[1] != CILEN_DEFLATE
394 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
395 || options[3] != DEFLATE_CHK_SEQUENCE)
396 return NULL;
397 w_size = DEFLATE_SIZE(options[2]);
398 if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
399 return NULL;
400
401 MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
402 M_DEVBUF, M_NOWAIT);
403 if (state == NULL)
404 return NULL;
405
406 state->strm.next_out = NULL;
407 state->strm.zalloc = zalloc;
408 state->strm.zfree = zfree;
409 if (inflateInit2(&state->strm, -w_size) != Z_OK) {
410 FREE(state, M_DEVBUF);
411 return NULL;
412 }
413
414 state->w_size = w_size;
415 bzero(&state->stats, sizeof(state->stats));
416 return (void *) state;
417 }
418
419 static void
420 z_decomp_free(arg)
421 void *arg;
422 {
423 struct deflate_state *state = (struct deflate_state *) arg;
424
425 inflateEnd(&state->strm);
426 FREE(state, M_DEVBUF);
427 }
428
429 static int
430 z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
431 void *arg;
432 u_char *options;
433 int opt_len, unit, hdrlen, mru, debug;
434 {
435 struct deflate_state *state = (struct deflate_state *) arg;
436
437 if (opt_len < CILEN_DEFLATE
438 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
439 || options[1] != CILEN_DEFLATE
440 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
441 || DEFLATE_SIZE(options[2]) != state->w_size
442 || options[3] != DEFLATE_CHK_SEQUENCE)
443 return 0;
444
445 state->seqno = 0;
446 state->unit = unit;
447 state->hdrlen = hdrlen;
448 state->debug = debug;
449 state->mru = mru;
450
451 inflateReset(&state->strm);
452
453 return 1;
454 }
455
456 static void
457 z_decomp_reset(arg)
458 void *arg;
459 {
460 struct deflate_state *state = (struct deflate_state *) arg;
461
462 state->seqno = 0;
463 inflateReset(&state->strm);
464 }
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482 int
483 z_decompress(arg, mi, mop)
484 void *arg;
485 struct mbuf *mi, **mop;
486 {
487 struct deflate_state *state = (struct deflate_state *) arg;
488 struct mbuf *mo, *mo_head;
489 u_char *rptr, *wptr;
490 int rlen, olen, ospace;
491 int seq, i, flush, r, decode_proto;
492 u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
493
494 *mop = NULL;
495 rptr = mtod(mi, u_char *);
496 rlen = mi->m_len;
497 for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
498 while (rlen <= 0) {
499 mi = mi->m_next;
500 if (mi == NULL)
501 return DECOMP_ERROR;
502 rptr = mtod(mi, u_char *);
503 rlen = mi->m_len;
504 }
505 hdr[i] = *rptr++;
506 --rlen;
507 }
508
509
510 seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
511 if (seq != state->seqno) {
512 if (state->debug)
513 printf("z_decompress%d: bad seq # %d, expected %d\n",
514 state->unit, seq, state->seqno);
515 return DECOMP_ERROR;
516 }
517 ++state->seqno;
518
519
520 MGETHDR(mo, M_DONTWAIT, MT_DATA);
521 if (mo == NULL)
522 return DECOMP_ERROR;
523 mo_head = mo;
524 mo->m_len = 0;
525 mo->m_next = NULL;
526 MCLGET(mo, M_DONTWAIT);
527 ospace = M_TRAILINGSPACE(mo);
528 if (state->hdrlen + PPP_HDRLEN < ospace) {
529 mo->m_data += state->hdrlen;
530 ospace -= state->hdrlen;
531 }
532
533
534
535
536
537 wptr = mtod(mo, u_char *);
538 wptr[0] = PPP_ADDRESS(hdr);
539 wptr[1] = PPP_CONTROL(hdr);
540 wptr[2] = 0;
541
542
543
544
545
546
547 state->strm.next_in = rptr;
548 state->strm.avail_in = rlen;
549 mi = mi->m_next;
550 flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
551 rlen += PPP_HDRLEN + DEFLATE_OVHD;
552 state->strm.next_out = wptr + 3;
553 state->strm.avail_out = 1;
554 decode_proto = 1;
555 olen = PPP_HDRLEN;
556
557
558
559
560 for (;;) {
561 r = inflate(&state->strm, flush);
562 if (r != Z_OK) {
563 #ifndef DEFLATE_DEBUG
564 if (state->debug)
565 #endif
566 printf("z_decompress%d: inflate returned %d (%s)\n",
567 state->unit, r, (state->strm.msg? state->strm.msg: ""));
568 m_freem(mo_head);
569 return DECOMP_FATALERROR;
570 }
571 if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
572 break;
573 if (state->strm.avail_in == 0 && mi != NULL) {
574 state->strm.next_in = mtod(mi, u_char *);
575 state->strm.avail_in = mi->m_len;
576 rlen += mi->m_len;
577 mi = mi->m_next;
578 if (mi == NULL)
579 flush = Z_PACKET_FLUSH;
580 }
581 if (state->strm.avail_out == 0) {
582 if (decode_proto) {
583 state->strm.avail_out = ospace - PPP_HDRLEN;
584 if ((wptr[3] & 1) == 0) {
585
586 wptr[2] = wptr[3];
587 --state->strm.next_out;
588 ++state->strm.avail_out;
589 --olen;
590 }
591 decode_proto = 0;
592 } else {
593 mo->m_len = ospace;
594 olen += ospace;
595 MGET(mo->m_next, M_DONTWAIT, MT_DATA);
596 mo = mo->m_next;
597 if (mo == NULL) {
598 m_freem(mo_head);
599 return DECOMP_ERROR;
600 }
601 MCLGET(mo, M_DONTWAIT);
602 state->strm.next_out = mtod(mo, u_char *);
603 state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
604 }
605 }
606 }
607 if (decode_proto) {
608 m_freem(mo_head);
609 return DECOMP_ERROR;
610 }
611 olen += (mo->m_len = ospace - state->strm.avail_out);
612 #ifdef DEFLATE_DEBUG
613 if (olen > state->mru + PPP_HDRLEN)
614 printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
615 state->unit, olen, state->mru + PPP_HDRLEN);
616 #endif
617
618 state->stats.unc_bytes += olen;
619 state->stats.unc_packets++;
620 state->stats.comp_bytes += rlen;
621 state->stats.comp_packets++;
622
623 *mop = mo_head;
624 return DECOMP_OK;
625 }
626
627
628
629
630 static void
631 z_incomp(arg, mi)
632 void *arg;
633 struct mbuf *mi;
634 {
635 struct deflate_state *state = (struct deflate_state *) arg;
636 u_char *rptr;
637 int rlen, proto, r;
638
639
640
641
642 rptr = mtod(mi, u_char *);
643 proto = PPP_PROTOCOL(rptr);
644 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
645 return;
646
647 ++state->seqno;
648
649
650
651
652
653
654
655 rlen = mi->m_len;
656 state->strm.next_in = rptr + 3;
657 state->strm.avail_in = rlen - 3;
658 if (proto > 0xff) {
659 --state->strm.next_in;
660 ++state->strm.avail_in;
661 }
662 for (;;) {
663 r = inflateIncomp(&state->strm);
664 if (r != Z_OK) {
665
666 #ifndef DEFLATE_DEBUG
667 if (state->debug)
668 #endif
669 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
670 state->unit, r, (state->strm.msg? state->strm.msg: ""));
671 return;
672 }
673 mi = mi->m_next;
674 if (mi == NULL)
675 break;
676 state->strm.next_in = mtod(mi, u_char *);
677 state->strm.avail_in = mi->m_len;
678 rlen += mi->m_len;
679 }
680
681
682
683
684 state->stats.inc_bytes += rlen;
685 state->stats.inc_packets++;
686 state->stats.unc_bytes += rlen;
687 state->stats.unc_packets++;
688 }
689
690 #endif