xref: /freebsd/usr.sbin/ppp/ccp.c (revision 85b542cf4f3d3d3338529aad0f9f006cdaeef9a8)
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  *
2085b542cfSBrian Somers  * $Id: ccp.c,v 1.30.2.8 1998/02/08 11:04:45 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"
45455aabc3SBrian Somers #include "bundle.h"
4685b542cfSBrian Somers #include "descriptor.h"
4785b542cfSBrian Somers #include "prompt.h"
481ae349f5Scvs2svn 
491ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *);
501ae349f5Scvs2svn static void CcpSendTerminateReq(struct fsm *);
511ae349f5Scvs2svn static void CcpSendTerminateAck(struct fsm *);
5283d1af55SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int);
531ae349f5Scvs2svn static void CcpLayerStart(struct fsm *);
541ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *);
551ae349f5Scvs2svn static void CcpLayerUp(struct fsm *);
561ae349f5Scvs2svn static void CcpLayerDown(struct fsm *);
571ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *);
581ae349f5Scvs2svn 
5983d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = {
6083d1af55SBrian Somers   CcpLayerUp,
6183d1af55SBrian Somers   CcpLayerDown,
6283d1af55SBrian Somers   CcpLayerStart,
6383d1af55SBrian Somers   CcpLayerFinish,
6483d1af55SBrian Somers   CcpInitRestartCounter,
6583d1af55SBrian Somers   CcpSendConfigReq,
6683d1af55SBrian Somers   CcpSendTerminateReq,
6783d1af55SBrian Somers   CcpSendTerminateAck,
6883d1af55SBrian Somers   CcpDecodeConfig
6983d1af55SBrian Somers };
7083d1af55SBrian Somers 
71aad81d1eSBrian Somers struct ccp CcpInfo = {
727308ec68SBrian Somers   {
731ae349f5Scvs2svn     "CCP",
741ae349f5Scvs2svn     PROTO_CCP,
751ae349f5Scvs2svn     CCP_MAXCODE,
761ae349f5Scvs2svn     0,
771ae349f5Scvs2svn     ST_INITIAL,
781ae349f5Scvs2svn     0, 0, 0,
791ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* FSM timer */
801ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* Open timer */
811ae349f5Scvs2svn     {0, 0, 0, NULL, NULL, NULL},	/* Stopped timer */
821ae349f5Scvs2svn     LogCCP,
837a6f8720SBrian Somers     NULL,				/* link */
847a6f8720SBrian Somers     NULL,				/* bundle */
8583d1af55SBrian Somers     &ccp_Callbacks
867308ec68SBrian Somers   },
877308ec68SBrian Somers   -1, -1, -1, -1, -1, -1
881ae349f5Scvs2svn };
891ae349f5Scvs2svn 
901ae349f5Scvs2svn static char const *cftypes[] = {
911ae349f5Scvs2svn   /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
921ae349f5Scvs2svn   "OUI",		/* 0: OUI */
931ae349f5Scvs2svn   "PRED1",		/* 1: Predictor type 1 */
941ae349f5Scvs2svn   "PRED2",		/* 2: Predictor type 2 */
951ae349f5Scvs2svn   "PUDDLE",		/* 3: Puddle Jumber */
961ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
971ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
981ae349f5Scvs2svn   "HWPPC",		/* 16: Hewlett-Packard PPC */
991ae349f5Scvs2svn   "STAC",		/* 17: Stac Electronics LZS (rfc1974) */
1001ae349f5Scvs2svn   "MSPPC",		/* 18: Microsoft PPC */
1011ae349f5Scvs2svn   "GAND",		/* 19: Gandalf FZA (rfc1993) */
1021ae349f5Scvs2svn   "V42BIS",		/* 20: ARG->DATA.42bis compression */
1031ae349f5Scvs2svn   "BSD",		/* 21: BSD LZW Compress */
1041ae349f5Scvs2svn   "???",
1051ae349f5Scvs2svn   "LZS-DCP",		/* 23: LZS-DCP Compression Protocol (rfc1967) */
1061ae349f5Scvs2svn   "MAGNALINK/DEFLATE",	/* 24: Magnalink Variable Resource (rfc1975) */
1071ae349f5Scvs2svn 			/* 24: Deflate (according to pppd-2.3.1) */
1081ae349f5Scvs2svn   "DCE",		/* 25: Data Circuit-Terminating Equip (rfc1976) */
1091ae349f5Scvs2svn   "DEFLATE",		/* 26: Deflate (rfc1979) */
1101ae349f5Scvs2svn };
1111ae349f5Scvs2svn 
1121ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
1131ae349f5Scvs2svn 
1141ae349f5Scvs2svn static const char *
1151ae349f5Scvs2svn protoname(int proto)
1161ae349f5Scvs2svn {
1171ae349f5Scvs2svn   if (proto < 0 || proto > NCFTYPES)
1181ae349f5Scvs2svn     return "none";
1191ae349f5Scvs2svn   return cftypes[proto];
1201ae349f5Scvs2svn }
1211ae349f5Scvs2svn 
1221ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */
1231ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = {
1241ae349f5Scvs2svn   &DeflateAlgorithm,
1251ae349f5Scvs2svn   &Pred1Algorithm,
1261ae349f5Scvs2svn   &PppdDeflateAlgorithm
1271ae349f5Scvs2svn };
1281ae349f5Scvs2svn 
1291ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
1301ae349f5Scvs2svn 
1311ae349f5Scvs2svn int
1321ae349f5Scvs2svn ReportCcpStatus(struct cmdargs const *arg)
1331ae349f5Scvs2svn {
13485b542cfSBrian Somers   prompt_Printf(&prompt, "%s [%s]\n", CcpInfo.fsm.name,
1357308ec68SBrian Somers                 StateNames[CcpInfo.fsm.state]);
13685b542cfSBrian Somers   prompt_Printf(&prompt, "My protocol = %s, His protocol = %s\n",
1371ae349f5Scvs2svn                 protoname(CcpInfo.my_proto), protoname(CcpInfo.his_proto));
13885b542cfSBrian Somers   prompt_Printf(&prompt, "Output: %ld --> %ld,  Input: %ld --> %ld\n",
1391ae349f5Scvs2svn                 CcpInfo.uncompout, CcpInfo.compout,
1401ae349f5Scvs2svn                 CcpInfo.compin, CcpInfo.uncompin);
1411ae349f5Scvs2svn   return 0;
1421ae349f5Scvs2svn }
1431ae349f5Scvs2svn 
1441ae349f5Scvs2svn void
1457a6f8720SBrian Somers CcpInit(struct bundle *bundle, struct link *l)
1461ae349f5Scvs2svn {
1477308ec68SBrian Somers   /* Initialise ourselves */
1487a6f8720SBrian Somers   FsmInit(&CcpInfo.fsm, bundle, l);
1497308ec68SBrian Somers   CcpInfo.his_proto = CcpInfo.my_proto = -1;
1507308ec68SBrian Somers   CcpInfo.reset_sent = CcpInfo.last_reset = -1;
1517308ec68SBrian Somers   CcpInfo.in_algorithm = CcpInfo.out_algorithm = -1;
1527308ec68SBrian Somers   CcpInfo.his_reject = CcpInfo.my_reject = 0;
1537308ec68SBrian Somers   CcpInfo.out_init = CcpInfo.in_init = 0;
1547308ec68SBrian Somers   CcpInfo.uncompout = CcpInfo.compout = 0;
1557308ec68SBrian Somers   CcpInfo.uncompin = CcpInfo.compin = 0;
1567308ec68SBrian Somers   CcpInfo.fsm.maxconfig = 10;
1571ae349f5Scvs2svn }
1581ae349f5Scvs2svn 
1591ae349f5Scvs2svn static void
1601ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp)
1611ae349f5Scvs2svn {
1627308ec68SBrian Somers   /* Set fsm timer load */
1631ae349f5Scvs2svn   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1641ae349f5Scvs2svn   fp->restart = 5;
1651ae349f5Scvs2svn }
1661ae349f5Scvs2svn 
1671ae349f5Scvs2svn static void
1681ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp)
1691ae349f5Scvs2svn {
1707308ec68SBrian Somers   /* Send config REQ please */
171aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1721ae349f5Scvs2svn   u_char *cp;
1731ae349f5Scvs2svn   int f;
1741ae349f5Scvs2svn 
1751ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendConfigReq\n");
1761ae349f5Scvs2svn   cp = ReqBuff;
17783d1af55SBrian Somers   ccp->my_proto = -1;
17883d1af55SBrian Somers   ccp->out_algorithm = -1;
1791ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
18083d1af55SBrian Somers     if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) {
1811ae349f5Scvs2svn       struct lcp_opt o;
1821ae349f5Scvs2svn 
1831ae349f5Scvs2svn       (*algorithm[f]->o.Get)(&o);
1841ae349f5Scvs2svn       cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
1851ae349f5Scvs2svn                        (*algorithm[f]->Disp)(&o));
18683d1af55SBrian Somers       ccp->my_proto = o.id;
18783d1af55SBrian Somers       ccp->out_algorithm = f;
1881ae349f5Scvs2svn     }
1891ae349f5Scvs2svn   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
1901ae349f5Scvs2svn }
1911ae349f5Scvs2svn 
1921ae349f5Scvs2svn void
1931ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp)
1941ae349f5Scvs2svn {
1957308ec68SBrian Somers   /* We can't read our input - ask peer to reset */
196aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1971ae349f5Scvs2svn   LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
19883d1af55SBrian Somers   ccp->reset_sent = fp->reqid;
19983d1af55SBrian Somers   ccp->last_reset = -1;
2001ae349f5Scvs2svn   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
2011ae349f5Scvs2svn }
2021ae349f5Scvs2svn 
2031ae349f5Scvs2svn static void
2041ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp)
2051ae349f5Scvs2svn {
2067308ec68SBrian Somers   /* Term REQ just sent by FSM */
2071ae349f5Scvs2svn }
2081ae349f5Scvs2svn 
2091ae349f5Scvs2svn static void
2101ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp)
2111ae349f5Scvs2svn {
2127308ec68SBrian Somers   /* Send Term ACK please */
2131ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendTerminateAck\n");
2141ae349f5Scvs2svn   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2151ae349f5Scvs2svn }
2161ae349f5Scvs2svn 
2171ae349f5Scvs2svn void
2181ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp)
2191ae349f5Scvs2svn {
2207308ec68SBrian Somers   /* Got a reset REQ, reset outgoing dictionary */
221aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
22283d1af55SBrian Somers   if (ccp->out_init)
22383d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Reset)();
2241ae349f5Scvs2svn }
2251ae349f5Scvs2svn 
2261ae349f5Scvs2svn static void
2271ae349f5Scvs2svn CcpLayerStart(struct fsm *fp)
2281ae349f5Scvs2svn {
2297308ec68SBrian Somers   /* We're about to start up ! */
2301ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerStart.\n");
2311ae349f5Scvs2svn }
2321ae349f5Scvs2svn 
2331ae349f5Scvs2svn static void
2341ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp)
2351ae349f5Scvs2svn {
2367308ec68SBrian Somers   /* We're now down */
237aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2381ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerFinish.\n");
23983d1af55SBrian Somers   if (ccp->in_init) {
24083d1af55SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Term)();
24183d1af55SBrian Somers     ccp->in_init = 0;
2427308ec68SBrian Somers   }
24383d1af55SBrian Somers   if (ccp->out_init) {
24483d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Term)();
24583d1af55SBrian Somers     ccp->out_init = 0;
2467308ec68SBrian Somers   }
2471ae349f5Scvs2svn }
2481ae349f5Scvs2svn 
2491ae349f5Scvs2svn static void
2501ae349f5Scvs2svn CcpLayerDown(struct fsm *fp)
2511ae349f5Scvs2svn {
2527308ec68SBrian Somers   /* About to come down */
2531ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerDown.\n");
2541ae349f5Scvs2svn }
2551ae349f5Scvs2svn 
2561ae349f5Scvs2svn /*
2571ae349f5Scvs2svn  *  Called when CCP has reached the OPEN state
2581ae349f5Scvs2svn  */
2591ae349f5Scvs2svn static void
2601ae349f5Scvs2svn CcpLayerUp(struct fsm *fp)
2611ae349f5Scvs2svn {
2627308ec68SBrian Somers   /* We're now up */
263aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
264455aabc3SBrian Somers   LogPrintf(LogCCP, "CcpLayerUp.\n");
26583d1af55SBrian Somers   if (!ccp->in_init && ccp->in_algorithm >= 0 &&
26683d1af55SBrian Somers       ccp->in_algorithm < NALGORITHMS)
26783d1af55SBrian Somers     if ((*algorithm[ccp->in_algorithm]->i.Init)())
26883d1af55SBrian Somers       ccp->in_init = 1;
269247ab36dSBrian Somers     else {
270247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (in) initialisation failure\n",
27183d1af55SBrian Somers                 protoname(ccp->his_proto));
27283d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
273247ab36dSBrian Somers       FsmClose(fp);
274247ab36dSBrian Somers     }
27583d1af55SBrian Somers   if (!ccp->out_init && ccp->out_algorithm >= 0 &&
27683d1af55SBrian Somers       ccp->out_algorithm < NALGORITHMS)
27783d1af55SBrian Somers     if ((*algorithm[ccp->out_algorithm]->o.Init)())
27883d1af55SBrian Somers       ccp->out_init = 1;
279247ab36dSBrian Somers     else {
280247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (out) initialisation failure\n",
28183d1af55SBrian Somers                 protoname(ccp->my_proto));
28283d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
283247ab36dSBrian Somers       FsmClose(fp);
284247ab36dSBrian Somers     }
2851ae349f5Scvs2svn   LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
28683d1af55SBrian Somers             protoname(ccp->my_proto), ccp->my_proto,
28783d1af55SBrian Somers             protoname(ccp->his_proto), ccp->his_proto);
2881ae349f5Scvs2svn }
2891ae349f5Scvs2svn 
2901ae349f5Scvs2svn void
2911ae349f5Scvs2svn CcpUp()
2921ae349f5Scvs2svn {
2937308ec68SBrian Somers   /* Lower layers are ready.... go */
2947308ec68SBrian Somers   FsmUp(&CcpInfo.fsm);
2951ae349f5Scvs2svn   LogPrintf(LogCCP, "CCP Up event!!\n");
2961ae349f5Scvs2svn }
2971ae349f5Scvs2svn 
2981ae349f5Scvs2svn void
2991ae349f5Scvs2svn CcpOpen()
3001ae349f5Scvs2svn {
3017308ec68SBrian Somers   /* Start CCP please */
3021ae349f5Scvs2svn   int f;
3031ae349f5Scvs2svn 
3041ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
3051ae349f5Scvs2svn     if (Enabled(algorithm[f]->Conf)) {
3067308ec68SBrian Somers       CcpInfo.fsm.open_mode = 0;
3077308ec68SBrian Somers       FsmOpen(&CcpInfo.fsm);
3081ae349f5Scvs2svn       break;
3091ae349f5Scvs2svn     }
3101ae349f5Scvs2svn 
3111ae349f5Scvs2svn   if (f == NALGORITHMS)
3121ae349f5Scvs2svn     for (f = 0; f < NALGORITHMS; f++)
3131ae349f5Scvs2svn       if (Acceptable(algorithm[f]->Conf)) {
3147308ec68SBrian Somers         CcpInfo.fsm.open_mode = OPEN_PASSIVE;
3157308ec68SBrian Somers         FsmOpen(&CcpInfo.fsm);
3161ae349f5Scvs2svn         break;
3171ae349f5Scvs2svn       }
3181ae349f5Scvs2svn }
3191ae349f5Scvs2svn 
3201ae349f5Scvs2svn static void
32183d1af55SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type)
3221ae349f5Scvs2svn {
3237308ec68SBrian Somers   /* Deal with incoming data */
324aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
3251ae349f5Scvs2svn   int type, length;
3261ae349f5Scvs2svn   int f;
3271ae349f5Scvs2svn 
3281ae349f5Scvs2svn   ackp = AckBuff;
3291ae349f5Scvs2svn   nakp = NakBuff;
3301ae349f5Scvs2svn   rejp = RejBuff;
3311ae349f5Scvs2svn 
3321ae349f5Scvs2svn   while (plen >= sizeof(struct fsmconfig)) {
3331ae349f5Scvs2svn     type = *cp;
3341ae349f5Scvs2svn     length = cp[1];
3351ae349f5Scvs2svn     if (type < NCFTYPES)
3361ae349f5Scvs2svn       LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
3371ae349f5Scvs2svn     else
3381ae349f5Scvs2svn       LogPrintf(LogCCP, " ???[%d]\n", length);
3391ae349f5Scvs2svn 
3401ae349f5Scvs2svn     for (f = NALGORITHMS-1; f > -1; f--)
3411ae349f5Scvs2svn       if (algorithm[f]->id == type)
3421ae349f5Scvs2svn         break;
3431ae349f5Scvs2svn 
3441ae349f5Scvs2svn     if (f == -1) {
3451ae349f5Scvs2svn       /* Don't understand that :-( */
3461ae349f5Scvs2svn       if (mode_type == MODE_REQ) {
34783d1af55SBrian Somers         ccp->my_reject |= (1 << type);
3481ae349f5Scvs2svn         memcpy(rejp, cp, length);
3491ae349f5Scvs2svn         rejp += length;
3501ae349f5Scvs2svn       }
3511ae349f5Scvs2svn     } else {
3521ae349f5Scvs2svn       struct lcp_opt o;
3531ae349f5Scvs2svn 
3541ae349f5Scvs2svn       switch (mode_type) {
3551ae349f5Scvs2svn       case MODE_REQ:
35683d1af55SBrian Somers 	if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) {
3571ae349f5Scvs2svn 	  memcpy(&o, cp, length);
3581ae349f5Scvs2svn           switch ((*algorithm[f]->i.Set)(&o)) {
3591ae349f5Scvs2svn           case MODE_REJ:
3601ae349f5Scvs2svn 	    memcpy(rejp, &o, o.len);
3611ae349f5Scvs2svn 	    rejp += o.len;
3621ae349f5Scvs2svn             break;
3631ae349f5Scvs2svn           case MODE_NAK:
3641ae349f5Scvs2svn 	    memcpy(nakp, &o, o.len);
3651ae349f5Scvs2svn 	    nakp += o.len;
3661ae349f5Scvs2svn             break;
3671ae349f5Scvs2svn           case MODE_ACK:
3681ae349f5Scvs2svn 	    memcpy(ackp, cp, length);
3691ae349f5Scvs2svn 	    ackp += length;
37083d1af55SBrian Somers 	    ccp->his_proto = type;
37183d1af55SBrian Somers             ccp->in_algorithm = f;		/* This one'll do ! */
3721ae349f5Scvs2svn             break;
3731ae349f5Scvs2svn           }
3741ae349f5Scvs2svn 	} else {
3751ae349f5Scvs2svn 	  memcpy(rejp, cp, length);
3761ae349f5Scvs2svn 	  rejp += length;
3771ae349f5Scvs2svn 	}
3781ae349f5Scvs2svn 	break;
3791ae349f5Scvs2svn       case MODE_NAK:
3801ae349f5Scvs2svn 	memcpy(&o, cp, length);
3811ae349f5Scvs2svn         if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
38283d1af55SBrian Somers           ccp->my_proto = algorithm[f]->id;
3831ae349f5Scvs2svn         else {
38483d1af55SBrian Somers 	  ccp->his_reject |= (1 << type);
38583d1af55SBrian Somers 	  ccp->my_proto = -1;
3861ae349f5Scvs2svn         }
3871ae349f5Scvs2svn         break;
3881ae349f5Scvs2svn       case MODE_REJ:
38983d1af55SBrian Somers 	ccp->his_reject |= (1 << type);
39083d1af55SBrian Somers 	ccp->my_proto = -1;
3911ae349f5Scvs2svn 	break;
3921ae349f5Scvs2svn       }
3931ae349f5Scvs2svn     }
3941ae349f5Scvs2svn 
3951ae349f5Scvs2svn     plen -= length;
3961ae349f5Scvs2svn     cp += length;
3971ae349f5Scvs2svn   }
3981ae349f5Scvs2svn 
3991ae349f5Scvs2svn   if (rejp != RejBuff) {
4001ae349f5Scvs2svn     ackp = AckBuff;	/* let's not send both ! */
40183d1af55SBrian Somers     if (!ccp->in_init) {
40283d1af55SBrian Somers       ccp->his_proto = -1;
40383d1af55SBrian Somers       ccp->in_algorithm = -1;
404247ab36dSBrian Somers     }
4051ae349f5Scvs2svn   }
4061ae349f5Scvs2svn }
4071ae349f5Scvs2svn 
4081ae349f5Scvs2svn void
409455aabc3SBrian Somers CcpInput(struct bundle *bundle, struct mbuf *bp)
4101ae349f5Scvs2svn {
4117308ec68SBrian Somers   /* Got PROTO_CCP from link */
412455aabc3SBrian Somers   if (bundle_Phase(bundle) == PHASE_NETWORK)
4137308ec68SBrian Somers     FsmInput(&CcpInfo.fsm, bp);
414455aabc3SBrian Somers   else if (bundle_Phase(bundle) < PHASE_NETWORK) {
415455aabc3SBrian Somers     LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n",
416455aabc3SBrian Somers               bundle_PhaseName(bundle));
4171ae349f5Scvs2svn     pfree(bp);
4181ae349f5Scvs2svn   }
4191ae349f5Scvs2svn }
4201ae349f5Scvs2svn 
4211ae349f5Scvs2svn void
4221ae349f5Scvs2svn CcpResetInput(u_char id)
4231ae349f5Scvs2svn {
4247308ec68SBrian Somers   /* Got a reset ACK, reset incoming dictionary */
4251ae349f5Scvs2svn   if (CcpInfo.reset_sent != -1) {
4261ae349f5Scvs2svn     if (id != CcpInfo.reset_sent) {
4271ae349f5Scvs2svn       LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
4281ae349f5Scvs2svn                 id, CcpInfo.reset_sent);
4291ae349f5Scvs2svn       return;
4301ae349f5Scvs2svn     }
4311ae349f5Scvs2svn     /* Whaddaya know - a correct reset ack */
4321ae349f5Scvs2svn   } else if (id == CcpInfo.last_reset)
4331ae349f5Scvs2svn     LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
4341ae349f5Scvs2svn   else {
4351ae349f5Scvs2svn     LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
4361ae349f5Scvs2svn     return;
4371ae349f5Scvs2svn   }
4381ae349f5Scvs2svn 
4391ae349f5Scvs2svn   CcpInfo.last_reset = CcpInfo.reset_sent;
4401ae349f5Scvs2svn   CcpInfo.reset_sent = -1;
441247ab36dSBrian Somers   if (CcpInfo.in_init)
442247ab36dSBrian Somers     (*algorithm[CcpInfo.in_algorithm]->i.Reset)();
4431ae349f5Scvs2svn }
4441ae349f5Scvs2svn 
4451ae349f5Scvs2svn int
4468c07a7b2SBrian Somers CcpOutput(struct link *l, int pri, u_short proto, struct mbuf *m)
4471ae349f5Scvs2svn {
4487308ec68SBrian Somers   /* Compress outgoing data */
449247ab36dSBrian Somers   if (CcpInfo.out_init)
4508c07a7b2SBrian Somers     return (*algorithm[CcpInfo.out_algorithm]->o.Write)(l, pri, proto, m);
4511ae349f5Scvs2svn   return 0;
4521ae349f5Scvs2svn }
4531ae349f5Scvs2svn 
4541ae349f5Scvs2svn struct mbuf *
4551ae349f5Scvs2svn CompdInput(u_short *proto, struct mbuf *m)
4561ae349f5Scvs2svn {
4577308ec68SBrian Somers   /* Decompress incoming data */
4581ae349f5Scvs2svn   if (CcpInfo.reset_sent != -1) {
4591ae349f5Scvs2svn     /* Send another REQ and put the packet in the bit bucket */
4601ae349f5Scvs2svn     LogPrintf(LogCCP, "ReSendResetReq(%d)\n", CcpInfo.reset_sent);
4617308ec68SBrian Somers     FsmOutput(&CcpInfo.fsm, CODE_RESETREQ, CcpInfo.reset_sent, NULL, 0);
4621ae349f5Scvs2svn     pfree(m);
463247ab36dSBrian Somers   } else if (CcpInfo.in_init)
464247ab36dSBrian Somers     return (*algorithm[CcpInfo.in_algorithm]->i.Read)(proto, m);
4651ae349f5Scvs2svn   return NULL;
4661ae349f5Scvs2svn }
4671ae349f5Scvs2svn 
4681ae349f5Scvs2svn void
4691ae349f5Scvs2svn CcpDictSetup(u_short proto, struct mbuf *m)
4701ae349f5Scvs2svn {
4717308ec68SBrian Somers   /* Add incoming data to the dictionary */
472247ab36dSBrian Somers   if (CcpInfo.in_init)
473247ab36dSBrian Somers     (*algorithm[CcpInfo.in_algorithm]->i.DictSetup)(proto, m);
4741ae349f5Scvs2svn }
475