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 * 20aad81d1eSBrian Somers * $Id: ccp.c,v 1.30.2.7 1998/02/07 20:49:26 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> 301ae349f5Scvs2svn 311ae349f5Scvs2svn #include "command.h" 321ae349f5Scvs2svn #include "mbuf.h" 331ae349f5Scvs2svn #include "log.h" 341ae349f5Scvs2svn #include "defs.h" 351ae349f5Scvs2svn #include "timer.h" 361ae349f5Scvs2svn #include "fsm.h" 371ae349f5Scvs2svn #include "lcpproto.h" 381ae349f5Scvs2svn #include "lcp.h" 391ae349f5Scvs2svn #include "ccp.h" 401ae349f5Scvs2svn #include "loadalias.h" 411ae349f5Scvs2svn #include "vars.h" 421ae349f5Scvs2svn #include "pred.h" 431ae349f5Scvs2svn #include "deflate.h" 44455aabc3SBrian Somers #include "bundle.h" 451ae349f5Scvs2svn 461ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *); 471ae349f5Scvs2svn static void CcpSendTerminateReq(struct fsm *); 481ae349f5Scvs2svn static void CcpSendTerminateAck(struct fsm *); 4983d1af55SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int); 501ae349f5Scvs2svn static void CcpLayerStart(struct fsm *); 511ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *); 521ae349f5Scvs2svn static void CcpLayerUp(struct fsm *); 531ae349f5Scvs2svn static void CcpLayerDown(struct fsm *); 541ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *); 551ae349f5Scvs2svn 5683d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 5783d1af55SBrian Somers CcpLayerUp, 5883d1af55SBrian Somers CcpLayerDown, 5983d1af55SBrian Somers CcpLayerStart, 6083d1af55SBrian Somers CcpLayerFinish, 6183d1af55SBrian Somers CcpInitRestartCounter, 6283d1af55SBrian Somers CcpSendConfigReq, 6383d1af55SBrian Somers CcpSendTerminateReq, 6483d1af55SBrian Somers CcpSendTerminateAck, 6583d1af55SBrian Somers CcpDecodeConfig 6683d1af55SBrian Somers }; 6783d1af55SBrian Somers 68aad81d1eSBrian Somers struct ccp CcpInfo = { 697308ec68SBrian Somers { 701ae349f5Scvs2svn "CCP", 711ae349f5Scvs2svn PROTO_CCP, 721ae349f5Scvs2svn CCP_MAXCODE, 731ae349f5Scvs2svn 0, 741ae349f5Scvs2svn ST_INITIAL, 751ae349f5Scvs2svn 0, 0, 0, 761ae349f5Scvs2svn {0, 0, 0, NULL, NULL, NULL}, /* FSM timer */ 771ae349f5Scvs2svn {0, 0, 0, NULL, NULL, NULL}, /* Open timer */ 781ae349f5Scvs2svn {0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */ 791ae349f5Scvs2svn LogCCP, 807a6f8720SBrian Somers NULL, /* link */ 817a6f8720SBrian Somers NULL, /* bundle */ 8283d1af55SBrian Somers &ccp_Callbacks 837308ec68SBrian Somers }, 847308ec68SBrian Somers -1, -1, -1, -1, -1, -1 851ae349f5Scvs2svn }; 861ae349f5Scvs2svn 871ae349f5Scvs2svn static char const *cftypes[] = { 881ae349f5Scvs2svn /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 891ae349f5Scvs2svn "OUI", /* 0: OUI */ 901ae349f5Scvs2svn "PRED1", /* 1: Predictor type 1 */ 911ae349f5Scvs2svn "PRED2", /* 2: Predictor type 2 */ 921ae349f5Scvs2svn "PUDDLE", /* 3: Puddle Jumber */ 931ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 941ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 951ae349f5Scvs2svn "HWPPC", /* 16: Hewlett-Packard PPC */ 961ae349f5Scvs2svn "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 971ae349f5Scvs2svn "MSPPC", /* 18: Microsoft PPC */ 981ae349f5Scvs2svn "GAND", /* 19: Gandalf FZA (rfc1993) */ 991ae349f5Scvs2svn "V42BIS", /* 20: ARG->DATA.42bis compression */ 1001ae349f5Scvs2svn "BSD", /* 21: BSD LZW Compress */ 1011ae349f5Scvs2svn "???", 1021ae349f5Scvs2svn "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 1031ae349f5Scvs2svn "MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */ 1041ae349f5Scvs2svn /* 24: Deflate (according to pppd-2.3.1) */ 1051ae349f5Scvs2svn "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 1061ae349f5Scvs2svn "DEFLATE", /* 26: Deflate (rfc1979) */ 1071ae349f5Scvs2svn }; 1081ae349f5Scvs2svn 1091ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1101ae349f5Scvs2svn 1111ae349f5Scvs2svn static const char * 1121ae349f5Scvs2svn protoname(int proto) 1131ae349f5Scvs2svn { 1141ae349f5Scvs2svn if (proto < 0 || proto > NCFTYPES) 1151ae349f5Scvs2svn return "none"; 1161ae349f5Scvs2svn return cftypes[proto]; 1171ae349f5Scvs2svn } 1181ae349f5Scvs2svn 1191ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */ 1201ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = { 1211ae349f5Scvs2svn &DeflateAlgorithm, 1221ae349f5Scvs2svn &Pred1Algorithm, 1231ae349f5Scvs2svn &PppdDeflateAlgorithm 1241ae349f5Scvs2svn }; 1251ae349f5Scvs2svn 1261ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1271ae349f5Scvs2svn 1281ae349f5Scvs2svn int 1291ae349f5Scvs2svn ReportCcpStatus(struct cmdargs const *arg) 1301ae349f5Scvs2svn { 1311ae349f5Scvs2svn if (VarTerm) { 1327308ec68SBrian Somers fprintf(VarTerm, "%s [%s]\n", CcpInfo.fsm.name, 1337308ec68SBrian Somers StateNames[CcpInfo.fsm.state]); 1341ae349f5Scvs2svn fprintf(VarTerm, "My protocol = %s, His protocol = %s\n", 1351ae349f5Scvs2svn protoname(CcpInfo.my_proto), protoname(CcpInfo.his_proto)); 1361ae349f5Scvs2svn fprintf(VarTerm, "Output: %ld --> %ld, Input: %ld --> %ld\n", 1371ae349f5Scvs2svn CcpInfo.uncompout, CcpInfo.compout, 1381ae349f5Scvs2svn CcpInfo.compin, CcpInfo.uncompin); 1391ae349f5Scvs2svn } 1401ae349f5Scvs2svn return 0; 1411ae349f5Scvs2svn } 1421ae349f5Scvs2svn 1431ae349f5Scvs2svn void 1447a6f8720SBrian Somers CcpInit(struct bundle *bundle, struct link *l) 1451ae349f5Scvs2svn { 1467308ec68SBrian Somers /* Initialise ourselves */ 1477a6f8720SBrian Somers FsmInit(&CcpInfo.fsm, bundle, l); 1487308ec68SBrian Somers CcpInfo.his_proto = CcpInfo.my_proto = -1; 1497308ec68SBrian Somers CcpInfo.reset_sent = CcpInfo.last_reset = -1; 1507308ec68SBrian Somers CcpInfo.in_algorithm = CcpInfo.out_algorithm = -1; 1517308ec68SBrian Somers CcpInfo.his_reject = CcpInfo.my_reject = 0; 1527308ec68SBrian Somers CcpInfo.out_init = CcpInfo.in_init = 0; 1537308ec68SBrian Somers CcpInfo.uncompout = CcpInfo.compout = 0; 1547308ec68SBrian Somers CcpInfo.uncompin = CcpInfo.compin = 0; 1557308ec68SBrian Somers CcpInfo.fsm.maxconfig = 10; 1561ae349f5Scvs2svn } 1571ae349f5Scvs2svn 1581ae349f5Scvs2svn static void 1591ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp) 1601ae349f5Scvs2svn { 1617308ec68SBrian Somers /* Set fsm timer load */ 1621ae349f5Scvs2svn fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 1631ae349f5Scvs2svn fp->restart = 5; 1641ae349f5Scvs2svn } 1651ae349f5Scvs2svn 1661ae349f5Scvs2svn static void 1671ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp) 1681ae349f5Scvs2svn { 1697308ec68SBrian Somers /* Send config REQ please */ 170aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 1711ae349f5Scvs2svn u_char *cp; 1721ae349f5Scvs2svn int f; 1731ae349f5Scvs2svn 1741ae349f5Scvs2svn LogPrintf(LogCCP, "CcpSendConfigReq\n"); 1751ae349f5Scvs2svn cp = ReqBuff; 17683d1af55SBrian Somers ccp->my_proto = -1; 17783d1af55SBrian Somers ccp->out_algorithm = -1; 1781ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 17983d1af55SBrian Somers if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) { 1801ae349f5Scvs2svn struct lcp_opt o; 1811ae349f5Scvs2svn 1821ae349f5Scvs2svn (*algorithm[f]->o.Get)(&o); 1831ae349f5Scvs2svn cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id], 1841ae349f5Scvs2svn (*algorithm[f]->Disp)(&o)); 18583d1af55SBrian Somers ccp->my_proto = o.id; 18683d1af55SBrian Somers ccp->out_algorithm = f; 1871ae349f5Scvs2svn } 1881ae349f5Scvs2svn FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 1891ae349f5Scvs2svn } 1901ae349f5Scvs2svn 1911ae349f5Scvs2svn void 1921ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp) 1931ae349f5Scvs2svn { 1947308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 195aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 1961ae349f5Scvs2svn LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid); 19783d1af55SBrian Somers ccp->reset_sent = fp->reqid; 19883d1af55SBrian Somers ccp->last_reset = -1; 1991ae349f5Scvs2svn FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 2001ae349f5Scvs2svn } 2011ae349f5Scvs2svn 2021ae349f5Scvs2svn static void 2031ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp) 2041ae349f5Scvs2svn { 2057308ec68SBrian Somers /* Term REQ just sent by FSM */ 2061ae349f5Scvs2svn } 2071ae349f5Scvs2svn 2081ae349f5Scvs2svn static void 2091ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp) 2101ae349f5Scvs2svn { 2117308ec68SBrian Somers /* Send Term ACK please */ 2121ae349f5Scvs2svn LogPrintf(LogCCP, "CcpSendTerminateAck\n"); 2131ae349f5Scvs2svn FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 2141ae349f5Scvs2svn } 2151ae349f5Scvs2svn 2161ae349f5Scvs2svn void 2171ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp) 2181ae349f5Scvs2svn { 2197308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 220aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 22183d1af55SBrian Somers if (ccp->out_init) 22283d1af55SBrian Somers (*algorithm[ccp->out_algorithm]->o.Reset)(); 2231ae349f5Scvs2svn } 2241ae349f5Scvs2svn 2251ae349f5Scvs2svn static void 2261ae349f5Scvs2svn CcpLayerStart(struct fsm *fp) 2271ae349f5Scvs2svn { 2287308ec68SBrian Somers /* We're about to start up ! */ 2291ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerStart.\n"); 2301ae349f5Scvs2svn } 2311ae349f5Scvs2svn 2321ae349f5Scvs2svn static void 2331ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp) 2341ae349f5Scvs2svn { 2357308ec68SBrian Somers /* We're now down */ 236aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2371ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerFinish.\n"); 23883d1af55SBrian Somers if (ccp->in_init) { 23983d1af55SBrian Somers (*algorithm[ccp->in_algorithm]->i.Term)(); 24083d1af55SBrian Somers ccp->in_init = 0; 2417308ec68SBrian Somers } 24283d1af55SBrian Somers if (ccp->out_init) { 24383d1af55SBrian Somers (*algorithm[ccp->out_algorithm]->o.Term)(); 24483d1af55SBrian Somers ccp->out_init = 0; 2457308ec68SBrian Somers } 2461ae349f5Scvs2svn } 2471ae349f5Scvs2svn 2481ae349f5Scvs2svn static void 2491ae349f5Scvs2svn CcpLayerDown(struct fsm *fp) 2501ae349f5Scvs2svn { 2517308ec68SBrian Somers /* About to come down */ 2521ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerDown.\n"); 2531ae349f5Scvs2svn } 2541ae349f5Scvs2svn 2551ae349f5Scvs2svn /* 2561ae349f5Scvs2svn * Called when CCP has reached the OPEN state 2571ae349f5Scvs2svn */ 2581ae349f5Scvs2svn static void 2591ae349f5Scvs2svn CcpLayerUp(struct fsm *fp) 2601ae349f5Scvs2svn { 2617308ec68SBrian Somers /* We're now up */ 262aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 263455aabc3SBrian Somers LogPrintf(LogCCP, "CcpLayerUp.\n"); 26483d1af55SBrian Somers if (!ccp->in_init && ccp->in_algorithm >= 0 && 26583d1af55SBrian Somers ccp->in_algorithm < NALGORITHMS) 26683d1af55SBrian Somers if ((*algorithm[ccp->in_algorithm]->i.Init)()) 26783d1af55SBrian Somers ccp->in_init = 1; 268247ab36dSBrian Somers else { 269247ab36dSBrian Somers LogPrintf(LogERROR, "%s (in) initialisation failure\n", 27083d1af55SBrian Somers protoname(ccp->his_proto)); 27183d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 272247ab36dSBrian Somers FsmClose(fp); 273247ab36dSBrian Somers } 27483d1af55SBrian Somers if (!ccp->out_init && ccp->out_algorithm >= 0 && 27583d1af55SBrian Somers ccp->out_algorithm < NALGORITHMS) 27683d1af55SBrian Somers if ((*algorithm[ccp->out_algorithm]->o.Init)()) 27783d1af55SBrian Somers ccp->out_init = 1; 278247ab36dSBrian Somers else { 279247ab36dSBrian Somers LogPrintf(LogERROR, "%s (out) initialisation failure\n", 28083d1af55SBrian Somers protoname(ccp->my_proto)); 28183d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 282247ab36dSBrian Somers FsmClose(fp); 283247ab36dSBrian Somers } 2841ae349f5Scvs2svn LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 28583d1af55SBrian Somers protoname(ccp->my_proto), ccp->my_proto, 28683d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 2871ae349f5Scvs2svn } 2881ae349f5Scvs2svn 2891ae349f5Scvs2svn void 2901ae349f5Scvs2svn CcpUp() 2911ae349f5Scvs2svn { 2927308ec68SBrian Somers /* Lower layers are ready.... go */ 2937308ec68SBrian Somers FsmUp(&CcpInfo.fsm); 2941ae349f5Scvs2svn LogPrintf(LogCCP, "CCP Up event!!\n"); 2951ae349f5Scvs2svn } 2961ae349f5Scvs2svn 2971ae349f5Scvs2svn void 2981ae349f5Scvs2svn CcpOpen() 2991ae349f5Scvs2svn { 3007308ec68SBrian Somers /* Start CCP please */ 3011ae349f5Scvs2svn int f; 3021ae349f5Scvs2svn 3031ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 3041ae349f5Scvs2svn if (Enabled(algorithm[f]->Conf)) { 3057308ec68SBrian Somers CcpInfo.fsm.open_mode = 0; 3067308ec68SBrian Somers FsmOpen(&CcpInfo.fsm); 3071ae349f5Scvs2svn break; 3081ae349f5Scvs2svn } 3091ae349f5Scvs2svn 3101ae349f5Scvs2svn if (f == NALGORITHMS) 3111ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 3121ae349f5Scvs2svn if (Acceptable(algorithm[f]->Conf)) { 3137308ec68SBrian Somers CcpInfo.fsm.open_mode = OPEN_PASSIVE; 3147308ec68SBrian Somers FsmOpen(&CcpInfo.fsm); 3151ae349f5Scvs2svn break; 3161ae349f5Scvs2svn } 3171ae349f5Scvs2svn } 3181ae349f5Scvs2svn 3191ae349f5Scvs2svn static void 32083d1af55SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type) 3211ae349f5Scvs2svn { 3227308ec68SBrian Somers /* Deal with incoming data */ 323aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3241ae349f5Scvs2svn int type, length; 3251ae349f5Scvs2svn int f; 3261ae349f5Scvs2svn 3271ae349f5Scvs2svn ackp = AckBuff; 3281ae349f5Scvs2svn nakp = NakBuff; 3291ae349f5Scvs2svn rejp = RejBuff; 3301ae349f5Scvs2svn 3311ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 3321ae349f5Scvs2svn type = *cp; 3331ae349f5Scvs2svn length = cp[1]; 3341ae349f5Scvs2svn if (type < NCFTYPES) 3351ae349f5Scvs2svn LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length); 3361ae349f5Scvs2svn else 3371ae349f5Scvs2svn LogPrintf(LogCCP, " ???[%d]\n", length); 3381ae349f5Scvs2svn 3391ae349f5Scvs2svn for (f = NALGORITHMS-1; f > -1; f--) 3401ae349f5Scvs2svn if (algorithm[f]->id == type) 3411ae349f5Scvs2svn break; 3421ae349f5Scvs2svn 3431ae349f5Scvs2svn if (f == -1) { 3441ae349f5Scvs2svn /* Don't understand that :-( */ 3451ae349f5Scvs2svn if (mode_type == MODE_REQ) { 34683d1af55SBrian Somers ccp->my_reject |= (1 << type); 3471ae349f5Scvs2svn memcpy(rejp, cp, length); 3481ae349f5Scvs2svn rejp += length; 3491ae349f5Scvs2svn } 3501ae349f5Scvs2svn } else { 3511ae349f5Scvs2svn struct lcp_opt o; 3521ae349f5Scvs2svn 3531ae349f5Scvs2svn switch (mode_type) { 3541ae349f5Scvs2svn case MODE_REQ: 35583d1af55SBrian Somers if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) { 3561ae349f5Scvs2svn memcpy(&o, cp, length); 3571ae349f5Scvs2svn switch ((*algorithm[f]->i.Set)(&o)) { 3581ae349f5Scvs2svn case MODE_REJ: 3591ae349f5Scvs2svn memcpy(rejp, &o, o.len); 3601ae349f5Scvs2svn rejp += o.len; 3611ae349f5Scvs2svn break; 3621ae349f5Scvs2svn case MODE_NAK: 3631ae349f5Scvs2svn memcpy(nakp, &o, o.len); 3641ae349f5Scvs2svn nakp += o.len; 3651ae349f5Scvs2svn break; 3661ae349f5Scvs2svn case MODE_ACK: 3671ae349f5Scvs2svn memcpy(ackp, cp, length); 3681ae349f5Scvs2svn ackp += length; 36983d1af55SBrian Somers ccp->his_proto = type; 37083d1af55SBrian Somers ccp->in_algorithm = f; /* This one'll do ! */ 3711ae349f5Scvs2svn break; 3721ae349f5Scvs2svn } 3731ae349f5Scvs2svn } else { 3741ae349f5Scvs2svn memcpy(rejp, cp, length); 3751ae349f5Scvs2svn rejp += length; 3761ae349f5Scvs2svn } 3771ae349f5Scvs2svn break; 3781ae349f5Scvs2svn case MODE_NAK: 3791ae349f5Scvs2svn memcpy(&o, cp, length); 3801ae349f5Scvs2svn if ((*algorithm[f]->o.Set)(&o) == MODE_ACK) 38183d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 3821ae349f5Scvs2svn else { 38383d1af55SBrian Somers ccp->his_reject |= (1 << type); 38483d1af55SBrian Somers ccp->my_proto = -1; 3851ae349f5Scvs2svn } 3861ae349f5Scvs2svn break; 3871ae349f5Scvs2svn case MODE_REJ: 38883d1af55SBrian Somers ccp->his_reject |= (1 << type); 38983d1af55SBrian Somers ccp->my_proto = -1; 3901ae349f5Scvs2svn break; 3911ae349f5Scvs2svn } 3921ae349f5Scvs2svn } 3931ae349f5Scvs2svn 3941ae349f5Scvs2svn plen -= length; 3951ae349f5Scvs2svn cp += length; 3961ae349f5Scvs2svn } 3971ae349f5Scvs2svn 3981ae349f5Scvs2svn if (rejp != RejBuff) { 3991ae349f5Scvs2svn ackp = AckBuff; /* let's not send both ! */ 40083d1af55SBrian Somers if (!ccp->in_init) { 40183d1af55SBrian Somers ccp->his_proto = -1; 40283d1af55SBrian Somers ccp->in_algorithm = -1; 403247ab36dSBrian Somers } 4041ae349f5Scvs2svn } 4051ae349f5Scvs2svn } 4061ae349f5Scvs2svn 4071ae349f5Scvs2svn void 408455aabc3SBrian Somers CcpInput(struct bundle *bundle, struct mbuf *bp) 4091ae349f5Scvs2svn { 4107308ec68SBrian Somers /* Got PROTO_CCP from link */ 411455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 4127308ec68SBrian Somers FsmInput(&CcpInfo.fsm, bp); 413455aabc3SBrian Somers else if (bundle_Phase(bundle) < PHASE_NETWORK) { 414455aabc3SBrian Somers LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n", 415455aabc3SBrian Somers bundle_PhaseName(bundle)); 4161ae349f5Scvs2svn pfree(bp); 4171ae349f5Scvs2svn } 4181ae349f5Scvs2svn } 4191ae349f5Scvs2svn 4201ae349f5Scvs2svn void 4211ae349f5Scvs2svn CcpResetInput(u_char id) 4221ae349f5Scvs2svn { 4237308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 4241ae349f5Scvs2svn if (CcpInfo.reset_sent != -1) { 4251ae349f5Scvs2svn if (id != CcpInfo.reset_sent) { 4261ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n", 4271ae349f5Scvs2svn id, CcpInfo.reset_sent); 4281ae349f5Scvs2svn return; 4291ae349f5Scvs2svn } 4301ae349f5Scvs2svn /* Whaddaya know - a correct reset ack */ 4311ae349f5Scvs2svn } else if (id == CcpInfo.last_reset) 4321ae349f5Scvs2svn LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n"); 4331ae349f5Scvs2svn else { 4341ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id); 4351ae349f5Scvs2svn return; 4361ae349f5Scvs2svn } 4371ae349f5Scvs2svn 4381ae349f5Scvs2svn CcpInfo.last_reset = CcpInfo.reset_sent; 4391ae349f5Scvs2svn CcpInfo.reset_sent = -1; 440247ab36dSBrian Somers if (CcpInfo.in_init) 441247ab36dSBrian Somers (*algorithm[CcpInfo.in_algorithm]->i.Reset)(); 4421ae349f5Scvs2svn } 4431ae349f5Scvs2svn 4441ae349f5Scvs2svn int 4458c07a7b2SBrian Somers CcpOutput(struct link *l, int pri, u_short proto, struct mbuf *m) 4461ae349f5Scvs2svn { 4477308ec68SBrian Somers /* Compress outgoing data */ 448247ab36dSBrian Somers if (CcpInfo.out_init) 4498c07a7b2SBrian Somers return (*algorithm[CcpInfo.out_algorithm]->o.Write)(l, pri, proto, m); 4501ae349f5Scvs2svn return 0; 4511ae349f5Scvs2svn } 4521ae349f5Scvs2svn 4531ae349f5Scvs2svn struct mbuf * 4541ae349f5Scvs2svn CompdInput(u_short *proto, struct mbuf *m) 4551ae349f5Scvs2svn { 4567308ec68SBrian Somers /* Decompress incoming data */ 4571ae349f5Scvs2svn if (CcpInfo.reset_sent != -1) { 4581ae349f5Scvs2svn /* Send another REQ and put the packet in the bit bucket */ 4591ae349f5Scvs2svn LogPrintf(LogCCP, "ReSendResetReq(%d)\n", CcpInfo.reset_sent); 4607308ec68SBrian Somers FsmOutput(&CcpInfo.fsm, CODE_RESETREQ, CcpInfo.reset_sent, NULL, 0); 4611ae349f5Scvs2svn pfree(m); 462247ab36dSBrian Somers } else if (CcpInfo.in_init) 463247ab36dSBrian Somers return (*algorithm[CcpInfo.in_algorithm]->i.Read)(proto, m); 4641ae349f5Scvs2svn return NULL; 4651ae349f5Scvs2svn } 4661ae349f5Scvs2svn 4671ae349f5Scvs2svn void 4681ae349f5Scvs2svn CcpDictSetup(u_short proto, struct mbuf *m) 4691ae349f5Scvs2svn { 4707308ec68SBrian Somers /* Add incoming data to the dictionary */ 471247ab36dSBrian Somers if (CcpInfo.in_init) 472247ab36dSBrian Somers (*algorithm[CcpInfo.in_algorithm]->i.DictSetup)(proto, m); 4731ae349f5Scvs2svn } 474