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