xref: /freebsd/usr.sbin/ppp/ccp.c (revision aad81d1ecfec3906f8b4e6945d6967a82c391cd5)
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  *
20aad81d1eSBrian Somers  * $Id: ccp.c,v 1.30.2.7 1998/02/07 20:49:26 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>
301ae349f5Scvs2svn 
311ae349f5Scvs2svn #include "command.h"
321ae349f5Scvs2svn #include "mbuf.h"
331ae349f5Scvs2svn #include "log.h"
341ae349f5Scvs2svn #include "defs.h"
351ae349f5Scvs2svn #include "timer.h"
361ae349f5Scvs2svn #include "fsm.h"
371ae349f5Scvs2svn #include "lcpproto.h"
381ae349f5Scvs2svn #include "lcp.h"
391ae349f5Scvs2svn #include "ccp.h"
401ae349f5Scvs2svn #include "loadalias.h"
411ae349f5Scvs2svn #include "vars.h"
421ae349f5Scvs2svn #include "pred.h"
431ae349f5Scvs2svn #include "deflate.h"
44455aabc3SBrian Somers #include "bundle.h"
451ae349f5Scvs2svn 
461ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *);
471ae349f5Scvs2svn static void CcpSendTerminateReq(struct fsm *);
481ae349f5Scvs2svn static void CcpSendTerminateAck(struct fsm *);
4983d1af55SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int);
501ae349f5Scvs2svn static void CcpLayerStart(struct fsm *);
511ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *);
521ae349f5Scvs2svn static void CcpLayerUp(struct fsm *);
531ae349f5Scvs2svn static void CcpLayerDown(struct fsm *);
541ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *);
551ae349f5Scvs2svn 
5683d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = {
5783d1af55SBrian Somers   CcpLayerUp,
5883d1af55SBrian Somers   CcpLayerDown,
5983d1af55SBrian Somers   CcpLayerStart,
6083d1af55SBrian Somers   CcpLayerFinish,
6183d1af55SBrian Somers   CcpInitRestartCounter,
6283d1af55SBrian Somers   CcpSendConfigReq,
6383d1af55SBrian Somers   CcpSendTerminateReq,
6483d1af55SBrian Somers   CcpSendTerminateAck,
6583d1af55SBrian Somers   CcpDecodeConfig
6683d1af55SBrian Somers };
6783d1af55SBrian Somers 
68aad81d1eSBrian Somers struct ccp CcpInfo = {
697308ec68SBrian Somers   {
701ae349f5Scvs2svn     "CCP",
711ae349f5Scvs2svn     PROTO_CCP,
721ae349f5Scvs2svn     CCP_MAXCODE,
731ae349f5Scvs2svn     0,
741ae349f5Scvs2svn     ST_INITIAL,
751ae349f5Scvs2svn     0, 0, 0,
761ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* FSM timer */
771ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* Open timer */
781ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* Stopped timer */
791ae349f5Scvs2svn     LogCCP,
807a6f8720SBrian Somers     NULL,				/* link */
817a6f8720SBrian Somers     NULL,				/* bundle */
8283d1af55SBrian Somers     &ccp_Callbacks
837308ec68SBrian Somers   },
847308ec68SBrian Somers   -1, -1, -1, -1, -1, -1
851ae349f5Scvs2svn };
861ae349f5Scvs2svn 
871ae349f5Scvs2svn static char const *cftypes[] = {
881ae349f5Scvs2svn   /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
891ae349f5Scvs2svn   "OUI",		/* 0: OUI */
901ae349f5Scvs2svn   "PRED1",		/* 1: Predictor type 1 */
911ae349f5Scvs2svn   "PRED2",		/* 2: Predictor type 2 */
921ae349f5Scvs2svn   "PUDDLE",		/* 3: Puddle Jumber */
931ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
941ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
951ae349f5Scvs2svn   "HWPPC",		/* 16: Hewlett-Packard PPC */
961ae349f5Scvs2svn   "STAC",		/* 17: Stac Electronics LZS (rfc1974) */
971ae349f5Scvs2svn   "MSPPC",		/* 18: Microsoft PPC */
981ae349f5Scvs2svn   "GAND",		/* 19: Gandalf FZA (rfc1993) */
991ae349f5Scvs2svn   "V42BIS",		/* 20: ARG->DATA.42bis compression */
1001ae349f5Scvs2svn   "BSD",		/* 21: BSD LZW Compress */
1011ae349f5Scvs2svn   "???",
1021ae349f5Scvs2svn   "LZS-DCP",		/* 23: LZS-DCP Compression Protocol (rfc1967) */
1031ae349f5Scvs2svn   "MAGNALINK/DEFLATE",	/* 24: Magnalink Variable Resource (rfc1975) */
1041ae349f5Scvs2svn 			/* 24: Deflate (according to pppd-2.3.1) */
1051ae349f5Scvs2svn   "DCE",		/* 25: Data Circuit-Terminating Equip (rfc1976) */
1061ae349f5Scvs2svn   "DEFLATE",		/* 26: Deflate (rfc1979) */
1071ae349f5Scvs2svn };
1081ae349f5Scvs2svn 
1091ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
1101ae349f5Scvs2svn 
1111ae349f5Scvs2svn static const char *
1121ae349f5Scvs2svn protoname(int proto)
1131ae349f5Scvs2svn {
1141ae349f5Scvs2svn   if (proto < 0 || proto > NCFTYPES)
1151ae349f5Scvs2svn     return "none";
1161ae349f5Scvs2svn   return cftypes[proto];
1171ae349f5Scvs2svn }
1181ae349f5Scvs2svn 
1191ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */
1201ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = {
1211ae349f5Scvs2svn   &DeflateAlgorithm,
1221ae349f5Scvs2svn   &Pred1Algorithm,
1231ae349f5Scvs2svn   &PppdDeflateAlgorithm
1241ae349f5Scvs2svn };
1251ae349f5Scvs2svn 
1261ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
1271ae349f5Scvs2svn 
1281ae349f5Scvs2svn int
1291ae349f5Scvs2svn ReportCcpStatus(struct cmdargs const *arg)
1301ae349f5Scvs2svn {
1311ae349f5Scvs2svn   if (VarTerm) {
1327308ec68SBrian Somers     fprintf(VarTerm, "%s [%s]\n", CcpInfo.fsm.name,
1337308ec68SBrian Somers             StateNames[CcpInfo.fsm.state]);
1341ae349f5Scvs2svn     fprintf(VarTerm, "My protocol = %s, His protocol = %s\n",
1351ae349f5Scvs2svn             protoname(CcpInfo.my_proto), protoname(CcpInfo.his_proto));
1361ae349f5Scvs2svn     fprintf(VarTerm, "Output: %ld --> %ld,  Input: %ld --> %ld\n",
1371ae349f5Scvs2svn             CcpInfo.uncompout, CcpInfo.compout,
1381ae349f5Scvs2svn             CcpInfo.compin, CcpInfo.uncompin);
1391ae349f5Scvs2svn   }
1401ae349f5Scvs2svn   return 0;
1411ae349f5Scvs2svn }
1421ae349f5Scvs2svn 
1431ae349f5Scvs2svn void
1447a6f8720SBrian Somers CcpInit(struct bundle *bundle, struct link *l)
1451ae349f5Scvs2svn {
1467308ec68SBrian Somers   /* Initialise ourselves */
1477a6f8720SBrian Somers   FsmInit(&CcpInfo.fsm, bundle, l);
1487308ec68SBrian Somers   CcpInfo.his_proto = CcpInfo.my_proto = -1;
1497308ec68SBrian Somers   CcpInfo.reset_sent = CcpInfo.last_reset = -1;
1507308ec68SBrian Somers   CcpInfo.in_algorithm = CcpInfo.out_algorithm = -1;
1517308ec68SBrian Somers   CcpInfo.his_reject = CcpInfo.my_reject = 0;
1527308ec68SBrian Somers   CcpInfo.out_init = CcpInfo.in_init = 0;
1537308ec68SBrian Somers   CcpInfo.uncompout = CcpInfo.compout = 0;
1547308ec68SBrian Somers   CcpInfo.uncompin = CcpInfo.compin = 0;
1557308ec68SBrian Somers   CcpInfo.fsm.maxconfig = 10;
1561ae349f5Scvs2svn }
1571ae349f5Scvs2svn 
1581ae349f5Scvs2svn static void
1591ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp)
1601ae349f5Scvs2svn {
1617308ec68SBrian Somers   /* Set fsm timer load */
1621ae349f5Scvs2svn   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1631ae349f5Scvs2svn   fp->restart = 5;
1641ae349f5Scvs2svn }
1651ae349f5Scvs2svn 
1661ae349f5Scvs2svn static void
1671ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp)
1681ae349f5Scvs2svn {
1697308ec68SBrian Somers   /* Send config REQ please */
170aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1711ae349f5Scvs2svn   u_char *cp;
1721ae349f5Scvs2svn   int f;
1731ae349f5Scvs2svn 
1741ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendConfigReq\n");
1751ae349f5Scvs2svn   cp = ReqBuff;
17683d1af55SBrian Somers   ccp->my_proto = -1;
17783d1af55SBrian Somers   ccp->out_algorithm = -1;
1781ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
17983d1af55SBrian Somers     if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) {
1801ae349f5Scvs2svn       struct lcp_opt o;
1811ae349f5Scvs2svn 
1821ae349f5Scvs2svn       (*algorithm[f]->o.Get)(&o);
1831ae349f5Scvs2svn       cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
1841ae349f5Scvs2svn                        (*algorithm[f]->Disp)(&o));
18583d1af55SBrian Somers       ccp->my_proto = o.id;
18683d1af55SBrian Somers       ccp->out_algorithm = f;
1871ae349f5Scvs2svn     }
1881ae349f5Scvs2svn   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
1891ae349f5Scvs2svn }
1901ae349f5Scvs2svn 
1911ae349f5Scvs2svn void
1921ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp)
1931ae349f5Scvs2svn {
1947308ec68SBrian Somers   /* We can't read our input - ask peer to reset */
195aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1961ae349f5Scvs2svn   LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
19783d1af55SBrian Somers   ccp->reset_sent = fp->reqid;
19883d1af55SBrian Somers   ccp->last_reset = -1;
1991ae349f5Scvs2svn   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
2001ae349f5Scvs2svn }
2011ae349f5Scvs2svn 
2021ae349f5Scvs2svn static void
2031ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp)
2041ae349f5Scvs2svn {
2057308ec68SBrian Somers   /* Term REQ just sent by FSM */
2061ae349f5Scvs2svn }
2071ae349f5Scvs2svn 
2081ae349f5Scvs2svn static void
2091ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp)
2101ae349f5Scvs2svn {
2117308ec68SBrian Somers   /* Send Term ACK please */
2121ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendTerminateAck\n");
2131ae349f5Scvs2svn   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2141ae349f5Scvs2svn }
2151ae349f5Scvs2svn 
2161ae349f5Scvs2svn void
2171ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp)
2181ae349f5Scvs2svn {
2197308ec68SBrian Somers   /* Got a reset REQ, reset outgoing dictionary */
220aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
22183d1af55SBrian Somers   if (ccp->out_init)
22283d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Reset)();
2231ae349f5Scvs2svn }
2241ae349f5Scvs2svn 
2251ae349f5Scvs2svn static void
2261ae349f5Scvs2svn CcpLayerStart(struct fsm *fp)
2271ae349f5Scvs2svn {
2287308ec68SBrian Somers   /* We're about to start up ! */
2291ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerStart.\n");
2301ae349f5Scvs2svn }
2311ae349f5Scvs2svn 
2321ae349f5Scvs2svn static void
2331ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp)
2341ae349f5Scvs2svn {
2357308ec68SBrian Somers   /* We're now down */
236aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2371ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerFinish.\n");
23883d1af55SBrian Somers   if (ccp->in_init) {
23983d1af55SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Term)();
24083d1af55SBrian Somers     ccp->in_init = 0;
2417308ec68SBrian Somers   }
24283d1af55SBrian Somers   if (ccp->out_init) {
24383d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Term)();
24483d1af55SBrian Somers     ccp->out_init = 0;
2457308ec68SBrian Somers   }
2461ae349f5Scvs2svn }
2471ae349f5Scvs2svn 
2481ae349f5Scvs2svn static void
2491ae349f5Scvs2svn CcpLayerDown(struct fsm *fp)
2501ae349f5Scvs2svn {
2517308ec68SBrian Somers   /* About to come down */
2521ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerDown.\n");
2531ae349f5Scvs2svn }
2541ae349f5Scvs2svn 
2551ae349f5Scvs2svn /*
2561ae349f5Scvs2svn  *  Called when CCP has reached the OPEN state
2571ae349f5Scvs2svn  */
2581ae349f5Scvs2svn static void
2591ae349f5Scvs2svn CcpLayerUp(struct fsm *fp)
2601ae349f5Scvs2svn {
2617308ec68SBrian Somers   /* We're now up */
262aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
263455aabc3SBrian Somers   LogPrintf(LogCCP, "CcpLayerUp.\n");
26483d1af55SBrian Somers   if (!ccp->in_init && ccp->in_algorithm >= 0 &&
26583d1af55SBrian Somers       ccp->in_algorithm < NALGORITHMS)
26683d1af55SBrian Somers     if ((*algorithm[ccp->in_algorithm]->i.Init)())
26783d1af55SBrian Somers       ccp->in_init = 1;
268247ab36dSBrian Somers     else {
269247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (in) initialisation failure\n",
27083d1af55SBrian Somers                 protoname(ccp->his_proto));
27183d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
272247ab36dSBrian Somers       FsmClose(fp);
273247ab36dSBrian Somers     }
27483d1af55SBrian Somers   if (!ccp->out_init && ccp->out_algorithm >= 0 &&
27583d1af55SBrian Somers       ccp->out_algorithm < NALGORITHMS)
27683d1af55SBrian Somers     if ((*algorithm[ccp->out_algorithm]->o.Init)())
27783d1af55SBrian Somers       ccp->out_init = 1;
278247ab36dSBrian Somers     else {
279247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (out) initialisation failure\n",
28083d1af55SBrian Somers                 protoname(ccp->my_proto));
28183d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
282247ab36dSBrian Somers       FsmClose(fp);
283247ab36dSBrian Somers     }
2841ae349f5Scvs2svn   LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
28583d1af55SBrian Somers             protoname(ccp->my_proto), ccp->my_proto,
28683d1af55SBrian Somers             protoname(ccp->his_proto), ccp->his_proto);
2871ae349f5Scvs2svn }
2881ae349f5Scvs2svn 
2891ae349f5Scvs2svn void
2901ae349f5Scvs2svn CcpUp()
2911ae349f5Scvs2svn {
2927308ec68SBrian Somers   /* Lower layers are ready.... go */
2937308ec68SBrian Somers   FsmUp(&CcpInfo.fsm);
2941ae349f5Scvs2svn   LogPrintf(LogCCP, "CCP Up event!!\n");
2951ae349f5Scvs2svn }
2961ae349f5Scvs2svn 
2971ae349f5Scvs2svn void
2981ae349f5Scvs2svn CcpOpen()
2991ae349f5Scvs2svn {
3007308ec68SBrian Somers   /* Start CCP please */
3011ae349f5Scvs2svn   int f;
3021ae349f5Scvs2svn 
3031ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
3041ae349f5Scvs2svn     if (Enabled(algorithm[f]->Conf)) {
3057308ec68SBrian Somers       CcpInfo.fsm.open_mode = 0;
3067308ec68SBrian Somers       FsmOpen(&CcpInfo.fsm);
3071ae349f5Scvs2svn       break;
3081ae349f5Scvs2svn     }
3091ae349f5Scvs2svn 
3101ae349f5Scvs2svn   if (f == NALGORITHMS)
3111ae349f5Scvs2svn     for (f = 0; f < NALGORITHMS; f++)
3121ae349f5Scvs2svn       if (Acceptable(algorithm[f]->Conf)) {
3137308ec68SBrian Somers         CcpInfo.fsm.open_mode = OPEN_PASSIVE;
3147308ec68SBrian Somers         FsmOpen(&CcpInfo.fsm);
3151ae349f5Scvs2svn         break;
3161ae349f5Scvs2svn       }
3171ae349f5Scvs2svn }
3181ae349f5Scvs2svn 
3191ae349f5Scvs2svn static void
32083d1af55SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type)
3211ae349f5Scvs2svn {
3227308ec68SBrian Somers   /* Deal with incoming data */
323aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
3241ae349f5Scvs2svn   int type, length;
3251ae349f5Scvs2svn   int f;
3261ae349f5Scvs2svn 
3271ae349f5Scvs2svn   ackp = AckBuff;
3281ae349f5Scvs2svn   nakp = NakBuff;
3291ae349f5Scvs2svn   rejp = RejBuff;
3301ae349f5Scvs2svn 
3311ae349f5Scvs2svn   while (plen >= sizeof(struct fsmconfig)) {
3321ae349f5Scvs2svn     type = *cp;
3331ae349f5Scvs2svn     length = cp[1];
3341ae349f5Scvs2svn     if (type < NCFTYPES)
3351ae349f5Scvs2svn       LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
3361ae349f5Scvs2svn     else
3371ae349f5Scvs2svn       LogPrintf(LogCCP, " ???[%d]\n", length);
3381ae349f5Scvs2svn 
3391ae349f5Scvs2svn     for (f = NALGORITHMS-1; f > -1; f--)
3401ae349f5Scvs2svn       if (algorithm[f]->id == type)
3411ae349f5Scvs2svn         break;
3421ae349f5Scvs2svn 
3431ae349f5Scvs2svn     if (f == -1) {
3441ae349f5Scvs2svn       /* Don't understand that :-( */
3451ae349f5Scvs2svn       if (mode_type == MODE_REQ) {
34683d1af55SBrian Somers         ccp->my_reject |= (1 << type);
3471ae349f5Scvs2svn         memcpy(rejp, cp, length);
3481ae349f5Scvs2svn         rejp += length;
3491ae349f5Scvs2svn       }
3501ae349f5Scvs2svn     } else {
3511ae349f5Scvs2svn       struct lcp_opt o;
3521ae349f5Scvs2svn 
3531ae349f5Scvs2svn       switch (mode_type) {
3541ae349f5Scvs2svn       case MODE_REQ:
35583d1af55SBrian Somers 	if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) {
3561ae349f5Scvs2svn 	  memcpy(&o, cp, length);
3571ae349f5Scvs2svn           switch ((*algorithm[f]->i.Set)(&o)) {
3581ae349f5Scvs2svn           case MODE_REJ:
3591ae349f5Scvs2svn 	    memcpy(rejp, &o, o.len);
3601ae349f5Scvs2svn 	    rejp += o.len;
3611ae349f5Scvs2svn             break;
3621ae349f5Scvs2svn           case MODE_NAK:
3631ae349f5Scvs2svn 	    memcpy(nakp, &o, o.len);
3641ae349f5Scvs2svn 	    nakp += o.len;
3651ae349f5Scvs2svn             break;
3661ae349f5Scvs2svn           case MODE_ACK:
3671ae349f5Scvs2svn 	    memcpy(ackp, cp, length);
3681ae349f5Scvs2svn 	    ackp += length;
36983d1af55SBrian Somers 	    ccp->his_proto = type;
37083d1af55SBrian Somers             ccp->in_algorithm = f;		/* This one'll do ! */
3711ae349f5Scvs2svn             break;
3721ae349f5Scvs2svn           }
3731ae349f5Scvs2svn 	} else {
3741ae349f5Scvs2svn 	  memcpy(rejp, cp, length);
3751ae349f5Scvs2svn 	  rejp += length;
3761ae349f5Scvs2svn 	}
3771ae349f5Scvs2svn 	break;
3781ae349f5Scvs2svn       case MODE_NAK:
3791ae349f5Scvs2svn 	memcpy(&o, cp, length);
3801ae349f5Scvs2svn         if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
38183d1af55SBrian Somers           ccp->my_proto = algorithm[f]->id;
3821ae349f5Scvs2svn         else {
38383d1af55SBrian Somers 	  ccp->his_reject |= (1 << type);
38483d1af55SBrian Somers 	  ccp->my_proto = -1;
3851ae349f5Scvs2svn         }
3861ae349f5Scvs2svn         break;
3871ae349f5Scvs2svn       case MODE_REJ:
38883d1af55SBrian Somers 	ccp->his_reject |= (1 << type);
38983d1af55SBrian Somers 	ccp->my_proto = -1;
3901ae349f5Scvs2svn 	break;
3911ae349f5Scvs2svn       }
3921ae349f5Scvs2svn     }
3931ae349f5Scvs2svn 
3941ae349f5Scvs2svn     plen -= length;
3951ae349f5Scvs2svn     cp += length;
3961ae349f5Scvs2svn   }
3971ae349f5Scvs2svn 
3981ae349f5Scvs2svn   if (rejp != RejBuff) {
3991ae349f5Scvs2svn     ackp = AckBuff;	/* let's not send both ! */
40083d1af55SBrian Somers     if (!ccp->in_init) {
40183d1af55SBrian Somers       ccp->his_proto = -1;
40283d1af55SBrian Somers       ccp->in_algorithm = -1;
403247ab36dSBrian Somers     }
4041ae349f5Scvs2svn   }
4051ae349f5Scvs2svn }
4061ae349f5Scvs2svn 
4071ae349f5Scvs2svn void
408455aabc3SBrian Somers CcpInput(struct bundle *bundle, struct mbuf *bp)
4091ae349f5Scvs2svn {
4107308ec68SBrian Somers   /* Got PROTO_CCP from link */
411455aabc3SBrian Somers   if (bundle_Phase(bundle) == PHASE_NETWORK)
4127308ec68SBrian Somers     FsmInput(&CcpInfo.fsm, bp);
413455aabc3SBrian Somers   else if (bundle_Phase(bundle) < PHASE_NETWORK) {
414455aabc3SBrian Somers     LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n",
415455aabc3SBrian Somers               bundle_PhaseName(bundle));
4161ae349f5Scvs2svn     pfree(bp);
4171ae349f5Scvs2svn   }
4181ae349f5Scvs2svn }
4191ae349f5Scvs2svn 
4201ae349f5Scvs2svn void
4211ae349f5Scvs2svn CcpResetInput(u_char id)
4221ae349f5Scvs2svn {
4237308ec68SBrian Somers   /* Got a reset ACK, reset incoming dictionary */
4241ae349f5Scvs2svn   if (CcpInfo.reset_sent != -1) {
4251ae349f5Scvs2svn     if (id != CcpInfo.reset_sent) {
4261ae349f5Scvs2svn       LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
4271ae349f5Scvs2svn                 id, CcpInfo.reset_sent);
4281ae349f5Scvs2svn       return;
4291ae349f5Scvs2svn     }
4301ae349f5Scvs2svn     /* Whaddaya know - a correct reset ack */
4311ae349f5Scvs2svn   } else if (id == CcpInfo.last_reset)
4321ae349f5Scvs2svn     LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
4331ae349f5Scvs2svn   else {
4341ae349f5Scvs2svn     LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
4351ae349f5Scvs2svn     return;
4361ae349f5Scvs2svn   }
4371ae349f5Scvs2svn 
4381ae349f5Scvs2svn   CcpInfo.last_reset = CcpInfo.reset_sent;
4391ae349f5Scvs2svn   CcpInfo.reset_sent = -1;
440247ab36dSBrian Somers   if (CcpInfo.in_init)
441247ab36dSBrian Somers     (*algorithm[CcpInfo.in_algorithm]->i.Reset)();
4421ae349f5Scvs2svn }
4431ae349f5Scvs2svn 
4441ae349f5Scvs2svn int
4458c07a7b2SBrian Somers CcpOutput(struct link *l, int pri, u_short proto, struct mbuf *m)
4461ae349f5Scvs2svn {
4477308ec68SBrian Somers   /* Compress outgoing data */
448247ab36dSBrian Somers   if (CcpInfo.out_init)
4498c07a7b2SBrian Somers     return (*algorithm[CcpInfo.out_algorithm]->o.Write)(l, pri, proto, m);
4501ae349f5Scvs2svn   return 0;
4511ae349f5Scvs2svn }
4521ae349f5Scvs2svn 
4531ae349f5Scvs2svn struct mbuf *
4541ae349f5Scvs2svn CompdInput(u_short *proto, struct mbuf *m)
4551ae349f5Scvs2svn {
4567308ec68SBrian Somers   /* Decompress incoming data */
4571ae349f5Scvs2svn   if (CcpInfo.reset_sent != -1) {
4581ae349f5Scvs2svn     /* Send another REQ and put the packet in the bit bucket */
4591ae349f5Scvs2svn     LogPrintf(LogCCP, "ReSendResetReq(%d)\n", CcpInfo.reset_sent);
4607308ec68SBrian Somers     FsmOutput(&CcpInfo.fsm, CODE_RESETREQ, CcpInfo.reset_sent, NULL, 0);
4611ae349f5Scvs2svn     pfree(m);
462247ab36dSBrian Somers   } else if (CcpInfo.in_init)
463247ab36dSBrian Somers     return (*algorithm[CcpInfo.in_algorithm]->i.Read)(proto, m);
4641ae349f5Scvs2svn   return NULL;
4651ae349f5Scvs2svn }
4661ae349f5Scvs2svn 
4671ae349f5Scvs2svn void
4681ae349f5Scvs2svn CcpDictSetup(u_short proto, struct mbuf *m)
4691ae349f5Scvs2svn {
4707308ec68SBrian Somers   /* Add incoming data to the dictionary */
471247ab36dSBrian Somers   if (CcpInfo.in_init)
472247ab36dSBrian Somers     (*algorithm[CcpInfo.in_algorithm]->i.DictSetup)(proto, m);
4731ae349f5Scvs2svn }
474