xref: /freebsd/usr.sbin/ppp/ccp.c (revision 5828db6d2dd0f1a405f9140373c37e07395466b6)
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  *
205828db6dSBrian Somers  * $Id: ccp.c,v 1.30.2.19 1998/03/13 00:44:39 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 *);
6283d1af55SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int);
631ae349f5Scvs2svn static void CcpLayerStart(struct fsm *);
641ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *);
651ae349f5Scvs2svn static void CcpLayerUp(struct fsm *);
661ae349f5Scvs2svn static void CcpLayerDown(struct fsm *);
671ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *);
68503a7782SBrian Somers static void CcpRecvResetReq(struct fsm *);
69503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char);
701ae349f5Scvs2svn 
7183d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = {
7283d1af55SBrian Somers   CcpLayerUp,
7383d1af55SBrian Somers   CcpLayerDown,
7483d1af55SBrian Somers   CcpLayerStart,
756d666775SBrian Somers   CcpLayerFinish,
7683d1af55SBrian Somers   CcpInitRestartCounter,
7783d1af55SBrian Somers   CcpSendConfigReq,
7883d1af55SBrian Somers   CcpSendTerminateReq,
7983d1af55SBrian Somers   CcpSendTerminateAck,
80503a7782SBrian Somers   CcpDecodeConfig,
81503a7782SBrian Somers   CcpRecvResetReq,
82503a7782SBrian Somers   CcpRecvResetAck
8383d1af55SBrian Somers };
8483d1af55SBrian Somers 
851ae349f5Scvs2svn static char const *cftypes[] = {
861ae349f5Scvs2svn   /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
871ae349f5Scvs2svn   "OUI",		/* 0: OUI */
881ae349f5Scvs2svn   "PRED1",		/* 1: Predictor type 1 */
891ae349f5Scvs2svn   "PRED2",		/* 2: Predictor type 2 */
901ae349f5Scvs2svn   "PUDDLE",		/* 3: Puddle Jumber */
911ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
921ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
931ae349f5Scvs2svn   "HWPPC",		/* 16: Hewlett-Packard PPC */
941ae349f5Scvs2svn   "STAC",		/* 17: Stac Electronics LZS (rfc1974) */
951ae349f5Scvs2svn   "MSPPC",		/* 18: Microsoft PPC */
961ae349f5Scvs2svn   "GAND",		/* 19: Gandalf FZA (rfc1993) */
971ae349f5Scvs2svn   "V42BIS",		/* 20: ARG->DATA.42bis compression */
981ae349f5Scvs2svn   "BSD",		/* 21: BSD LZW Compress */
991ae349f5Scvs2svn   "???",
1001ae349f5Scvs2svn   "LZS-DCP",		/* 23: LZS-DCP Compression Protocol (rfc1967) */
1011ae349f5Scvs2svn   "MAGNALINK/DEFLATE",	/* 24: Magnalink Variable Resource (rfc1975) */
1021ae349f5Scvs2svn 			/* 24: Deflate (according to pppd-2.3.1) */
1031ae349f5Scvs2svn   "DCE",		/* 25: Data Circuit-Terminating Equip (rfc1976) */
1041ae349f5Scvs2svn   "DEFLATE",		/* 26: Deflate (rfc1979) */
1051ae349f5Scvs2svn };
1061ae349f5Scvs2svn 
1071ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
1081ae349f5Scvs2svn 
1091ae349f5Scvs2svn static const char *
1101ae349f5Scvs2svn protoname(int proto)
1111ae349f5Scvs2svn {
1121ae349f5Scvs2svn   if (proto < 0 || proto > NCFTYPES)
1131ae349f5Scvs2svn     return "none";
1141ae349f5Scvs2svn   return cftypes[proto];
1151ae349f5Scvs2svn }
1161ae349f5Scvs2svn 
1171ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */
1181ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = {
1191ae349f5Scvs2svn   &DeflateAlgorithm,
1201ae349f5Scvs2svn   &Pred1Algorithm,
1211ae349f5Scvs2svn   &PppdDeflateAlgorithm
1221ae349f5Scvs2svn };
1231ae349f5Scvs2svn 
1241ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
1251ae349f5Scvs2svn 
1261ae349f5Scvs2svn int
127503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg)
1281ae349f5Scvs2svn {
129dc0fdb6bSBrian Somers   struct ccp *ccp = arg->cx ? &arg->cx->ccp : bundle2ccp(arg->bundle, NULL);
130503a7782SBrian Somers 
131503a7782SBrian Somers   prompt_Printf(&prompt, "%s [%s]\n", ccp->fsm.name,
132503a7782SBrian Somers                 StateNames[ccp->fsm.state]);
13385b542cfSBrian Somers   prompt_Printf(&prompt, "My protocol = %s, His protocol = %s\n",
134503a7782SBrian Somers                 protoname(ccp->my_proto), protoname(ccp->his_proto));
13585b542cfSBrian Somers   prompt_Printf(&prompt, "Output: %ld --> %ld,  Input: %ld --> %ld\n",
136503a7782SBrian Somers                 ccp->uncompout, ccp->compout,
137503a7782SBrian Somers                 ccp->compin, ccp->uncompin);
1381ae349f5Scvs2svn   return 0;
1391ae349f5Scvs2svn }
1401ae349f5Scvs2svn 
1411ae349f5Scvs2svn void
1426d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l,
1436d666775SBrian Somers          const struct fsm_parent *parent)
1441ae349f5Scvs2svn {
1457308ec68SBrian Somers   /* Initialise ourselves */
146f4768038SBrian Somers   fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, CCP_MAXCODE, 10, LogCCP,
1476d666775SBrian Somers            bundle, l, parent, &ccp_Callbacks);
148503a7782SBrian Somers   ccp_Setup(ccp);
149503a7782SBrian Somers }
150503a7782SBrian Somers 
151503a7782SBrian Somers void
152503a7782SBrian Somers ccp_Setup(struct ccp *ccp)
153503a7782SBrian Somers {
154503a7782SBrian Somers   /* Set ourselves up for a startup */
155503a7782SBrian Somers   ccp->fsm.open_mode = 0;
1565454ccd9SBrian Somers   ccp->fsm.maxconfig = 10;
157503a7782SBrian Somers   ccp->his_proto = ccp->my_proto = -1;
158503a7782SBrian Somers   ccp->reset_sent = ccp->last_reset = -1;
159503a7782SBrian Somers   ccp->in_algorithm = ccp->out_algorithm = -1;
160503a7782SBrian Somers   ccp->his_reject = ccp->my_reject = 0;
161503a7782SBrian Somers   ccp->out_init = ccp->in_init = 0;
162503a7782SBrian Somers   ccp->uncompout = ccp->compout = 0;
163503a7782SBrian Somers   ccp->uncompin = ccp->compin = 0;
1641ae349f5Scvs2svn }
1651ae349f5Scvs2svn 
1661ae349f5Scvs2svn static void
1671ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp)
1681ae349f5Scvs2svn {
1697308ec68SBrian Somers   /* Set fsm timer load */
1701ae349f5Scvs2svn   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1711ae349f5Scvs2svn   fp->restart = 5;
1721ae349f5Scvs2svn }
1731ae349f5Scvs2svn 
1741ae349f5Scvs2svn static void
1751ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp)
1761ae349f5Scvs2svn {
1777308ec68SBrian Somers   /* Send config REQ please */
178aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1791ae349f5Scvs2svn   u_char *cp;
1801ae349f5Scvs2svn   int f;
1811ae349f5Scvs2svn 
1821ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendConfigReq\n");
1831ae349f5Scvs2svn   cp = ReqBuff;
18483d1af55SBrian Somers   ccp->my_proto = -1;
18583d1af55SBrian Somers   ccp->out_algorithm = -1;
1861ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
18783d1af55SBrian Somers     if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) {
1881ae349f5Scvs2svn       struct lcp_opt o;
1891ae349f5Scvs2svn 
1901ae349f5Scvs2svn       (*algorithm[f]->o.Get)(&o);
1911ae349f5Scvs2svn       cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
1921ae349f5Scvs2svn                        (*algorithm[f]->Disp)(&o));
19383d1af55SBrian Somers       ccp->my_proto = o.id;
19483d1af55SBrian Somers       ccp->out_algorithm = f;
1951ae349f5Scvs2svn     }
1961ae349f5Scvs2svn   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
1971ae349f5Scvs2svn }
1981ae349f5Scvs2svn 
1991ae349f5Scvs2svn void
2001ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp)
2011ae349f5Scvs2svn {
2027308ec68SBrian Somers   /* We can't read our input - ask peer to reset */
203aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2041ae349f5Scvs2svn   LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
20583d1af55SBrian Somers   ccp->reset_sent = fp->reqid;
20683d1af55SBrian Somers   ccp->last_reset = -1;
2071ae349f5Scvs2svn   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
2081ae349f5Scvs2svn }
2091ae349f5Scvs2svn 
2101ae349f5Scvs2svn static void
2111ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp)
2121ae349f5Scvs2svn {
2137308ec68SBrian Somers   /* Term REQ just sent by FSM */
2141ae349f5Scvs2svn }
2151ae349f5Scvs2svn 
2161ae349f5Scvs2svn static void
2171ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp)
2181ae349f5Scvs2svn {
2197308ec68SBrian Somers   /* Send Term ACK please */
2201ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendTerminateAck\n");
2211ae349f5Scvs2svn   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2221ae349f5Scvs2svn }
2231ae349f5Scvs2svn 
224503a7782SBrian Somers static void
2251ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp)
2261ae349f5Scvs2svn {
2277308ec68SBrian Somers   /* Got a reset REQ, reset outgoing dictionary */
228aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
22983d1af55SBrian Somers   if (ccp->out_init)
23083d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Reset)();
2311ae349f5Scvs2svn }
2321ae349f5Scvs2svn 
2331ae349f5Scvs2svn static void
2341ae349f5Scvs2svn CcpLayerStart(struct fsm *fp)
2351ae349f5Scvs2svn {
2367308ec68SBrian Somers   /* We're about to start up ! */
2371ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerStart.\n");
2381ae349f5Scvs2svn }
2391ae349f5Scvs2svn 
2401ae349f5Scvs2svn static void
2411ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp)
2421ae349f5Scvs2svn {
2437308ec68SBrian Somers   /* We're now down */
244aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2451ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerFinish.\n");
24683d1af55SBrian Somers   if (ccp->in_init) {
24783d1af55SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Term)();
24883d1af55SBrian Somers     ccp->in_init = 0;
2497308ec68SBrian Somers   }
25083d1af55SBrian Somers   if (ccp->out_init) {
25183d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Term)();
25283d1af55SBrian Somers     ccp->out_init = 0;
2537308ec68SBrian Somers   }
2541ae349f5Scvs2svn }
2551ae349f5Scvs2svn 
2561ae349f5Scvs2svn static void
2571ae349f5Scvs2svn CcpLayerDown(struct fsm *fp)
2581ae349f5Scvs2svn {
2597308ec68SBrian Somers   /* About to come down */
2601ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerDown.\n");
2611ae349f5Scvs2svn }
2621ae349f5Scvs2svn 
2631ae349f5Scvs2svn /*
2641ae349f5Scvs2svn  *  Called when CCP has reached the OPEN state
2651ae349f5Scvs2svn  */
2661ae349f5Scvs2svn static void
2671ae349f5Scvs2svn CcpLayerUp(struct fsm *fp)
2681ae349f5Scvs2svn {
2697308ec68SBrian Somers   /* We're now up */
270aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
271455aabc3SBrian Somers   LogPrintf(LogCCP, "CcpLayerUp.\n");
27283d1af55SBrian Somers   if (!ccp->in_init && ccp->in_algorithm >= 0 &&
27383d1af55SBrian Somers       ccp->in_algorithm < NALGORITHMS)
27483d1af55SBrian Somers     if ((*algorithm[ccp->in_algorithm]->i.Init)())
27583d1af55SBrian Somers       ccp->in_init = 1;
276247ab36dSBrian Somers     else {
277247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (in) initialisation failure\n",
27883d1af55SBrian Somers                 protoname(ccp->his_proto));
27983d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
280247ab36dSBrian Somers       FsmClose(fp);
281247ab36dSBrian Somers     }
28283d1af55SBrian Somers   if (!ccp->out_init && ccp->out_algorithm >= 0 &&
28383d1af55SBrian Somers       ccp->out_algorithm < NALGORITHMS)
28483d1af55SBrian Somers     if ((*algorithm[ccp->out_algorithm]->o.Init)())
28583d1af55SBrian Somers       ccp->out_init = 1;
286247ab36dSBrian Somers     else {
287247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (out) initialisation failure\n",
28883d1af55SBrian Somers                 protoname(ccp->my_proto));
28983d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
290247ab36dSBrian Somers       FsmClose(fp);
291247ab36dSBrian Somers     }
2921ae349f5Scvs2svn   LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
29383d1af55SBrian Somers             protoname(ccp->my_proto), ccp->my_proto,
29483d1af55SBrian Somers             protoname(ccp->his_proto), ccp->his_proto);
2951ae349f5Scvs2svn }
2961ae349f5Scvs2svn 
2971ae349f5Scvs2svn static void
29883d1af55SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type)
2991ae349f5Scvs2svn {
3007308ec68SBrian Somers   /* Deal with incoming data */
301aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
3021ae349f5Scvs2svn   int type, length;
3031ae349f5Scvs2svn   int f;
3041ae349f5Scvs2svn 
3051ae349f5Scvs2svn   ackp = AckBuff;
3061ae349f5Scvs2svn   nakp = NakBuff;
3071ae349f5Scvs2svn   rejp = RejBuff;
3081ae349f5Scvs2svn 
3091ae349f5Scvs2svn   while (plen >= sizeof(struct fsmconfig)) {
3101ae349f5Scvs2svn     type = *cp;
3111ae349f5Scvs2svn     length = cp[1];
3121ae349f5Scvs2svn     if (type < NCFTYPES)
3131ae349f5Scvs2svn       LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
3141ae349f5Scvs2svn     else
3151ae349f5Scvs2svn       LogPrintf(LogCCP, " ???[%d]\n", length);
3161ae349f5Scvs2svn 
3171ae349f5Scvs2svn     for (f = NALGORITHMS-1; f > -1; f--)
3181ae349f5Scvs2svn       if (algorithm[f]->id == type)
3191ae349f5Scvs2svn         break;
3201ae349f5Scvs2svn 
3211ae349f5Scvs2svn     if (f == -1) {
3221ae349f5Scvs2svn       /* Don't understand that :-( */
3231ae349f5Scvs2svn       if (mode_type == MODE_REQ) {
32483d1af55SBrian Somers         ccp->my_reject |= (1 << type);
3251ae349f5Scvs2svn         memcpy(rejp, cp, length);
3261ae349f5Scvs2svn         rejp += length;
3271ae349f5Scvs2svn       }
3281ae349f5Scvs2svn     } else {
3291ae349f5Scvs2svn       struct lcp_opt o;
3301ae349f5Scvs2svn 
3311ae349f5Scvs2svn       switch (mode_type) {
3321ae349f5Scvs2svn       case MODE_REQ:
33383d1af55SBrian Somers 	if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) {
3341ae349f5Scvs2svn 	  memcpy(&o, cp, length);
3351ae349f5Scvs2svn           switch ((*algorithm[f]->i.Set)(&o)) {
3361ae349f5Scvs2svn           case MODE_REJ:
3371ae349f5Scvs2svn 	    memcpy(rejp, &o, o.len);
3381ae349f5Scvs2svn 	    rejp += o.len;
3391ae349f5Scvs2svn             break;
3401ae349f5Scvs2svn           case MODE_NAK:
3411ae349f5Scvs2svn 	    memcpy(nakp, &o, o.len);
3421ae349f5Scvs2svn 	    nakp += o.len;
3431ae349f5Scvs2svn             break;
3441ae349f5Scvs2svn           case MODE_ACK:
3451ae349f5Scvs2svn 	    memcpy(ackp, cp, length);
3461ae349f5Scvs2svn 	    ackp += length;
34783d1af55SBrian Somers 	    ccp->his_proto = type;
34883d1af55SBrian Somers             ccp->in_algorithm = f;		/* This one'll do ! */
3491ae349f5Scvs2svn             break;
3501ae349f5Scvs2svn           }
3511ae349f5Scvs2svn 	} else {
3521ae349f5Scvs2svn 	  memcpy(rejp, cp, length);
3531ae349f5Scvs2svn 	  rejp += length;
3541ae349f5Scvs2svn 	}
3551ae349f5Scvs2svn 	break;
3561ae349f5Scvs2svn       case MODE_NAK:
3571ae349f5Scvs2svn 	memcpy(&o, cp, length);
3581ae349f5Scvs2svn         if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
35983d1af55SBrian Somers           ccp->my_proto = algorithm[f]->id;
3601ae349f5Scvs2svn         else {
36183d1af55SBrian Somers 	  ccp->his_reject |= (1 << type);
36283d1af55SBrian Somers 	  ccp->my_proto = -1;
3631ae349f5Scvs2svn         }
3641ae349f5Scvs2svn         break;
3651ae349f5Scvs2svn       case MODE_REJ:
36683d1af55SBrian Somers 	ccp->his_reject |= (1 << type);
36783d1af55SBrian Somers 	ccp->my_proto = -1;
3681ae349f5Scvs2svn 	break;
3691ae349f5Scvs2svn       }
3701ae349f5Scvs2svn     }
3711ae349f5Scvs2svn 
3721ae349f5Scvs2svn     plen -= length;
3731ae349f5Scvs2svn     cp += length;
3741ae349f5Scvs2svn   }
3751ae349f5Scvs2svn 
3761ae349f5Scvs2svn   if (rejp != RejBuff) {
3771ae349f5Scvs2svn     ackp = AckBuff;	/* let's not send both ! */
37883d1af55SBrian Somers     if (!ccp->in_init) {
37983d1af55SBrian Somers       ccp->his_proto = -1;
38083d1af55SBrian Somers       ccp->in_algorithm = -1;
381247ab36dSBrian Somers     }
3821ae349f5Scvs2svn   }
3831ae349f5Scvs2svn }
3841ae349f5Scvs2svn 
3851ae349f5Scvs2svn void
386f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp)
3871ae349f5Scvs2svn {
3887308ec68SBrian Somers   /* Got PROTO_CCP from link */
389455aabc3SBrian Somers   if (bundle_Phase(bundle) == PHASE_NETWORK)
390f4768038SBrian Somers     FsmInput(&ccp->fsm, bp);
391455aabc3SBrian Somers   else if (bundle_Phase(bundle) < PHASE_NETWORK) {
392455aabc3SBrian Somers     LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n",
393455aabc3SBrian Somers               bundle_PhaseName(bundle));
3941ae349f5Scvs2svn     pfree(bp);
3951ae349f5Scvs2svn   }
3961ae349f5Scvs2svn }
3971ae349f5Scvs2svn 
398503a7782SBrian Somers static void
399503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id)
4001ae349f5Scvs2svn {
4017308ec68SBrian Somers   /* Got a reset ACK, reset incoming dictionary */
402f4768038SBrian Somers   struct ccp *ccp = fsm2ccp(fp);
403f4768038SBrian Somers 
404f4768038SBrian Somers   if (ccp->reset_sent != -1) {
405f4768038SBrian Somers     if (id != ccp->reset_sent) {
4061ae349f5Scvs2svn       LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
407f4768038SBrian Somers                 id, ccp->reset_sent);
4081ae349f5Scvs2svn       return;
4091ae349f5Scvs2svn     }
4101ae349f5Scvs2svn     /* Whaddaya know - a correct reset ack */
411f4768038SBrian Somers   } else if (id == ccp->last_reset)
4121ae349f5Scvs2svn     LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
4131ae349f5Scvs2svn   else {
4141ae349f5Scvs2svn     LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
4151ae349f5Scvs2svn     return;
4161ae349f5Scvs2svn   }
4171ae349f5Scvs2svn 
418f4768038SBrian Somers   ccp->last_reset = ccp->reset_sent;
419f4768038SBrian Somers   ccp->reset_sent = -1;
420f4768038SBrian Somers   if (ccp->in_init)
421f4768038SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Reset)();
4221ae349f5Scvs2svn }
4231ae349f5Scvs2svn 
4241ae349f5Scvs2svn int
425503a7782SBrian Somers ccp_Output(struct ccp *ccp, struct link *l, int pri, u_short proto,
426503a7782SBrian Somers            struct mbuf *m)
4271ae349f5Scvs2svn {
428503a7782SBrian Somers   /* Compress outgoing Network Layer data */
429503a7782SBrian Somers   if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && ccp->out_init)
430f4768038SBrian Somers     return (*algorithm[ccp->out_algorithm]->o.Write)(ccp, l, pri, proto, m);
4311ae349f5Scvs2svn   return 0;
4321ae349f5Scvs2svn }
4331ae349f5Scvs2svn 
4341ae349f5Scvs2svn struct mbuf *
435503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp)
4361ae349f5Scvs2svn {
437ee6c193fSBrian Somers   /*
438ee6c193fSBrian Somers    * If proto isn't PROTO_COMPD, we still want to pass it to the
439ee6c193fSBrian Somers    * decompression routines so that the dictionary's updated
440ee6c193fSBrian Somers    */
441503a7782SBrian Somers   if (ccp->fsm.state == ST_OPENED)
442ee6c193fSBrian Somers     if (*proto == PROTO_COMPD) {
4437308ec68SBrian Somers       /* Decompress incoming data */
444503a7782SBrian Somers       if (ccp->reset_sent != -1) {
4451ae349f5Scvs2svn         /* Send another REQ and put the packet in the bit bucket */
446503a7782SBrian Somers         LogPrintf(LogCCP, "ReSendResetReq(%d)\n", ccp->reset_sent);
447503a7782SBrian Somers         FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0);
448503a7782SBrian Somers       } else if (ccp->in_init)
449f4768038SBrian Somers         return (*algorithm[ccp->in_algorithm]->i.Read)(ccp, proto, bp);
450ee6c193fSBrian Somers       pfree(bp);
451ee6c193fSBrian Somers       bp = NULL;
452503a7782SBrian Somers     } else if ((*proto & 0xfff1) == 0x21 && ccp->in_init)
453ee6c193fSBrian Somers       /* Add incoming Network Layer traffic to our dictionary */
454f4768038SBrian Somers       (*algorithm[ccp->in_algorithm]->i.DictSetup)(ccp, *proto, bp);
4551ae349f5Scvs2svn 
456ee6c193fSBrian Somers   return bp;
4571ae349f5Scvs2svn }
458