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