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