xref: /freebsd/usr.sbin/ppp/ccp.c (revision 30c2f2ffe26d680a600fbff9f2fdd2a473905597)
11ae349f5Scvs2svn /*
21ae349f5Scvs2svn  *	   PPP Compression Control Protocol (CCP) Module
31ae349f5Scvs2svn  *
41ae349f5Scvs2svn  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51ae349f5Scvs2svn  *
61ae349f5Scvs2svn  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
71ae349f5Scvs2svn  *
81ae349f5Scvs2svn  * Redistribution and use in source and binary forms are permitted
91ae349f5Scvs2svn  * provided that the above copyright notice and this paragraph are
101ae349f5Scvs2svn  * duplicated in all such forms and that any documentation,
111ae349f5Scvs2svn  * advertising materials, and other materials related to such
121ae349f5Scvs2svn  * distribution and use acknowledge that the software was developed
131ae349f5Scvs2svn  * by the Internet Initiative Japan, Inc.  The name of the
141ae349f5Scvs2svn  * IIJ may not be used to endorse or promote products derived
151ae349f5Scvs2svn  * from this software without specific prior written permission.
161ae349f5Scvs2svn  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
171ae349f5Scvs2svn  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
181ae349f5Scvs2svn  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
191ae349f5Scvs2svn  *
2030c2f2ffSBrian Somers  * $Id: ccp.c,v 1.30.2.20 1998/03/13 21:07:28 brian Exp $
211ae349f5Scvs2svn  *
221ae349f5Scvs2svn  *	TODO:
231ae349f5Scvs2svn  *		o Support other compression protocols
241ae349f5Scvs2svn  */
251ae349f5Scvs2svn #include <sys/param.h>
261ae349f5Scvs2svn #include <netinet/in.h>
271ae349f5Scvs2svn 
281ae349f5Scvs2svn #include <stdio.h>
291ae349f5Scvs2svn #include <string.h>
3085b542cfSBrian Somers #include <termios.h>
311ae349f5Scvs2svn 
321ae349f5Scvs2svn #include "command.h"
331ae349f5Scvs2svn #include "mbuf.h"
341ae349f5Scvs2svn #include "log.h"
351ae349f5Scvs2svn #include "defs.h"
361ae349f5Scvs2svn #include "timer.h"
371ae349f5Scvs2svn #include "fsm.h"
381ae349f5Scvs2svn #include "lcpproto.h"
391ae349f5Scvs2svn #include "lcp.h"
401ae349f5Scvs2svn #include "ccp.h"
411ae349f5Scvs2svn #include "loadalias.h"
421ae349f5Scvs2svn #include "vars.h"
431ae349f5Scvs2svn #include "pred.h"
441ae349f5Scvs2svn #include "deflate.h"
455828db6dSBrian Somers #include "throughput.h"
465828db6dSBrian Somers #include "iplist.h"
475828db6dSBrian Somers #include "ipcp.h"
48455aabc3SBrian Somers #include "bundle.h"
4985b542cfSBrian Somers #include "descriptor.h"
5085b542cfSBrian Somers #include "prompt.h"
51879ed6faSBrian Somers #include "lqr.h"
52503a7782SBrian Somers #include "hdlc.h"
53503a7782SBrian Somers #include "link.h"
54503a7782SBrian Somers #include "chat.h"
55e2ebb036SBrian Somers #include "auth.h"
56e2ebb036SBrian Somers #include "chap.h"
57503a7782SBrian Somers #include "datalink.h"
581ae349f5Scvs2svn 
591ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *);
601ae349f5Scvs2svn static void CcpSendTerminateReq(struct fsm *);
611ae349f5Scvs2svn static void CcpSendTerminateAck(struct fsm *);
6230c2f2ffSBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int,
6330c2f2ffSBrian Somers                             struct fsm_decode *);
641ae349f5Scvs2svn static void CcpLayerStart(struct fsm *);
651ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *);
661ae349f5Scvs2svn static void CcpLayerUp(struct fsm *);
671ae349f5Scvs2svn static void CcpLayerDown(struct fsm *);
681ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *);
69503a7782SBrian Somers static void CcpRecvResetReq(struct fsm *);
70503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char);
711ae349f5Scvs2svn 
7283d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = {
7383d1af55SBrian Somers   CcpLayerUp,
7483d1af55SBrian Somers   CcpLayerDown,
7583d1af55SBrian Somers   CcpLayerStart,
766d666775SBrian Somers   CcpLayerFinish,
7783d1af55SBrian Somers   CcpInitRestartCounter,
7883d1af55SBrian Somers   CcpSendConfigReq,
7983d1af55SBrian Somers   CcpSendTerminateReq,
8083d1af55SBrian Somers   CcpSendTerminateAck,
81503a7782SBrian Somers   CcpDecodeConfig,
82503a7782SBrian Somers   CcpRecvResetReq,
83503a7782SBrian Somers   CcpRecvResetAck
8483d1af55SBrian Somers };
8583d1af55SBrian Somers 
861ae349f5Scvs2svn static char const *cftypes[] = {
871ae349f5Scvs2svn   /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
881ae349f5Scvs2svn   "OUI",		/* 0: OUI */
891ae349f5Scvs2svn   "PRED1",		/* 1: Predictor type 1 */
901ae349f5Scvs2svn   "PRED2",		/* 2: Predictor type 2 */
911ae349f5Scvs2svn   "PUDDLE",		/* 3: Puddle Jumber */
921ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
931ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
941ae349f5Scvs2svn   "HWPPC",		/* 16: Hewlett-Packard PPC */
951ae349f5Scvs2svn   "STAC",		/* 17: Stac Electronics LZS (rfc1974) */
961ae349f5Scvs2svn   "MSPPC",		/* 18: Microsoft PPC */
971ae349f5Scvs2svn   "GAND",		/* 19: Gandalf FZA (rfc1993) */
981ae349f5Scvs2svn   "V42BIS",		/* 20: ARG->DATA.42bis compression */
991ae349f5Scvs2svn   "BSD",		/* 21: BSD LZW Compress */
1001ae349f5Scvs2svn   "???",
1011ae349f5Scvs2svn   "LZS-DCP",		/* 23: LZS-DCP Compression Protocol (rfc1967) */
1021ae349f5Scvs2svn   "MAGNALINK/DEFLATE",	/* 24: Magnalink Variable Resource (rfc1975) */
1031ae349f5Scvs2svn 			/* 24: Deflate (according to pppd-2.3.1) */
1041ae349f5Scvs2svn   "DCE",		/* 25: Data Circuit-Terminating Equip (rfc1976) */
1051ae349f5Scvs2svn   "DEFLATE",		/* 26: Deflate (rfc1979) */
1061ae349f5Scvs2svn };
1071ae349f5Scvs2svn 
1081ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
1091ae349f5Scvs2svn 
1101ae349f5Scvs2svn static const char *
1111ae349f5Scvs2svn protoname(int proto)
1121ae349f5Scvs2svn {
1131ae349f5Scvs2svn   if (proto < 0 || proto > NCFTYPES)
1141ae349f5Scvs2svn     return "none";
1151ae349f5Scvs2svn   return cftypes[proto];
1161ae349f5Scvs2svn }
1171ae349f5Scvs2svn 
1181ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */
1191ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = {
1201ae349f5Scvs2svn   &DeflateAlgorithm,
1211ae349f5Scvs2svn   &Pred1Algorithm,
1221ae349f5Scvs2svn   &PppdDeflateAlgorithm
1231ae349f5Scvs2svn };
1241ae349f5Scvs2svn 
1251ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
1261ae349f5Scvs2svn 
1271ae349f5Scvs2svn int
128503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg)
1291ae349f5Scvs2svn {
130dc0fdb6bSBrian Somers   struct ccp *ccp = arg->cx ? &arg->cx->ccp : bundle2ccp(arg->bundle, NULL);
131503a7782SBrian Somers 
132503a7782SBrian Somers   prompt_Printf(&prompt, "%s [%s]\n", ccp->fsm.name,
133503a7782SBrian Somers                 StateNames[ccp->fsm.state]);
13485b542cfSBrian Somers   prompt_Printf(&prompt, "My protocol = %s, His protocol = %s\n",
135503a7782SBrian Somers                 protoname(ccp->my_proto), protoname(ccp->his_proto));
13685b542cfSBrian Somers   prompt_Printf(&prompt, "Output: %ld --> %ld,  Input: %ld --> %ld\n",
137503a7782SBrian Somers                 ccp->uncompout, ccp->compout,
138503a7782SBrian Somers                 ccp->compin, ccp->uncompin);
1391ae349f5Scvs2svn   return 0;
1401ae349f5Scvs2svn }
1411ae349f5Scvs2svn 
1421ae349f5Scvs2svn void
1436d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l,
1446d666775SBrian Somers          const struct fsm_parent *parent)
1451ae349f5Scvs2svn {
1467308ec68SBrian Somers   /* Initialise ourselves */
147f4768038SBrian Somers   fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, CCP_MAXCODE, 10, LogCCP,
1486d666775SBrian Somers            bundle, l, parent, &ccp_Callbacks);
149503a7782SBrian Somers   ccp_Setup(ccp);
150503a7782SBrian Somers }
151503a7782SBrian Somers 
152503a7782SBrian Somers void
153503a7782SBrian Somers ccp_Setup(struct ccp *ccp)
154503a7782SBrian Somers {
155503a7782SBrian Somers   /* Set ourselves up for a startup */
156503a7782SBrian Somers   ccp->fsm.open_mode = 0;
1575454ccd9SBrian Somers   ccp->fsm.maxconfig = 10;
158503a7782SBrian Somers   ccp->his_proto = ccp->my_proto = -1;
159503a7782SBrian Somers   ccp->reset_sent = ccp->last_reset = -1;
160503a7782SBrian Somers   ccp->in_algorithm = ccp->out_algorithm = -1;
161503a7782SBrian Somers   ccp->his_reject = ccp->my_reject = 0;
162503a7782SBrian Somers   ccp->out_init = ccp->in_init = 0;
163503a7782SBrian Somers   ccp->uncompout = ccp->compout = 0;
164503a7782SBrian Somers   ccp->uncompin = ccp->compin = 0;
1651ae349f5Scvs2svn }
1661ae349f5Scvs2svn 
1671ae349f5Scvs2svn static void
1681ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp)
1691ae349f5Scvs2svn {
1707308ec68SBrian Somers   /* Set fsm timer load */
1711ae349f5Scvs2svn   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1721ae349f5Scvs2svn   fp->restart = 5;
1731ae349f5Scvs2svn }
1741ae349f5Scvs2svn 
1751ae349f5Scvs2svn static void
1761ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp)
1771ae349f5Scvs2svn {
1787308ec68SBrian Somers   /* Send config REQ please */
179aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
18030c2f2ffSBrian Somers   u_char *cp, buff[100];
1811ae349f5Scvs2svn   int f;
1821ae349f5Scvs2svn 
1831ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendConfigReq\n");
18430c2f2ffSBrian Somers   cp = buff;
18583d1af55SBrian Somers   ccp->my_proto = -1;
18683d1af55SBrian Somers   ccp->out_algorithm = -1;
1871ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
18883d1af55SBrian Somers     if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) {
1891ae349f5Scvs2svn       struct lcp_opt o;
1901ae349f5Scvs2svn 
1911ae349f5Scvs2svn       (*algorithm[f]->o.Get)(&o);
19230c2f2ffSBrian Somers       if (cp + o.len > buff + sizeof buff) {
19330c2f2ffSBrian Somers         LogPrintf(LogERROR, "CCP REQ buffer overrun !\n");
19430c2f2ffSBrian Somers         break;
19530c2f2ffSBrian Somers       }
1961ae349f5Scvs2svn       cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
1971ae349f5Scvs2svn                        (*algorithm[f]->Disp)(&o));
19883d1af55SBrian Somers       ccp->my_proto = o.id;
19983d1af55SBrian Somers       ccp->out_algorithm = f;
2001ae349f5Scvs2svn     }
20130c2f2ffSBrian Somers   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, buff, cp - buff);
2021ae349f5Scvs2svn }
2031ae349f5Scvs2svn 
2041ae349f5Scvs2svn void
2051ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp)
2061ae349f5Scvs2svn {
2077308ec68SBrian Somers   /* We can't read our input - ask peer to reset */
208aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2091ae349f5Scvs2svn   LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
21083d1af55SBrian Somers   ccp->reset_sent = fp->reqid;
21183d1af55SBrian Somers   ccp->last_reset = -1;
2121ae349f5Scvs2svn   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
2131ae349f5Scvs2svn }
2141ae349f5Scvs2svn 
2151ae349f5Scvs2svn static void
2161ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp)
2171ae349f5Scvs2svn {
2187308ec68SBrian Somers   /* Term REQ just sent by FSM */
2191ae349f5Scvs2svn }
2201ae349f5Scvs2svn 
2211ae349f5Scvs2svn static void
2221ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp)
2231ae349f5Scvs2svn {
2247308ec68SBrian Somers   /* Send Term ACK please */
2251ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendTerminateAck\n");
2261ae349f5Scvs2svn   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2271ae349f5Scvs2svn }
2281ae349f5Scvs2svn 
229503a7782SBrian Somers static void
2301ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp)
2311ae349f5Scvs2svn {
2327308ec68SBrian Somers   /* Got a reset REQ, reset outgoing dictionary */
233aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
23483d1af55SBrian Somers   if (ccp->out_init)
23583d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Reset)();
2361ae349f5Scvs2svn }
2371ae349f5Scvs2svn 
2381ae349f5Scvs2svn static void
2391ae349f5Scvs2svn CcpLayerStart(struct fsm *fp)
2401ae349f5Scvs2svn {
2417308ec68SBrian Somers   /* We're about to start up ! */
2421ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerStart.\n");
2431ae349f5Scvs2svn }
2441ae349f5Scvs2svn 
2451ae349f5Scvs2svn static void
2461ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp)
2471ae349f5Scvs2svn {
2487308ec68SBrian Somers   /* We're now down */
249aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2501ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerFinish.\n");
25183d1af55SBrian Somers   if (ccp->in_init) {
25283d1af55SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Term)();
25383d1af55SBrian Somers     ccp->in_init = 0;
2547308ec68SBrian Somers   }
25583d1af55SBrian Somers   if (ccp->out_init) {
25683d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Term)();
25783d1af55SBrian Somers     ccp->out_init = 0;
2587308ec68SBrian Somers   }
2591ae349f5Scvs2svn }
2601ae349f5Scvs2svn 
2611ae349f5Scvs2svn static void
2621ae349f5Scvs2svn CcpLayerDown(struct fsm *fp)
2631ae349f5Scvs2svn {
2647308ec68SBrian Somers   /* About to come down */
2651ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerDown.\n");
2661ae349f5Scvs2svn }
2671ae349f5Scvs2svn 
2681ae349f5Scvs2svn /*
2691ae349f5Scvs2svn  *  Called when CCP has reached the OPEN state
2701ae349f5Scvs2svn  */
2711ae349f5Scvs2svn static void
2721ae349f5Scvs2svn CcpLayerUp(struct fsm *fp)
2731ae349f5Scvs2svn {
2747308ec68SBrian Somers   /* We're now up */
275aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
276455aabc3SBrian Somers   LogPrintf(LogCCP, "CcpLayerUp.\n");
27783d1af55SBrian Somers   if (!ccp->in_init && ccp->in_algorithm >= 0 &&
27883d1af55SBrian Somers       ccp->in_algorithm < NALGORITHMS)
27983d1af55SBrian Somers     if ((*algorithm[ccp->in_algorithm]->i.Init)())
28083d1af55SBrian Somers       ccp->in_init = 1;
281247ab36dSBrian Somers     else {
282247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (in) initialisation failure\n",
28383d1af55SBrian Somers                 protoname(ccp->his_proto));
28483d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
285247ab36dSBrian Somers       FsmClose(fp);
286247ab36dSBrian Somers     }
28783d1af55SBrian Somers   if (!ccp->out_init && ccp->out_algorithm >= 0 &&
28883d1af55SBrian Somers       ccp->out_algorithm < NALGORITHMS)
28983d1af55SBrian Somers     if ((*algorithm[ccp->out_algorithm]->o.Init)())
29083d1af55SBrian Somers       ccp->out_init = 1;
291247ab36dSBrian Somers     else {
292247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (out) initialisation failure\n",
29383d1af55SBrian Somers                 protoname(ccp->my_proto));
29483d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
295247ab36dSBrian Somers       FsmClose(fp);
296247ab36dSBrian Somers     }
2971ae349f5Scvs2svn   LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
29883d1af55SBrian Somers             protoname(ccp->my_proto), ccp->my_proto,
29983d1af55SBrian Somers             protoname(ccp->his_proto), ccp->his_proto);
3001ae349f5Scvs2svn }
3011ae349f5Scvs2svn 
3021ae349f5Scvs2svn static void
30330c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
30430c2f2ffSBrian Somers                 struct fsm_decode *dec)
3051ae349f5Scvs2svn {
3067308ec68SBrian Somers   /* Deal with incoming data */
307aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
3081ae349f5Scvs2svn   int type, length;
3091ae349f5Scvs2svn   int f;
3101ae349f5Scvs2svn 
3111ae349f5Scvs2svn   while (plen >= sizeof(struct fsmconfig)) {
3121ae349f5Scvs2svn     type = *cp;
3131ae349f5Scvs2svn     length = cp[1];
3141ae349f5Scvs2svn     if (type < NCFTYPES)
3151ae349f5Scvs2svn       LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
3161ae349f5Scvs2svn     else
3171ae349f5Scvs2svn       LogPrintf(LogCCP, " ???[%d]\n", length);
3181ae349f5Scvs2svn 
3191ae349f5Scvs2svn     for (f = NALGORITHMS-1; f > -1; f--)
3201ae349f5Scvs2svn       if (algorithm[f]->id == type)
3211ae349f5Scvs2svn         break;
3221ae349f5Scvs2svn 
3231ae349f5Scvs2svn     if (f == -1) {
3241ae349f5Scvs2svn       /* Don't understand that :-( */
3251ae349f5Scvs2svn       if (mode_type == MODE_REQ) {
32683d1af55SBrian Somers         ccp->my_reject |= (1 << type);
32730c2f2ffSBrian Somers         memcpy(dec->rejend, cp, length);
32830c2f2ffSBrian Somers         dec->rejend += length;
3291ae349f5Scvs2svn       }
3301ae349f5Scvs2svn     } else {
3311ae349f5Scvs2svn       struct lcp_opt o;
3321ae349f5Scvs2svn 
3331ae349f5Scvs2svn       switch (mode_type) {
3341ae349f5Scvs2svn       case MODE_REQ:
33583d1af55SBrian Somers 	if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) {
3361ae349f5Scvs2svn 	  memcpy(&o, cp, length);
3371ae349f5Scvs2svn           switch ((*algorithm[f]->i.Set)(&o)) {
3381ae349f5Scvs2svn           case MODE_REJ:
33930c2f2ffSBrian Somers 	    memcpy(dec->rejend, &o, o.len);
34030c2f2ffSBrian Somers 	    dec->rejend += o.len;
3411ae349f5Scvs2svn             break;
3421ae349f5Scvs2svn           case MODE_NAK:
34330c2f2ffSBrian Somers 	    memcpy(dec->nakend, &o, o.len);
34430c2f2ffSBrian Somers 	    dec->nakend += o.len;
3451ae349f5Scvs2svn             break;
3461ae349f5Scvs2svn           case MODE_ACK:
34730c2f2ffSBrian Somers 	    memcpy(dec->ackend, cp, length);
34830c2f2ffSBrian Somers 	    dec->ackend += length;
34983d1af55SBrian Somers 	    ccp->his_proto = type;
35083d1af55SBrian Somers             ccp->in_algorithm = f;		/* This one'll do ! */
3511ae349f5Scvs2svn             break;
3521ae349f5Scvs2svn           }
3531ae349f5Scvs2svn 	} else {
35430c2f2ffSBrian Somers 	  memcpy(dec->rejend, cp, length);
35530c2f2ffSBrian Somers 	  dec->rejend += length;
3561ae349f5Scvs2svn 	}
3571ae349f5Scvs2svn 	break;
3581ae349f5Scvs2svn       case MODE_NAK:
3591ae349f5Scvs2svn 	memcpy(&o, cp, length);
3601ae349f5Scvs2svn         if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
36183d1af55SBrian Somers           ccp->my_proto = algorithm[f]->id;
3621ae349f5Scvs2svn         else {
36383d1af55SBrian Somers 	  ccp->his_reject |= (1 << type);
36483d1af55SBrian Somers 	  ccp->my_proto = -1;
3651ae349f5Scvs2svn         }
3661ae349f5Scvs2svn         break;
3671ae349f5Scvs2svn       case MODE_REJ:
36883d1af55SBrian Somers 	ccp->his_reject |= (1 << type);
36983d1af55SBrian Somers 	ccp->my_proto = -1;
3701ae349f5Scvs2svn 	break;
3711ae349f5Scvs2svn       }
3721ae349f5Scvs2svn     }
3731ae349f5Scvs2svn 
3741ae349f5Scvs2svn     plen -= length;
3751ae349f5Scvs2svn     cp += length;
3761ae349f5Scvs2svn   }
3771ae349f5Scvs2svn 
37830c2f2ffSBrian Somers   if (mode_type != MODE_NOP && dec->rejend != dec->rej) {
37930c2f2ffSBrian Somers     dec->ackend = dec->ack;	/* let's not send both ! */
38083d1af55SBrian Somers     if (!ccp->in_init) {
38183d1af55SBrian Somers       ccp->his_proto = -1;
38283d1af55SBrian Somers       ccp->in_algorithm = -1;
383247ab36dSBrian Somers     }
3841ae349f5Scvs2svn   }
3851ae349f5Scvs2svn }
3861ae349f5Scvs2svn 
3871ae349f5Scvs2svn void
388f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp)
3891ae349f5Scvs2svn {
3907308ec68SBrian Somers   /* Got PROTO_CCP from link */
391455aabc3SBrian Somers   if (bundle_Phase(bundle) == PHASE_NETWORK)
392f4768038SBrian Somers     FsmInput(&ccp->fsm, bp);
393455aabc3SBrian Somers   else if (bundle_Phase(bundle) < PHASE_NETWORK) {
394455aabc3SBrian Somers     LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n",
395455aabc3SBrian Somers               bundle_PhaseName(bundle));
3961ae349f5Scvs2svn     pfree(bp);
3971ae349f5Scvs2svn   }
3981ae349f5Scvs2svn }
3991ae349f5Scvs2svn 
400503a7782SBrian Somers static void
401503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id)
4021ae349f5Scvs2svn {
4037308ec68SBrian Somers   /* Got a reset ACK, reset incoming dictionary */
404f4768038SBrian Somers   struct ccp *ccp = fsm2ccp(fp);
405f4768038SBrian Somers 
406f4768038SBrian Somers   if (ccp->reset_sent != -1) {
407f4768038SBrian Somers     if (id != ccp->reset_sent) {
4081ae349f5Scvs2svn       LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
409f4768038SBrian Somers                 id, ccp->reset_sent);
4101ae349f5Scvs2svn       return;
4111ae349f5Scvs2svn     }
4121ae349f5Scvs2svn     /* Whaddaya know - a correct reset ack */
413f4768038SBrian Somers   } else if (id == ccp->last_reset)
4141ae349f5Scvs2svn     LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
4151ae349f5Scvs2svn   else {
4161ae349f5Scvs2svn     LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
4171ae349f5Scvs2svn     return;
4181ae349f5Scvs2svn   }
4191ae349f5Scvs2svn 
420f4768038SBrian Somers   ccp->last_reset = ccp->reset_sent;
421f4768038SBrian Somers   ccp->reset_sent = -1;
422f4768038SBrian Somers   if (ccp->in_init)
423f4768038SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Reset)();
4241ae349f5Scvs2svn }
4251ae349f5Scvs2svn 
4261ae349f5Scvs2svn int
427503a7782SBrian Somers ccp_Output(struct ccp *ccp, struct link *l, int pri, u_short proto,
428503a7782SBrian Somers            struct mbuf *m)
4291ae349f5Scvs2svn {
430503a7782SBrian Somers   /* Compress outgoing Network Layer data */
431503a7782SBrian Somers   if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && ccp->out_init)
432f4768038SBrian Somers     return (*algorithm[ccp->out_algorithm]->o.Write)(ccp, l, pri, proto, m);
4331ae349f5Scvs2svn   return 0;
4341ae349f5Scvs2svn }
4351ae349f5Scvs2svn 
4361ae349f5Scvs2svn struct mbuf *
437503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp)
4381ae349f5Scvs2svn {
439ee6c193fSBrian Somers   /*
440ee6c193fSBrian Somers    * If proto isn't PROTO_COMPD, we still want to pass it to the
441ee6c193fSBrian Somers    * decompression routines so that the dictionary's updated
442ee6c193fSBrian Somers    */
443503a7782SBrian Somers   if (ccp->fsm.state == ST_OPENED)
444ee6c193fSBrian Somers     if (*proto == PROTO_COMPD) {
4457308ec68SBrian Somers       /* Decompress incoming data */
446503a7782SBrian Somers       if (ccp->reset_sent != -1) {
4471ae349f5Scvs2svn         /* Send another REQ and put the packet in the bit bucket */
448503a7782SBrian Somers         LogPrintf(LogCCP, "ReSendResetReq(%d)\n", ccp->reset_sent);
449503a7782SBrian Somers         FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0);
450503a7782SBrian Somers       } else if (ccp->in_init)
451f4768038SBrian Somers         return (*algorithm[ccp->in_algorithm]->i.Read)(ccp, proto, bp);
452ee6c193fSBrian Somers       pfree(bp);
453ee6c193fSBrian Somers       bp = NULL;
454503a7782SBrian Somers     } else if ((*proto & 0xfff1) == 0x21 && ccp->in_init)
455ee6c193fSBrian Somers       /* Add incoming Network Layer traffic to our dictionary */
456f4768038SBrian Somers       (*algorithm[ccp->in_algorithm]->i.DictSetup)(ccp, *proto, bp);
4571ae349f5Scvs2svn 
458ee6c193fSBrian Somers   return bp;
4591ae349f5Scvs2svn }
460