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 * 206d666775SBrian Somers * $Id: ccp.c,v 1.30.2.14 1998/02/24 03:36: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" 48503a7782SBrian Somers #include "hdlc.h" 49503a7782SBrian Somers #include "throughput.h" 50503a7782SBrian Somers #include "link.h" 51503a7782SBrian Somers #include "chat.h" 52503a7782SBrian Somers #include "datalink.h" 531ae349f5Scvs2svn 541ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *); 551ae349f5Scvs2svn static void CcpSendTerminateReq(struct fsm *); 561ae349f5Scvs2svn static void CcpSendTerminateAck(struct fsm *); 5783d1af55SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int); 581ae349f5Scvs2svn static void CcpLayerStart(struct fsm *); 591ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *); 601ae349f5Scvs2svn static void CcpLayerUp(struct fsm *); 611ae349f5Scvs2svn static void CcpLayerDown(struct fsm *); 621ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *); 63503a7782SBrian Somers static void CcpRecvResetReq(struct fsm *); 64503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char); 651ae349f5Scvs2svn 6683d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 6783d1af55SBrian Somers CcpLayerUp, 6883d1af55SBrian Somers CcpLayerDown, 6983d1af55SBrian Somers CcpLayerStart, 706d666775SBrian Somers CcpLayerFinish, 7183d1af55SBrian Somers CcpInitRestartCounter, 7283d1af55SBrian Somers CcpSendConfigReq, 7383d1af55SBrian Somers CcpSendTerminateReq, 7483d1af55SBrian Somers CcpSendTerminateAck, 75503a7782SBrian Somers CcpDecodeConfig, 76503a7782SBrian Somers CcpRecvResetReq, 77503a7782SBrian Somers CcpRecvResetAck 7883d1af55SBrian Somers }; 7983d1af55SBrian Somers 801ae349f5Scvs2svn static char const *cftypes[] = { 811ae349f5Scvs2svn /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 821ae349f5Scvs2svn "OUI", /* 0: OUI */ 831ae349f5Scvs2svn "PRED1", /* 1: Predictor type 1 */ 841ae349f5Scvs2svn "PRED2", /* 2: Predictor type 2 */ 851ae349f5Scvs2svn "PUDDLE", /* 3: Puddle Jumber */ 861ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 871ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 881ae349f5Scvs2svn "HWPPC", /* 16: Hewlett-Packard PPC */ 891ae349f5Scvs2svn "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 901ae349f5Scvs2svn "MSPPC", /* 18: Microsoft PPC */ 911ae349f5Scvs2svn "GAND", /* 19: Gandalf FZA (rfc1993) */ 921ae349f5Scvs2svn "V42BIS", /* 20: ARG->DATA.42bis compression */ 931ae349f5Scvs2svn "BSD", /* 21: BSD LZW Compress */ 941ae349f5Scvs2svn "???", 951ae349f5Scvs2svn "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 961ae349f5Scvs2svn "MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */ 971ae349f5Scvs2svn /* 24: Deflate (according to pppd-2.3.1) */ 981ae349f5Scvs2svn "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 991ae349f5Scvs2svn "DEFLATE", /* 26: Deflate (rfc1979) */ 1001ae349f5Scvs2svn }; 1011ae349f5Scvs2svn 1021ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1031ae349f5Scvs2svn 1041ae349f5Scvs2svn static const char * 1051ae349f5Scvs2svn protoname(int proto) 1061ae349f5Scvs2svn { 1071ae349f5Scvs2svn if (proto < 0 || proto > NCFTYPES) 1081ae349f5Scvs2svn return "none"; 1091ae349f5Scvs2svn return cftypes[proto]; 1101ae349f5Scvs2svn } 1111ae349f5Scvs2svn 1121ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */ 1131ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = { 1141ae349f5Scvs2svn &DeflateAlgorithm, 1151ae349f5Scvs2svn &Pred1Algorithm, 1161ae349f5Scvs2svn &PppdDeflateAlgorithm 1171ae349f5Scvs2svn }; 1181ae349f5Scvs2svn 1191ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1201ae349f5Scvs2svn 1211ae349f5Scvs2svn int 122503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg) 1231ae349f5Scvs2svn { 124503a7782SBrian Somers struct ccp *ccp = bundle2ccp(arg->bundle, arg->cx ? arg->cx->name : NULL); 125503a7782SBrian Somers 126503a7782SBrian Somers prompt_Printf(&prompt, "%s [%s]\n", ccp->fsm.name, 127503a7782SBrian Somers StateNames[ccp->fsm.state]); 12885b542cfSBrian Somers prompt_Printf(&prompt, "My protocol = %s, His protocol = %s\n", 129503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 13085b542cfSBrian Somers prompt_Printf(&prompt, "Output: %ld --> %ld, Input: %ld --> %ld\n", 131503a7782SBrian Somers ccp->uncompout, ccp->compout, 132503a7782SBrian Somers ccp->compin, ccp->uncompin); 1331ae349f5Scvs2svn return 0; 1341ae349f5Scvs2svn } 1351ae349f5Scvs2svn 1361ae349f5Scvs2svn void 1376d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 1386d666775SBrian Somers const struct fsm_parent *parent) 1391ae349f5Scvs2svn { 1407308ec68SBrian Somers /* Initialise ourselves */ 141f4768038SBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, CCP_MAXCODE, 10, LogCCP, 1426d666775SBrian Somers bundle, l, parent, &ccp_Callbacks); 143503a7782SBrian Somers ccp_Setup(ccp); 144503a7782SBrian Somers } 145503a7782SBrian Somers 146503a7782SBrian Somers void 147503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 148503a7782SBrian Somers { 149503a7782SBrian Somers /* Set ourselves up for a startup */ 150503a7782SBrian Somers ccp->fsm.open_mode = 0; 151503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 152503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 153503a7782SBrian Somers ccp->in_algorithm = ccp->out_algorithm = -1; 154503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 155503a7782SBrian Somers ccp->out_init = ccp->in_init = 0; 156503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 157503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 1581ae349f5Scvs2svn } 1591ae349f5Scvs2svn 1601ae349f5Scvs2svn static void 1611ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp) 1621ae349f5Scvs2svn { 1637308ec68SBrian Somers /* Set fsm timer load */ 1641ae349f5Scvs2svn fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 1651ae349f5Scvs2svn fp->restart = 5; 1661ae349f5Scvs2svn } 1671ae349f5Scvs2svn 1681ae349f5Scvs2svn static void 1691ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp) 1701ae349f5Scvs2svn { 1717308ec68SBrian Somers /* Send config REQ please */ 172aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 1731ae349f5Scvs2svn u_char *cp; 1741ae349f5Scvs2svn int f; 1751ae349f5Scvs2svn 1761ae349f5Scvs2svn LogPrintf(LogCCP, "CcpSendConfigReq\n"); 1771ae349f5Scvs2svn cp = ReqBuff; 17883d1af55SBrian Somers ccp->my_proto = -1; 17983d1af55SBrian Somers ccp->out_algorithm = -1; 1801ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 18183d1af55SBrian Somers if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) { 1821ae349f5Scvs2svn struct lcp_opt o; 1831ae349f5Scvs2svn 1841ae349f5Scvs2svn (*algorithm[f]->o.Get)(&o); 1851ae349f5Scvs2svn cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id], 1861ae349f5Scvs2svn (*algorithm[f]->Disp)(&o)); 18783d1af55SBrian Somers ccp->my_proto = o.id; 18883d1af55SBrian Somers ccp->out_algorithm = f; 1891ae349f5Scvs2svn } 1901ae349f5Scvs2svn FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 1911ae349f5Scvs2svn } 1921ae349f5Scvs2svn 1931ae349f5Scvs2svn void 1941ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp) 1951ae349f5Scvs2svn { 1967308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 197aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 1981ae349f5Scvs2svn LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid); 19983d1af55SBrian Somers ccp->reset_sent = fp->reqid; 20083d1af55SBrian Somers ccp->last_reset = -1; 2011ae349f5Scvs2svn FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 2021ae349f5Scvs2svn } 2031ae349f5Scvs2svn 2041ae349f5Scvs2svn static void 2051ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp) 2061ae349f5Scvs2svn { 2077308ec68SBrian Somers /* Term REQ just sent by FSM */ 2081ae349f5Scvs2svn } 2091ae349f5Scvs2svn 2101ae349f5Scvs2svn static void 2111ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp) 2121ae349f5Scvs2svn { 2137308ec68SBrian Somers /* Send Term ACK please */ 2141ae349f5Scvs2svn LogPrintf(LogCCP, "CcpSendTerminateAck\n"); 2151ae349f5Scvs2svn FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 2161ae349f5Scvs2svn } 2171ae349f5Scvs2svn 218503a7782SBrian Somers static void 2191ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp) 2201ae349f5Scvs2svn { 2217308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 222aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 22383d1af55SBrian Somers if (ccp->out_init) 22483d1af55SBrian Somers (*algorithm[ccp->out_algorithm]->o.Reset)(); 2251ae349f5Scvs2svn } 2261ae349f5Scvs2svn 2271ae349f5Scvs2svn static void 2281ae349f5Scvs2svn CcpLayerStart(struct fsm *fp) 2291ae349f5Scvs2svn { 2307308ec68SBrian Somers /* We're about to start up ! */ 2311ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerStart.\n"); 2321ae349f5Scvs2svn } 2331ae349f5Scvs2svn 2341ae349f5Scvs2svn static void 2351ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp) 2361ae349f5Scvs2svn { 2377308ec68SBrian Somers /* We're now down */ 238aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2391ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerFinish.\n"); 24083d1af55SBrian Somers if (ccp->in_init) { 24183d1af55SBrian Somers (*algorithm[ccp->in_algorithm]->i.Term)(); 24283d1af55SBrian Somers ccp->in_init = 0; 2437308ec68SBrian Somers } 24483d1af55SBrian Somers if (ccp->out_init) { 24583d1af55SBrian Somers (*algorithm[ccp->out_algorithm]->o.Term)(); 24683d1af55SBrian Somers ccp->out_init = 0; 2477308ec68SBrian Somers } 2481ae349f5Scvs2svn } 2491ae349f5Scvs2svn 2501ae349f5Scvs2svn static void 2511ae349f5Scvs2svn CcpLayerDown(struct fsm *fp) 2521ae349f5Scvs2svn { 2537308ec68SBrian Somers /* About to come down */ 2541ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerDown.\n"); 2551ae349f5Scvs2svn } 2561ae349f5Scvs2svn 2571ae349f5Scvs2svn /* 2581ae349f5Scvs2svn * Called when CCP has reached the OPEN state 2591ae349f5Scvs2svn */ 2601ae349f5Scvs2svn static void 2611ae349f5Scvs2svn CcpLayerUp(struct fsm *fp) 2621ae349f5Scvs2svn { 2637308ec68SBrian Somers /* We're now up */ 264aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 265455aabc3SBrian Somers LogPrintf(LogCCP, "CcpLayerUp.\n"); 26683d1af55SBrian Somers if (!ccp->in_init && ccp->in_algorithm >= 0 && 26783d1af55SBrian Somers ccp->in_algorithm < NALGORITHMS) 26883d1af55SBrian Somers if ((*algorithm[ccp->in_algorithm]->i.Init)()) 26983d1af55SBrian Somers ccp->in_init = 1; 270247ab36dSBrian Somers else { 271247ab36dSBrian Somers LogPrintf(LogERROR, "%s (in) initialisation failure\n", 27283d1af55SBrian Somers protoname(ccp->his_proto)); 27383d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 274247ab36dSBrian Somers FsmClose(fp); 275247ab36dSBrian Somers } 27683d1af55SBrian Somers if (!ccp->out_init && ccp->out_algorithm >= 0 && 27783d1af55SBrian Somers ccp->out_algorithm < NALGORITHMS) 27883d1af55SBrian Somers if ((*algorithm[ccp->out_algorithm]->o.Init)()) 27983d1af55SBrian Somers ccp->out_init = 1; 280247ab36dSBrian Somers else { 281247ab36dSBrian Somers LogPrintf(LogERROR, "%s (out) initialisation failure\n", 28283d1af55SBrian Somers protoname(ccp->my_proto)); 28383d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 284247ab36dSBrian Somers FsmClose(fp); 285247ab36dSBrian Somers } 2861ae349f5Scvs2svn LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 28783d1af55SBrian Somers protoname(ccp->my_proto), ccp->my_proto, 28883d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 2891ae349f5Scvs2svn } 2901ae349f5Scvs2svn 2911ae349f5Scvs2svn static void 29283d1af55SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type) 2931ae349f5Scvs2svn { 2947308ec68SBrian Somers /* Deal with incoming data */ 295aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2961ae349f5Scvs2svn int type, length; 2971ae349f5Scvs2svn int f; 2981ae349f5Scvs2svn 2991ae349f5Scvs2svn ackp = AckBuff; 3001ae349f5Scvs2svn nakp = NakBuff; 3011ae349f5Scvs2svn rejp = RejBuff; 3021ae349f5Scvs2svn 3031ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 3041ae349f5Scvs2svn type = *cp; 3051ae349f5Scvs2svn length = cp[1]; 3061ae349f5Scvs2svn if (type < NCFTYPES) 3071ae349f5Scvs2svn LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length); 3081ae349f5Scvs2svn else 3091ae349f5Scvs2svn LogPrintf(LogCCP, " ???[%d]\n", length); 3101ae349f5Scvs2svn 3111ae349f5Scvs2svn for (f = NALGORITHMS-1; f > -1; f--) 3121ae349f5Scvs2svn if (algorithm[f]->id == type) 3131ae349f5Scvs2svn break; 3141ae349f5Scvs2svn 3151ae349f5Scvs2svn if (f == -1) { 3161ae349f5Scvs2svn /* Don't understand that :-( */ 3171ae349f5Scvs2svn if (mode_type == MODE_REQ) { 31883d1af55SBrian Somers ccp->my_reject |= (1 << type); 3191ae349f5Scvs2svn memcpy(rejp, cp, length); 3201ae349f5Scvs2svn rejp += length; 3211ae349f5Scvs2svn } 3221ae349f5Scvs2svn } else { 3231ae349f5Scvs2svn struct lcp_opt o; 3241ae349f5Scvs2svn 3251ae349f5Scvs2svn switch (mode_type) { 3261ae349f5Scvs2svn case MODE_REQ: 32783d1af55SBrian Somers if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) { 3281ae349f5Scvs2svn memcpy(&o, cp, length); 3291ae349f5Scvs2svn switch ((*algorithm[f]->i.Set)(&o)) { 3301ae349f5Scvs2svn case MODE_REJ: 3311ae349f5Scvs2svn memcpy(rejp, &o, o.len); 3321ae349f5Scvs2svn rejp += o.len; 3331ae349f5Scvs2svn break; 3341ae349f5Scvs2svn case MODE_NAK: 3351ae349f5Scvs2svn memcpy(nakp, &o, o.len); 3361ae349f5Scvs2svn nakp += o.len; 3371ae349f5Scvs2svn break; 3381ae349f5Scvs2svn case MODE_ACK: 3391ae349f5Scvs2svn memcpy(ackp, cp, length); 3401ae349f5Scvs2svn ackp += length; 34183d1af55SBrian Somers ccp->his_proto = type; 34283d1af55SBrian Somers ccp->in_algorithm = f; /* This one'll do ! */ 3431ae349f5Scvs2svn break; 3441ae349f5Scvs2svn } 3451ae349f5Scvs2svn } else { 3461ae349f5Scvs2svn memcpy(rejp, cp, length); 3471ae349f5Scvs2svn rejp += length; 3481ae349f5Scvs2svn } 3491ae349f5Scvs2svn break; 3501ae349f5Scvs2svn case MODE_NAK: 3511ae349f5Scvs2svn memcpy(&o, cp, length); 3521ae349f5Scvs2svn if ((*algorithm[f]->o.Set)(&o) == MODE_ACK) 35383d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 3541ae349f5Scvs2svn else { 35583d1af55SBrian Somers ccp->his_reject |= (1 << type); 35683d1af55SBrian Somers ccp->my_proto = -1; 3571ae349f5Scvs2svn } 3581ae349f5Scvs2svn break; 3591ae349f5Scvs2svn case MODE_REJ: 36083d1af55SBrian Somers ccp->his_reject |= (1 << type); 36183d1af55SBrian Somers ccp->my_proto = -1; 3621ae349f5Scvs2svn break; 3631ae349f5Scvs2svn } 3641ae349f5Scvs2svn } 3651ae349f5Scvs2svn 3661ae349f5Scvs2svn plen -= length; 3671ae349f5Scvs2svn cp += length; 3681ae349f5Scvs2svn } 3691ae349f5Scvs2svn 3701ae349f5Scvs2svn if (rejp != RejBuff) { 3711ae349f5Scvs2svn ackp = AckBuff; /* let's not send both ! */ 37283d1af55SBrian Somers if (!ccp->in_init) { 37383d1af55SBrian Somers ccp->his_proto = -1; 37483d1af55SBrian Somers ccp->in_algorithm = -1; 375247ab36dSBrian Somers } 3761ae349f5Scvs2svn } 3771ae349f5Scvs2svn } 3781ae349f5Scvs2svn 3791ae349f5Scvs2svn void 380f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp) 3811ae349f5Scvs2svn { 3827308ec68SBrian Somers /* Got PROTO_CCP from link */ 383455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 384f4768038SBrian Somers FsmInput(&ccp->fsm, bp); 385455aabc3SBrian Somers else if (bundle_Phase(bundle) < PHASE_NETWORK) { 386455aabc3SBrian Somers LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n", 387455aabc3SBrian Somers bundle_PhaseName(bundle)); 3881ae349f5Scvs2svn pfree(bp); 3891ae349f5Scvs2svn } 3901ae349f5Scvs2svn } 3911ae349f5Scvs2svn 392503a7782SBrian Somers static void 393503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 3941ae349f5Scvs2svn { 3957308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 396f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 397f4768038SBrian Somers 398f4768038SBrian Somers if (ccp->reset_sent != -1) { 399f4768038SBrian Somers if (id != ccp->reset_sent) { 4001ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n", 401f4768038SBrian Somers id, ccp->reset_sent); 4021ae349f5Scvs2svn return; 4031ae349f5Scvs2svn } 4041ae349f5Scvs2svn /* Whaddaya know - a correct reset ack */ 405f4768038SBrian Somers } else if (id == ccp->last_reset) 4061ae349f5Scvs2svn LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n"); 4071ae349f5Scvs2svn else { 4081ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id); 4091ae349f5Scvs2svn return; 4101ae349f5Scvs2svn } 4111ae349f5Scvs2svn 412f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 413f4768038SBrian Somers ccp->reset_sent = -1; 414f4768038SBrian Somers if (ccp->in_init) 415f4768038SBrian Somers (*algorithm[ccp->in_algorithm]->i.Reset)(); 4161ae349f5Scvs2svn } 4171ae349f5Scvs2svn 4181ae349f5Scvs2svn int 419503a7782SBrian Somers ccp_Output(struct ccp *ccp, struct link *l, int pri, u_short proto, 420503a7782SBrian Somers struct mbuf *m) 4211ae349f5Scvs2svn { 422503a7782SBrian Somers /* Compress outgoing Network Layer data */ 423503a7782SBrian Somers if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && ccp->out_init) 424f4768038SBrian Somers return (*algorithm[ccp->out_algorithm]->o.Write)(ccp, l, pri, proto, m); 4251ae349f5Scvs2svn return 0; 4261ae349f5Scvs2svn } 4271ae349f5Scvs2svn 4281ae349f5Scvs2svn struct mbuf * 429503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp) 4301ae349f5Scvs2svn { 431ee6c193fSBrian Somers /* 432ee6c193fSBrian Somers * If proto isn't PROTO_COMPD, we still want to pass it to the 433ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 434ee6c193fSBrian Somers */ 435503a7782SBrian Somers if (ccp->fsm.state == ST_OPENED) 436ee6c193fSBrian Somers if (*proto == PROTO_COMPD) { 4377308ec68SBrian Somers /* Decompress incoming data */ 438503a7782SBrian Somers if (ccp->reset_sent != -1) { 4391ae349f5Scvs2svn /* Send another REQ and put the packet in the bit bucket */ 440503a7782SBrian Somers LogPrintf(LogCCP, "ReSendResetReq(%d)\n", ccp->reset_sent); 441503a7782SBrian Somers FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0); 442503a7782SBrian Somers } else if (ccp->in_init) 443f4768038SBrian Somers return (*algorithm[ccp->in_algorithm]->i.Read)(ccp, proto, bp); 444ee6c193fSBrian Somers pfree(bp); 445ee6c193fSBrian Somers bp = NULL; 446503a7782SBrian Somers } else if ((*proto & 0xfff1) == 0x21 && ccp->in_init) 447ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 448f4768038SBrian Somers (*algorithm[ccp->in_algorithm]->i.DictSetup)(ccp, *proto, bp); 4491ae349f5Scvs2svn 450ee6c193fSBrian Somers return bp; 4511ae349f5Scvs2svn } 452