2 * ccp.c - PPP Compression Control Protocol.
6 static char rcsid[] = "$Id: ccp.c,v 1.1 1994/08/11 01:44:32 paulus Exp $";
10 #include <sys/ioctl.h>
18 ccp_options ccp_wantoptions[NPPP]; /* what to request the peer to use */
19 ccp_options ccp_gotoptions[NPPP]; /* what the peer agreed to do */
20 ccp_options ccp_allowoptions[NPPP]; /* what we'll agree to do */
21 ccp_options ccp_hisoptions[NPPP]; /* what we agreed to do */
24 * Callbacks for fsm code.
26 static void ccp_resetci __ARGS((fsm *));
27 static int ccp_cilen __ARGS((fsm *));
28 static void ccp_addci __ARGS((fsm *, u_char *, int *));
29 static int ccp_ackci __ARGS((fsm *, u_char *, int));
30 static int ccp_nakci __ARGS((fsm *, u_char *, int));
31 static int ccp_rejci __ARGS((fsm *, u_char *, int));
32 static int ccp_reqci __ARGS((fsm *, u_char *, int *, int));
33 static void ccp_up __ARGS((fsm *));
34 static void ccp_down __ARGS((fsm *));
35 static int ccp_extcode __ARGS((fsm *, int, int, u_char *, int));
36 static void ccp_rack_timeout __ARGS(());
38 static fsm_callbacks ccp_callbacks = {
57 * Length of configuration options, which describe possible
58 * compression methods.
63 * Configuration option values for compression methods.
65 #define CI_BSD_COMPRESS 0x21
68 * Local state (mainly for handling reset-reqs and reset-acks
70 static int ccp_localstate[NPPP];
71 #define RACK_PENDING 1 /* waiting for reset-ack */
72 #define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
74 #define RACKTIMEOUT 1 /* second */
77 * ccp_init - initialize CCP.
83 fsm *f = &ccp_fsm[unit];
87 f->callbacks = &ccp_callbacks;
90 memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options));
91 memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options));
92 memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
93 memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
95 ccp_wantoptions[0].bsd_bits = 12; /* default value */
97 ccp_allowoptions[0].bsd_compress = 1;
98 ccp_allowoptions[0].bsd_bits = MAX_BSD_BITS;
102 * ccp_open - CCP is allowed to come up.
108 fsm *f = &ccp_fsm[unit];
110 if (f->state != OPENED)
111 ccp_flags_set(unit, 1, 0);
116 * ccp_close - Terminate CCP.
122 ccp_flags_set(unit, 0, 0);
123 fsm_close(&ccp_fsm[unit]);
127 * ccp_lowerup - we may now transmit CCP packets.
133 fsm_lowerup(&ccp_fsm[unit]);
137 * ccp_lowerdown - we may not transmit CCP packets.
143 fsm_lowerdown(&ccp_fsm[unit]);
147 * ccp_input - process a received CCP packet.
150 ccp_input(unit, p, len)
155 fsm_input(&ccp_fsm[unit], p, len);
159 * Handle a CCP-specific code.
162 ccp_extcode(f, code, id, p, len)
170 if (f->state != OPENED)
172 /* send a reset-ack, which the transmitter will see and
173 reset its compression state. */
174 fsm_sdata(f, RESETACK, id, NULL, 0);
178 if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
179 ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
180 UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
192 * ccp_protrej - peer doesn't talk CCP.
198 ccp_flags_set(unit, 0, 0);
199 fsm_lowerdown(&ccp_fsm[unit]);
203 * ccp_resetci - initialize at start of negotiation.
209 ccp_gotoptions[f->unit] = ccp_wantoptions[f->unit];
213 * ccp_cilen - Return total length of our configuration info.
219 ccp_options *go = &ccp_gotoptions[f->unit];
221 return (go->bsd_compress? CILEN_BSD: 0);
225 * ccp_addci - put our requests in a packet.
228 ccp_addci(f, p, lenp)
233 ccp_options *go = &ccp_gotoptions[f->unit];
236 if (go->bsd_compress) {
237 p[0] = CI_BSD_COMPRESS;
246 * ccp_ackci - process a received configure-ack, and return
247 * 1 iff the packet was OK.
255 ccp_options *go = &ccp_gotoptions[f->unit];
257 if (go->bsd_compress) {
258 if (len != 3 || p[0] != CI_BSD_COMPRESS
259 || p[1] != CILEN_BSD || p[2] != go->bsd_bits)
270 * ccp_nakci - process received configure-nak.
271 * Returns 1 iff the nak was OK.
279 ccp_options *go = &ccp_gotoptions[f->unit];
280 ccp_options no; /* options we've seen already */
281 ccp_options try; /* options to ask for next time */
283 memset(&no, 0, sizeof(no));
286 if (go->bsd_compress && len >= CILEN_BSD && p[0] == CI_BSD_COMPRESS
287 && p[1] == CILEN_BSD) {
290 * Peer wants us to use a different number of bits.
292 if (p[2] < go->bsd_bits)
299 * Have a look at any remaining options...???
305 if (f->state != OPENED)
311 * ccp_rejci - reject some of our suggested compression methods.
319 ccp_options *go = &ccp_gotoptions[f->unit];
320 ccp_options try; /* options to request next time */
324 if (go->bsd_compress && len >= CILEN_BSD && p[0] == CI_BSD_COMPRESS
325 && p[1] == CILEN_BSD) {
326 if (p[2] != go->bsd_bits)
328 try.bsd_compress = 0;
336 if (f->state != OPENED)
343 * ccp_reqci - processed a received configure-request.
344 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
348 ccp_reqci(f, p, lenp, dont_nak)
357 ccp_options *ho = &ccp_hisoptions[f->unit];
358 ccp_options *ao = &ccp_allowoptions[f->unit];
364 memset(ho, 0, sizeof(ccp_options));
368 if (len < 2 || p[1] < 2 || p[1] > len) {
378 case CI_BSD_COMPRESS:
379 if (!ao->bsd_compress || clen != CILEN_BSD) {
384 ho->bsd_compress = 1;
386 if (ho->bsd_bits < MIN_BSD_BITS
387 || ho->bsd_bits > ao->bsd_bits) {
390 p[2] = (ho->bsd_bits < MIN_BSD_BITS? MIN_BSD_BITS:
401 if (!(newret == CONFACK || newret == CONFNAK && ret == CONFREJ)) {
402 /* we're returning this option */
408 BCOPY(p, retp, clen);
422 * CCP has come up - inform the kernel driver.
428 ccp_flags_set(f->unit, 1, 1);
432 * CCP has gone down - inform the kernel driver.
438 if (ccp_localstate[f->unit] & RACK_PENDING)
439 UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
440 ccp_localstate[f->unit] = 0;
441 ccp_flags_set(f->unit, 1, 0);
445 * Print the contents of a CCP packet.
447 char *ccp_codenames[] = {
448 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
449 "TermReq", "TermAck", "CodeRej",
450 NULL, NULL, NULL, NULL, NULL, NULL,
451 "ResetReq", "ResetAck",
455 ccp_printpkt(p, plen, printer, arg)
458 void (*printer) __ARGS((void *, char *, ...));
466 if (plen < HEADERLEN)
470 len = (p[2] << 8) + p[3];
471 if (len < HEADERLEN || len > plen)
474 if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
475 && ccp_codenames[code-1] != NULL)
476 printer(arg, " %s", ccp_codenames[code-1]);
478 printer(arg, " code=0x%x", code);
479 printer(arg, " id=0x%x", id);
488 /* print list of possible compression methods */
492 if (optlen < 2 || optlen > len)
498 case CI_BSD_COMPRESS:
499 if (optlen >= CILEN_BSD) {
500 printer(arg, "bsd %d", p[2]);
506 printer(arg, " %.2x", *p++);
512 /* dump out the rest of the packet in hex */
514 printer(arg, " %.2x", *p++);
520 * We have received a packet that the decompressor failed to decompress.
521 * Issue a reset-req (if we haven't issued one recently).
524 ccp_datainput(unit, pkt, len)
532 if (f->state == OPENED) {
533 if (!(ccp_localstate[unit] & RACK_PENDING)) {
534 fsm_sdata(f, RESETREQ, f->reqid = ++f->id, NULL, 0);
535 TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
536 ccp_localstate[unit] |= RACK_PENDING;
538 ccp_localstate[unit] |= RREQ_REPEAT;
543 * Timeout waiting for reset-ack.
546 ccp_rack_timeout(arg)
549 fsm *f = (fsm *) arg;
551 if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
552 fsm_sdata(f, RESETREQ, f->reqid, NULL, 0);
553 TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
554 ccp_localstate[f->unit] &= ~RREQ_REPEAT;
556 ccp_localstate[f->unit] &= ~RACK_PENDING;