2 * ppp_comp.c - STREAMS module for kernel-level CCP support.
4 * Copyright (c) 1994 The Australian National University.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies. This software is provided without any
10 * warranty, express or implied. The Australian National University
11 * makes no representations about the suitability of this software for
14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27 * $Id: ppp_comp.c,v 1.6 1995/06/23 01:42:54 paulus Exp $
30 #include <net/net_globals.h>
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/errno.h>
35 #include <sys/stream.h>
36 #include <sys/stropts.h>
37 #include <sys/strconf.h>
38 #include <sys/device.h>
39 #include <sys/syslog.h>
40 #include <sys/socket.h>
42 #include <net/ppp_defs.h>
43 #include <net/ppp_str.h>
45 #define PACKETPTR mblk_t *
46 #include <net/ppp-comp.h>
48 static int ppp_comp_open(), ppp_comp_close();
49 static int ppp_comp_rput(), ppp_comp_wput();
50 static void ppp_comp_ccp();
52 static struct module_info minfo
= {
53 0xbadf, "ppp_compress", 0, INFPSZ
, 16384, 4096,
56 static struct qinit r_init
= {
57 ppp_comp_rput
, NULL
, ppp_comp_open
, ppp_comp_close
,
61 static struct qinit w_init
= {
62 ppp_comp_wput
, NULL
, NULL
, NULL
, NULL
, &minfo
, NULL
65 struct streamtab ppp_compinfo
= {
66 &r_init
, &w_init
, NULL
, NULL
69 struct ppp_comp_state
{
73 struct compressor
*xcomp
;
75 struct compressor
*rcomp
;
79 /* Bits in ccp_state are as defined in ppp_str.h. */
80 #define CCP_ERR (CCP_ERROR | CCP_FATALERROR)
83 * List of compressors we know about.
86 extern struct compressor ppp_bsd_compress
;
88 struct compressor
*ppp_compressors
[] = {
95 strconf_t pppcompconf
= {
96 "pppcomp", &ppp_compinfo
, STR_NEW_OPEN
, 0, SQLVL_DEFAULT
, (void *) 0
99 int pppcomp_load(int cmd
, struct uio
*uiop
)
105 rc
= str_install(STR_LOAD_MOD
, &pppcompconf
);
108 rc
= str_install(STR_UNLOAD_MOD
, &pppcompconf
);
118 ppp_comp_open(q
, dev
, flag
, sflag
)
124 struct ppp_comp_state
*cp
;
126 if (q
->q_ptr
== NULL
) {
127 cp
= (struct ppp_comp_state
*)
128 xmalloc(sizeof(struct ppp_comp_state
), 0, pinned_heap
);
132 bzero(cp
, sizeof(struct ppp_comp_state
));
133 OTHERQ(q
)->q_ptr
= q
->q_ptr
= (caddr_t
) cp
;
147 struct ppp_comp_state
*cp
;
149 cp
= (struct ppp_comp_state
*) q
->q_ptr
;
151 if (cp
->xstate
!= NULL
)
152 (*cp
->xcomp
->comp_free
)(cp
->xstate
);
153 if (cp
->rstate
!= NULL
)
154 (*cp
->rcomp
->decomp_free
)(cp
->rstate
);
155 xmfree(cp
, pinned_heap
);
157 OTHERQ(q
)->q_ptr
= NULL
;
168 struct ppp_comp_state
*cp
;
170 int error
, len
, proto
, state
;
171 struct ppp_option_data
*odp
;
172 struct compressor
**comp
;
173 struct ppp_comp_stats
*pcp
;
175 cp
= (struct ppp_comp_state
*) q
->q_ptr
;
176 switch (mp
->b_datap
->db_type
) {
179 switch (*(u_char
*) mp
->b_rptr
) {
182 mp
= allocb(sizeof(struct ppp_comp_stats
) + sizeof(u_long
),
185 mp
->b_datap
->db_type
= M_CTL
;
186 *(u_char
*) mp
->b_wptr
= IF_CSTATS
;
187 mp
->b_wptr
+= sizeof(u_long
); /* should be enough alignment */
188 pcp
= (struct ppp_comp_stats
*) mp
->b_wptr
;
189 mp
->b_wptr
+= sizeof(struct ppp_comp_stats
);
190 bzero(pcp
, sizeof(struct ppp_comp_stats
));
191 if (cp
->xstate
!= NULL
)
192 (*cp
->xcomp
->comp_stat
)(cp
->xstate
, &pcp
->c
);
193 if (cp
->rstate
!= NULL
)
194 (*cp
->rcomp
->decomp_stat
)(cp
->rstate
, &pcp
->d
);
204 /* first find out what the protocol is */
205 if (mp
->b_wptr
- mp
->b_rptr
>= PPP_HDRLEN
206 || pullupmsg(mp
, PPP_HDRLEN
)) {
207 proto
= PPP_PROTOCOL(mp
->b_rptr
);
208 if (proto
== PPP_CCP
)
209 ppp_comp_ccp(q
, mp
, 0);
210 else if (proto
!= PPP_LCP
&& (cp
->ccp_state
& CCP_COMP_RUN
)
211 && cp
->xstate
!= NULL
) {
213 (*cp
->xcomp
->compress
)(cp
->xstate
, &cmp
, mp
, len
,
214 (cp
->ccp_state
& CCP_ISUP
? len
: 0));
215 /* XXX we really want the MTU here, not len */
226 iop
= (struct iocblk
*) mp
->b_rptr
;
228 switch ((unsigned int)iop
->ioc_cmd
) {
232 if ((iop
->ioc_count
!= sizeof(int)) &&
233 (iop
->ioc_count
!= TRANSPARENT
)) {
237 state
= (*(int *) mp
->b_cont
->b_rptr
) & (CCP_ISUP
| CCP_ISOPEN
);
238 if ((state
& CCP_ISOPEN
) == 0) {
239 if (cp
->xstate
!= NULL
) {
240 (*cp
->xcomp
->comp_free
)(cp
->xstate
);
243 if (cp
->rstate
!= NULL
) {
244 (*cp
->rcomp
->decomp_free
)(cp
->rstate
);
249 cp
->ccp_state
= (cp
->ccp_state
& ~CCP_ISUP
) | state
;
252 bsdlog(LOG_INFO
, "SIOCSIFCOMP %x, state = %x\n",
253 *(int *) mp
->b_cont
->b_rptr
, cp
->ccp_state
);
259 if ((mp
->b_cont
= allocb(sizeof(int), BPRI_MED
)) == NULL
) {
263 *(int *)mp
->b_cont
->b_wptr
= cp
->ccp_state
;
264 mp
->b_cont
->b_wptr
+= iop
->ioc_count
= sizeof(int);
269 if (iop
->ioc_count
!= TRANSPARENT
)
271 odp
= *((struct ppp_option_data
**) mp
->b_cont
->b_rptr
);
272 len
= sizeof(odp
->opt_data
);
273 if (len
> odp
->length
)
275 if (odp
->opt_data
[1] < 2 || odp
->opt_data
[1] > len
)
277 for (comp
= ppp_compressors
; *comp
!= NULL
; ++comp
)
278 if ((*comp
)->compress_proto
== odp
->opt_data
[0]) {
279 /* here's the handler! */
282 if (cp
->xstate
!= NULL
)
283 (*cp
->xcomp
->comp_free
)(cp
->xstate
);
285 cp
->xstate
= (*comp
)->comp_alloc(odp
->opt_data
, len
);
286 if (cp
->xstate
== NULL
)
289 if (cp
->rstate
!= NULL
)
290 (*cp
->rcomp
->decomp_free
)(cp
->rstate
);
292 cp
->rstate
= (*comp
)->decomp_alloc(odp
->opt_data
, len
);
293 if (cp
->rstate
== NULL
)
297 bsdlog(LOG_INFO
, "SIOCSCOMPRESS %s len=%d\n",
298 odp
->transmit
? "xmit": "recv", len
);
305 /* set our debug flag from this */
306 if ((iop
->ioc_count
== TRANSPARENT
) ||
307 (iop
->ioc_count
== sizeof(int))) {
308 cp
->debug
= *(int *) mp
->b_cont
->b_rptr
& 1;
313 /* remember this value */
314 if ((iop
->ioc_count
== TRANSPARENT
) ||
315 (iop
->ioc_count
== sizeof(int))) {
316 cp
->mru
= *(int *) mp
->b_cont
->b_rptr
;
324 else if (error
== 0) {
325 mp
->b_datap
->db_type
= M_IOCACK
;
328 mp
->b_datap
->db_type
= M_IOCNAK
;
346 struct ppp_comp_state
*cp
;
348 cp
= (struct ppp_comp_state
*) q
->q_ptr
;
349 switch (mp
->b_datap
->db_type
) {
352 /* possibly a compressed packet to decompress,
353 or a CCP packet to take notice of. */
354 if (mp
->b_wptr
- mp
->b_rptr
>= PPP_HDRLEN
355 || pullupmsg(mp
, PPP_HDRLEN
)) {
356 proto
= PPP_PROTOCOL(mp
->b_rptr
);
357 if (proto
== PPP_CCP
)
358 ppp_comp_ccp(q
, mp
, 1);
359 else if (proto
== PPP_COMP
) {
360 if ((cp
->ccp_state
& CCP_ISUP
)
361 && (cp
->ccp_state
& CCP_DECOMP_RUN
) && cp
->rstate
362 && (cp
->ccp_state
& CCP_ERR
) == 0) {
363 rv
= (*cp
->rcomp
->decompress
)(cp
->rstate
, mp
, &dmp
);
370 /* no error, but no packet returned */
375 cp
->ccp_state
|= CCP_ERROR
;
377 case DECOMP_FATALERROR
:
378 cp
->ccp_state
|= CCP_FATALERROR
;
383 } else if (cp
->rstate
&& (cp
->ccp_state
& CCP_DECOMP_RUN
)) {
384 (*cp
->rcomp
->incomp
)(cp
->rstate
, mp
);
397 ppp_comp_ccp(q
, mp
, rcvd
)
403 struct ppp_comp_state
*cp
;
407 if (len
< PPP_HDRLEN
+ CCP_HDRLEN
|| !pullupmsg(mp
, len
))
409 cp
= (struct ppp_comp_state
*) q
->q_ptr
;
410 dp
= mp
->b_rptr
+ PPP_HDRLEN
;
412 clen
= CCP_LENGTH(dp
);
416 bsdlog(LOG_INFO
, "CCP %s: code=%x len=%d\n", rcvd
? "rcvd": "sent",
419 switch (CCP_CODE(dp
)) {
423 cp
->ccp_state
&= ~CCP_ISUP
;
427 if ((cp
->ccp_state
& (CCP_ISOPEN
| CCP_ISUP
)) == CCP_ISOPEN
428 && clen
>= CCP_HDRLEN
+ CCP_OPT_MINLEN
429 && clen
>= CCP_HDRLEN
+ CCP_OPT_LENGTH(dp
+ CCP_HDRLEN
)) {
431 if (cp
->xstate
!= NULL
432 && (*cp
->xcomp
->comp_init
)
433 (cp
->xstate
, dp
+ CCP_HDRLEN
, clen
- CCP_HDRLEN
,
434 0, /* XXX: should be unit */ 0,
436 cp
->ccp_state
|= CCP_COMP_RUN
;
438 if (cp
->rstate
!= NULL
439 && (*cp
->rcomp
->decomp_init
)
440 (cp
->rstate
, dp
+ CCP_HDRLEN
, clen
- CCP_HDRLEN
,
441 0/* unit */, 0, cp
->mru
, cp
->debug
))
442 cp
->ccp_state
= (cp
->ccp_state
& ~CCP_ERR
)
449 if (cp
->ccp_state
& CCP_ISUP
) {
451 if (cp
->xstate
&& (cp
->ccp_state
& CCP_COMP_RUN
))
452 (*cp
->xcomp
->comp_reset
)(cp
->xstate
);
454 if (cp
->rstate
&& (cp
->ccp_state
& CCP_DECOMP_RUN
)) {
455 (*cp
->rcomp
->decomp_reset
)(cp
->rstate
);
456 cp
->ccp_state
&= ~CCP_ERROR
;
464 bsdlog(LOG_INFO
, "ccp_state = %x\n", cp
->ccp_state
);