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