xref: /freebsd/usr.sbin/ppp/ccp.c (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
5  *          based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
6  *                           Internet Initiative Japan, Inc (IIJ)
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32 
33 #include <sys/param.h>
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/ip.h>
37 #include <sys/socket.h>
38 #include <sys/un.h>
39 
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>	/* memcpy() on some archs */
44 #include <termios.h>
45 
46 #include "layer.h"
47 #include "defs.h"
48 #include "command.h"
49 #include "mbuf.h"
50 #include "log.h"
51 #include "timer.h"
52 #include "fsm.h"
53 #include "proto.h"
54 #include "pred.h"
55 #include "deflate.h"
56 #include "throughput.h"
57 #include "iplist.h"
58 #include "slcompress.h"
59 #include "lqr.h"
60 #include "hdlc.h"
61 #include "lcp.h"
62 #include "ccp.h"
63 #include "ncpaddr.h"
64 #include "ipcp.h"
65 #include "filter.h"
66 #include "descriptor.h"
67 #include "prompt.h"
68 #include "link.h"
69 #include "mp.h"
70 #include "async.h"
71 #include "physical.h"
72 #ifndef NORADIUS
73 #include "radius.h"
74 #endif
75 #ifndef NODES
76 #include "mppe.h"
77 #endif
78 #include "ipv6cp.h"
79 #include "ncp.h"
80 #include "bundle.h"
81 
82 static void CcpSendConfigReq(struct fsm *);
83 static void CcpSentTerminateReq(struct fsm *);
84 static void CcpSendTerminateAck(struct fsm *, u_char);
85 static void CcpDecodeConfig(struct fsm *, u_char *, u_char *, int,
86                             struct fsm_decode *);
87 static void CcpLayerStart(struct fsm *);
88 static void CcpLayerFinish(struct fsm *);
89 static int CcpLayerUp(struct fsm *);
90 static void CcpLayerDown(struct fsm *);
91 static void CcpInitRestartCounter(struct fsm *, int);
92 static int CcpRecvResetReq(struct fsm *);
93 static void CcpRecvResetAck(struct fsm *, u_char);
94 
95 static struct fsm_callbacks ccp_Callbacks = {
96   CcpLayerUp,
97   CcpLayerDown,
98   CcpLayerStart,
99   CcpLayerFinish,
100   CcpInitRestartCounter,
101   CcpSendConfigReq,
102   CcpSentTerminateReq,
103   CcpSendTerminateAck,
104   CcpDecodeConfig,
105   CcpRecvResetReq,
106   CcpRecvResetAck
107 };
108 
109 static const char * const ccp_TimerNames[] =
110   {"CCP restart", "CCP openmode", "CCP stopped"};
111 
112 static const char *
113 protoname(int proto)
114 {
115   static char const * const cftypes[] = {
116     /* Check out the latest ``Compression Control Protocol'' rfc (1962) */
117     "OUI",		/* 0: OUI */
118     "PRED1",		/* 1: Predictor type 1 */
119     "PRED2",		/* 2: Predictor type 2 */
120     "PUDDLE",		/* 3: Puddle Jumber */
121     NULL, NULL, NULL, NULL, NULL, NULL,
122     NULL, NULL, NULL, NULL, NULL, NULL,
123     "HWPPC",		/* 16: Hewlett-Packard PPC */
124     "STAC",		/* 17: Stac Electronics LZS (rfc1974) */
125     "MPPE",		/* 18: Microsoft PPC (rfc2118) and */
126 			/*     Microsoft PPE (draft-ietf-pppext-mppe) */
127     "GAND",		/* 19: Gandalf FZA (rfc1993) */
128     "V42BIS",		/* 20: ARG->DATA.42bis compression */
129     "BSD",		/* 21: BSD LZW Compress */
130     NULL,
131     "LZS-DCP",		/* 23: LZS-DCP Compression Protocol (rfc1967) */
132     "MAGNALINK/DEFLATE",/* 24: Magnalink Variable Resource (rfc1975) */
133 			/* 24: Deflate (according to pppd-2.3.*) */
134     "DCE",		/* 25: Data Circuit-Terminating Equip (rfc1976) */
135     "DEFLATE",		/* 26: Deflate (rfc1979) */
136   };
137 
138   if (proto < 0 || (unsigned)proto > sizeof cftypes / sizeof *cftypes ||
139       cftypes[proto] == NULL) {
140     if (proto == -1)
141       return "none";
142     return HexStr(proto, NULL, 0);
143   }
144 
145   return cftypes[proto];
146 }
147 
148 /* We support these algorithms, and Req them in the given order */
149 static const struct ccp_algorithm * const algorithm[] = {
150   &DeflateAlgorithm,
151   &Pred1Algorithm,
152   &PppdDeflateAlgorithm
153 #ifndef NODES
154   , &MPPEAlgorithm
155 #endif
156 };
157 
158 #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
159 
160 int
161 ccp_ReportStatus(struct cmdargs const *arg)
162 {
163   struct ccp_opt **o;
164   struct link *l;
165   struct ccp *ccp;
166   int f;
167 
168   l = command_ChooseLink(arg);
169   ccp = &l->ccp;
170 
171   prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name,
172                 State2Nam(ccp->fsm.state));
173   if (ccp->fsm.state == ST_OPENED) {
174     prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n",
175                   protoname(ccp->my_proto), protoname(ccp->his_proto));
176     prompt_Printf(arg->prompt, " Output: %ld --> %ld,  Input: %ld --> %ld\n",
177                   ccp->uncompout, ccp->compout,
178                   ccp->compin, ccp->uncompin);
179   }
180 
181   if (ccp->in.algorithm != -1)
182     prompt_Printf(arg->prompt, "\n Input Options:  %s\n",
183                   (*algorithm[ccp->in.algorithm]->Disp)(&ccp->in.opt));
184 
185   if (ccp->out.algorithm != -1) {
186     o = &ccp->out.opt;
187     for (f = 0; f < ccp->out.algorithm; f++)
188       if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]))
189         o = &(*o)->next;
190     prompt_Printf(arg->prompt, " Output Options: %s\n",
191                   (*algorithm[ccp->out.algorithm]->Disp)(&(*o)->val));
192   }
193 
194   prompt_Printf(arg->prompt, "\n Defaults: ");
195   prompt_Printf(arg->prompt, "FSM retry = %us, max %u Config"
196                 " REQ%s, %u Term REQ%s\n", ccp->cfg.fsm.timeout,
197                 ccp->cfg.fsm.maxreq, ccp->cfg.fsm.maxreq == 1 ? "" : "s",
198                 ccp->cfg.fsm.maxtrm, ccp->cfg.fsm.maxtrm == 1 ? "" : "s");
199   prompt_Printf(arg->prompt, "           deflate windows: ");
200   prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize);
201   prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize);
202 #ifndef NODES
203   prompt_Printf(arg->prompt, "           MPPE: ");
204   if (ccp->cfg.mppe.keybits)
205     prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits);
206   else
207     prompt_Printf(arg->prompt, "any bits, ");
208   switch (ccp->cfg.mppe.state) {
209   case MPPE_STATEFUL:
210     prompt_Printf(arg->prompt, "stateful");
211     break;
212   case MPPE_STATELESS:
213     prompt_Printf(arg->prompt, "stateless");
214     break;
215   case MPPE_ANYSTATE:
216     prompt_Printf(arg->prompt, "any state");
217     break;
218   }
219   prompt_Printf(arg->prompt, "%s\n",
220                 ccp->cfg.mppe.required ? ", required" : "");
221 #endif
222 
223   prompt_Printf(arg->prompt, "\n           DEFLATE:    %s\n",
224                 command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE]));
225   prompt_Printf(arg->prompt, "           PREDICTOR1: %s\n",
226                 command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1]));
227   prompt_Printf(arg->prompt, "           DEFLATE24:  %s\n",
228                 command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24]));
229 #ifndef NODES
230   prompt_Printf(arg->prompt, "           MPPE:       %s\n",
231                 command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE]));
232 #endif
233   return 0;
234 }
235 
236 void
237 ccp_SetupCallbacks(struct ccp *ccp)
238 {
239   ccp->fsm.fn = &ccp_Callbacks;
240   ccp->fsm.FsmTimer.name = ccp_TimerNames[0];
241   ccp->fsm.OpenTimer.name = ccp_TimerNames[1];
242   ccp->fsm.StoppedTimer.name = ccp_TimerNames[2];
243 }
244 
245 void
246 ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l,
247          const struct fsm_parent *parent)
248 {
249   /* Initialise ourselves */
250 
251   fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, LogCCP,
252            bundle, l, parent, &ccp_Callbacks, ccp_TimerNames);
253 
254   ccp->cfg.deflate.in.winsize = 0;
255   ccp->cfg.deflate.out.winsize = 15;
256   ccp->cfg.fsm.timeout = DEF_FSMRETRY;
257   ccp->cfg.fsm.maxreq = DEF_FSMTRIES;
258   ccp->cfg.fsm.maxtrm = DEF_FSMTRIES;
259   ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED;
260   ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED;
261   ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0;
262 #ifndef NODES
263   ccp->cfg.mppe.keybits = 0;
264   ccp->cfg.mppe.state = MPPE_ANYSTATE;
265   ccp->cfg.mppe.required = 0;
266   ccp->cfg.neg[CCP_NEG_MPPE] = NEG_ENABLED|NEG_ACCEPTED;
267 #endif
268 
269   ccp_Setup(ccp);
270 }
271 
272 void
273 ccp_Setup(struct ccp *ccp)
274 {
275   /* Set ourselves up for a startup */
276   ccp->fsm.open_mode = 0;
277   ccp->his_proto = ccp->my_proto = -1;
278   ccp->reset_sent = ccp->last_reset = -1;
279   ccp->in.algorithm = ccp->out.algorithm = -1;
280   ccp->in.state = ccp->out.state = NULL;
281   ccp->in.opt.hdr.id = -1;
282   ccp->out.opt = NULL;
283   ccp->his_reject = ccp->my_reject = 0;
284   ccp->uncompout = ccp->compout = 0;
285   ccp->uncompin = ccp->compin = 0;
286 }
287 
288 /*
289  * Is ccp *REQUIRED* ?
290  * We ask each of the configured ccp protocols if they're required and
291  * return TRUE if they are.
292  *
293  * It's not possible for the peer to reject a required ccp protocol
294  * without our state machine bringing the supporting lcp layer down.
295  *
296  * If ccp is required but not open, the NCP layer should not push
297  * any data into the link.
298  */
299 int
300 ccp_Required(struct ccp *ccp)
301 {
302   unsigned f;
303 
304   for (f = 0; f < NALGORITHMS; f++)
305     if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) &&
306         (*algorithm[f]->Required)(&ccp->fsm))
307       return 1;
308 
309   return 0;
310 }
311 
312 /*
313  * Report whether it's possible to increase a packet's size after
314  * compression (and by how much).
315  */
316 int
317 ccp_MTUOverhead(struct ccp *ccp)
318 {
319   if (ccp->fsm.state == ST_OPENED && ccp->out.algorithm >= 0)
320     return algorithm[ccp->out.algorithm]->o.MTUOverhead;
321 
322   return 0;
323 }
324 
325 static void
326 CcpInitRestartCounter(struct fsm *fp, int what)
327 {
328   /* Set fsm timer load */
329   struct ccp *ccp = fsm2ccp(fp);
330 
331   fp->FsmTimer.load = ccp->cfg.fsm.timeout * SECTICKS;
332   switch (what) {
333     case FSM_REQ_TIMER:
334       fp->restart = ccp->cfg.fsm.maxreq;
335       break;
336     case FSM_TRM_TIMER:
337       fp->restart = ccp->cfg.fsm.maxtrm;
338       break;
339     default:
340       fp->restart = 1;
341       break;
342   }
343 }
344 
345 static void
346 CcpSendConfigReq(struct fsm *fp)
347 {
348   /* Send config REQ please */
349   struct ccp *ccp = fsm2ccp(fp);
350   struct ccp_opt **o;
351   u_char *cp, buff[100];
352   unsigned f;
353   int alloc;
354 
355   cp = buff;
356   o = &ccp->out.opt;
357   alloc = ccp->his_reject == 0 && ccp->out.opt == NULL;
358   ccp->my_proto = -1;
359   ccp->out.algorithm = -1;
360   for (f = 0; f < NALGORITHMS; f++)
361     if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) &&
362         !REJECTED(ccp, algorithm[f]->id) &&
363         (*algorithm[f]->Usable)(fp)) {
364 
365       if (!alloc)
366         for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next)
367           if ((*o)->val.hdr.id == algorithm[f]->id && (*o)->algorithm == (int)f)
368             break;
369 
370       if (alloc || *o == NULL) {
371         if ((*o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt))) == NULL) {
372 	  log_Printf(LogERROR, "%s: Not enough memory for CCP REQ !\n",
373 		     fp->link->name);
374 	  break;
375 	}
376         (*o)->val.hdr.id = algorithm[f]->id;
377         (*o)->val.hdr.len = 2;
378         (*o)->next = NULL;
379         (*o)->algorithm = f;
380         (*algorithm[f]->o.OptInit)(fp->bundle, &(*o)->val, &ccp->cfg);
381       }
382 
383       if (cp + (*o)->val.hdr.len > buff + sizeof buff) {
384         log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name);
385         break;
386       }
387       memcpy(cp, &(*o)->val, (*o)->val.hdr.len);
388       cp += (*o)->val.hdr.len;
389 
390       ccp->my_proto = (*o)->val.hdr.id;
391       ccp->out.algorithm = f;
392 
393       if (alloc)
394         o = &(*o)->next;
395     }
396 
397   fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT);
398 }
399 
400 void
401 ccp_SendResetReq(struct fsm *fp)
402 {
403   /* We can't read our input - ask peer to reset */
404   struct ccp *ccp = fsm2ccp(fp);
405 
406   ccp->reset_sent = fp->reqid;
407   ccp->last_reset = -1;
408   fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT);
409 }
410 
411 static void
412 CcpSentTerminateReq(struct fsm *fp __unused)
413 {
414   /* Term REQ just sent by FSM */
415 }
416 
417 static void
418 CcpSendTerminateAck(struct fsm *fp, u_char id)
419 {
420   /* Send Term ACK please */
421   fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT);
422 }
423 
424 static int
425 CcpRecvResetReq(struct fsm *fp)
426 {
427   /* Got a reset REQ, reset outgoing dictionary */
428   struct ccp *ccp = fsm2ccp(fp);
429   if (ccp->out.state == NULL)
430     return 1;
431   return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state);
432 }
433 
434 static void
435 CcpLayerStart(struct fsm *fp)
436 {
437   /* We're about to start up ! */
438   struct ccp *ccp = fsm2ccp(fp);
439 
440   log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name);
441   fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3;
442 }
443 
444 static void
445 CcpLayerDown(struct fsm *fp)
446 {
447   /* About to come down */
448   struct ccp *ccp = fsm2ccp(fp);
449   struct ccp_opt *next;
450 
451   log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name);
452   if (ccp->in.state != NULL) {
453     (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state);
454     ccp->in.state = NULL;
455     ccp->in.algorithm = -1;
456   }
457   if (ccp->out.state != NULL) {
458     (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state);
459     ccp->out.state = NULL;
460     ccp->out.algorithm = -1;
461   }
462   ccp->his_reject = ccp->my_reject = 0;
463 
464   while (ccp->out.opt) {
465     next = ccp->out.opt->next;
466     free(ccp->out.opt);
467     ccp->out.opt = next;
468   }
469   ccp_Setup(ccp);
470 }
471 
472 static void
473 CcpLayerFinish(struct fsm *fp)
474 {
475   /* We're now down */
476   struct ccp *ccp = fsm2ccp(fp);
477   struct ccp_opt *next;
478 
479   log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name);
480 
481   /*
482    * Nuke options that may be left over from sending a REQ but never
483    * coming up.
484    */
485   while (ccp->out.opt) {
486     next = ccp->out.opt->next;
487     free(ccp->out.opt);
488     ccp->out.opt = next;
489   }
490 
491   if (ccp_Required(ccp)) {
492     if (fp->link->lcp.fsm.state == ST_OPENED)
493       log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name);
494     fsm_Close(&fp->link->lcp.fsm);
495   }
496 }
497 
498 /*  Called when CCP has reached the OPEN state */
499 static int
500 CcpLayerUp(struct fsm *fp)
501 {
502   /* We're now up */
503   struct ccp *ccp = fsm2ccp(fp);
504   struct ccp_opt **o;
505   unsigned f, fail;
506 
507   for (f = fail = 0; f < NALGORITHMS; f++)
508     if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) &&
509         (*algorithm[f]->Required)(&ccp->fsm) &&
510         (ccp->in.algorithm != (int)f || ccp->out.algorithm != (int)f)) {
511       /* Blow it all away - we haven't negotiated a required algorithm */
512       log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n",
513                  fp->link->name, protoname(algorithm[f]->id));
514       fail = 1;
515     }
516 
517   if (fail) {
518     ccp->his_proto = ccp->my_proto = -1;
519     fsm_Close(fp);
520     fsm_Close(&fp->link->lcp.fsm);
521     return 0;
522   }
523 
524   log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name);
525 
526   if (ccp->in.state == NULL && ccp->in.algorithm >= 0 &&
527       ccp->in.algorithm < (int)NALGORITHMS) {
528     ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)
529       (fp->bundle, &ccp->in.opt);
530     if (ccp->in.state == NULL) {
531       log_Printf(LogERROR, "%s: %s (in) initialisation failure\n",
532                 fp->link->name, protoname(ccp->his_proto));
533       ccp->his_proto = ccp->my_proto = -1;
534       fsm_Close(fp);
535       return 0;
536     }
537   }
538 
539   o = &ccp->out.opt;
540   if (ccp->out.algorithm > 0)
541     for (f = 0; f < (unsigned)ccp->out.algorithm; f++)
542       if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]))
543 	o = &(*o)->next;
544 
545   if (ccp->out.state == NULL && ccp->out.algorithm >= 0 &&
546       ccp->out.algorithm < (int)NALGORITHMS) {
547     ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)
548       (fp->bundle, &(*o)->val);
549     if (ccp->out.state == NULL) {
550       log_Printf(LogERROR, "%s: %s (out) initialisation failure\n",
551                 fp->link->name, protoname(ccp->my_proto));
552       ccp->his_proto = ccp->my_proto = -1;
553       fsm_Close(fp);
554       return 0;
555     }
556   }
557 
558   fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3;
559 
560   log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n",
561             fp->link->name, protoname(ccp->my_proto), ccp->my_proto,
562             protoname(ccp->his_proto), ccp->his_proto);
563 
564   return 1;
565 }
566 
567 static void
568 CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
569                 struct fsm_decode *dec)
570 {
571   /* Deal with incoming data */
572   struct ccp *ccp = fsm2ccp(fp);
573   int f;
574   const char *disp;
575   struct fsm_opt *opt;
576 
577   if (mode_type == MODE_REQ)
578     ccp->in.algorithm = -1;	/* In case we've received two REQs in a row */
579 
580   while (end >= cp + sizeof(opt->hdr)) {
581     if ((opt = fsm_readopt(&cp)) == NULL)
582       break;
583 
584     for (f = NALGORITHMS-1; f > -1; f--)
585       if (algorithm[f]->id == opt->hdr.id)
586         break;
587 
588     disp = f == -1 ? "" : (*algorithm[f]->Disp)(opt);
589     if (disp == NULL)
590       disp = "";
591 
592     log_Printf(LogCCP, " %s[%d] %s\n", protoname(opt->hdr.id),
593                opt->hdr.len, disp);
594 
595     if (f == -1) {
596       /* Don't understand that :-( */
597       if (mode_type == MODE_REQ) {
598         ccp->my_reject |= (1 << opt->hdr.id);
599         fsm_rej(dec, opt);
600       }
601     } else {
602       struct ccp_opt *o;
603 
604       switch (mode_type) {
605       case MODE_REQ:
606         if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) &&
607             (*algorithm[f]->Usable)(fp) &&
608             ccp->in.algorithm == -1) {
609           memcpy(&ccp->in.opt, opt, opt->hdr.len);
610           switch ((*algorithm[f]->i.Set)(fp->bundle, &ccp->in.opt, &ccp->cfg)) {
611           case MODE_REJ:
612             fsm_rej(dec, &ccp->in.opt);
613             break;
614           case MODE_NAK:
615             fsm_nak(dec, &ccp->in.opt);
616             break;
617           case MODE_ACK:
618             fsm_ack(dec, &ccp->in.opt);
619             ccp->his_proto = opt->hdr.id;
620             ccp->in.algorithm = (int)f;		/* This one'll do :-) */
621             break;
622           }
623         } else {
624           fsm_rej(dec, opt);
625         }
626         break;
627       case MODE_NAK:
628         for (o = ccp->out.opt; o != NULL; o = o->next)
629           if (o->val.hdr.id == opt->hdr.id)
630             break;
631         if (o == NULL)
632           log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent"
633                      " option\n", fp->link->name);
634         else {
635           memcpy(&o->val, opt, opt->hdr.len);
636           if ((*algorithm[f]->o.Set)(fp->bundle, &o->val, &ccp->cfg) ==
637               MODE_ACK)
638             ccp->my_proto = algorithm[f]->id;
639           else {
640             ccp->his_reject |= (1 << opt->hdr.id);
641             ccp->my_proto = -1;
642             if (algorithm[f]->Required(fp)) {
643               log_Printf(LogWARN, "%s: Cannot understand peers (required)"
644                          " %s negotiation\n", fp->link->name,
645                          protoname(algorithm[f]->id));
646               fsm_Close(&fp->link->lcp.fsm);
647             }
648           }
649         }
650         break;
651       case MODE_REJ:
652         ccp->his_reject |= (1 << opt->hdr.id);
653         ccp->my_proto = -1;
654         if (algorithm[f]->Required(fp)) {
655           log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n",
656                      fp->link->name, protoname(algorithm[f]->id));
657           fsm_Close(&fp->link->lcp.fsm);
658         }
659         break;
660       }
661     }
662   }
663 
664   if (mode_type != MODE_NOP) {
665     fsm_opt_normalise(dec);
666     if (dec->rejend != dec->rej || dec->nakend != dec->nak) {
667       if (ccp->in.state == NULL) {
668         ccp->his_proto = -1;
669         ccp->in.algorithm = -1;
670       }
671     }
672   }
673 }
674 
675 extern struct mbuf *
676 ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
677 {
678   /* Got PROTO_CCP from link */
679   m_settype(bp, MB_CCPIN);
680   if (bundle_Phase(bundle) == PHASE_NETWORK)
681     fsm_Input(&l->ccp.fsm, bp);
682   else {
683     if (bundle_Phase(bundle) < PHASE_NETWORK)
684       log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n",
685                  l->ccp.fsm.link->name, bundle_PhaseName(bundle));
686     m_freem(bp);
687   }
688   return NULL;
689 }
690 
691 static void
692 CcpRecvResetAck(struct fsm *fp, u_char id)
693 {
694   /* Got a reset ACK, reset incoming dictionary */
695   struct ccp *ccp = fsm2ccp(fp);
696 
697   if (ccp->reset_sent != -1) {
698     if (id != ccp->reset_sent) {
699       log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)"
700                 " ignored\n", fp->link->name, id, ccp->reset_sent);
701       return;
702     }
703     /* Whaddaya know - a correct reset ack */
704   } else if (id == ccp->last_reset)
705     log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n",
706                fp->link->name);
707   else {
708     log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n",
709                fp->link->name, id);
710     return;
711   }
712 
713   ccp->last_reset = ccp->reset_sent;
714   ccp->reset_sent = -1;
715   if (ccp->in.state != NULL)
716     (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state);
717 }
718 
719 static struct mbuf *
720 ccp_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp,
721               int pri, u_short *proto)
722 {
723   if (PROTO_COMPRESSIBLE(*proto)) {
724     if (l->ccp.fsm.state != ST_OPENED) {
725       if (ccp_Required(&l->ccp)) {
726         /* The NCP layer shouldn't have let this happen ! */
727         log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and"
728                    " required CCP layer\n", l->name);
729         m_freem(bp);
730         bp = NULL;
731       }
732     } else if (l->ccp.out.state != NULL) {
733       bp = (*algorithm[l->ccp.out.algorithm]->o.Write)
734              (l->ccp.out.state, &l->ccp, l, pri, proto, bp);
735       switch (*proto) {
736         case PROTO_ICOMPD:
737           m_settype(bp, MB_ICOMPDOUT);
738           break;
739         case PROTO_COMPD:
740           m_settype(bp, MB_COMPDOUT);
741           break;
742       }
743     }
744   }
745 
746   return bp;
747 }
748 
749 static struct mbuf *
750 ccp_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp,
751 	      u_short *proto)
752 {
753   /*
754    * If proto isn't PROTO_[I]COMPD, we still want to pass it to the
755    * decompression routines so that the dictionary's updated
756    */
757   if (l->ccp.fsm.state == ST_OPENED) {
758     if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) {
759       /* Decompress incoming data */
760       if (l->ccp.reset_sent != -1)
761         /* Send another REQ and put the packet in the bit bucket */
762         fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0,
763                    MB_CCPOUT);
764       else if (l->ccp.in.state != NULL) {
765         bp = (*algorithm[l->ccp.in.algorithm]->i.Read)
766                (l->ccp.in.state, &l->ccp, proto, bp);
767         switch (*proto) {
768           case PROTO_ICOMPD:
769             m_settype(bp, MB_ICOMPDIN);
770             break;
771           case PROTO_COMPD:
772             m_settype(bp, MB_COMPDIN);
773             break;
774         }
775         return bp;
776       }
777       m_freem(bp);
778       bp = NULL;
779     } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) {
780       /* Add incoming Network Layer traffic to our dictionary */
781       (*algorithm[l->ccp.in.algorithm]->i.DictSetup)
782         (l->ccp.in.state, &l->ccp, *proto, bp);
783     }
784   }
785 
786   return bp;
787 }
788 
789 u_short
790 ccp_Proto(struct ccp *ccp)
791 {
792   return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ?
793          PROTO_COMPD : PROTO_ICOMPD;
794 }
795 
796 int
797 ccp_SetOpenMode(struct ccp *ccp)
798 {
799   int f;
800 
801   for (f = 0; f < CCP_NEG_TOTAL; f++)
802     if (IsEnabled(ccp->cfg.neg[f])) {
803       ccp->fsm.open_mode = 0;
804       return 1;
805     }
806 
807   ccp->fsm.open_mode = OPEN_PASSIVE;	/* Go straight to ST_STOPPED ? */
808 
809   for (f = 0; f < CCP_NEG_TOTAL; f++)
810     if (IsAccepted(ccp->cfg.neg[f]))
811       return 1;
812 
813   return 0;				/* No CCP at all */
814 }
815 
816 int
817 ccp_DefaultUsable(struct fsm *fp __unused)
818 {
819   return 1;
820 }
821 
822 int
823 ccp_DefaultRequired(struct fsm *fp __unused)
824 {
825   return 0;
826 }
827 
828 struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull };
829