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 * 20b6217683SBrian Somers * $Id: ccp.c,v 1.30.2.30 1998/04/03 19:23:53 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o Support other compression protocols 241ae349f5Scvs2svn */ 251ae349f5Scvs2svn #include <sys/param.h> 261ae349f5Scvs2svn #include <netinet/in.h> 27eaa4df37SBrian Somers #include <netinet/in_systm.h> 28eaa4df37SBrian Somers #include <netinet/ip.h> 291ae349f5Scvs2svn 301ae349f5Scvs2svn #include <stdio.h> 3103036ec7SBrian Somers #include <stdlib.h> 321ae349f5Scvs2svn #include <string.h> 3385b542cfSBrian Somers #include <termios.h> 341ae349f5Scvs2svn 351ae349f5Scvs2svn #include "command.h" 361ae349f5Scvs2svn #include "mbuf.h" 371ae349f5Scvs2svn #include "log.h" 381ae349f5Scvs2svn #include "defs.h" 391ae349f5Scvs2svn #include "timer.h" 401ae349f5Scvs2svn #include "fsm.h" 411ae349f5Scvs2svn #include "lcpproto.h" 421ae349f5Scvs2svn #include "lcp.h" 431ae349f5Scvs2svn #include "ccp.h" 441ae349f5Scvs2svn #include "loadalias.h" 451ae349f5Scvs2svn #include "vars.h" 461ae349f5Scvs2svn #include "pred.h" 471ae349f5Scvs2svn #include "deflate.h" 485828db6dSBrian Somers #include "throughput.h" 495828db6dSBrian Somers #include "iplist.h" 50eaa4df37SBrian Somers #include "slcompress.h" 515828db6dSBrian Somers #include "ipcp.h" 525ca5389aSBrian Somers #include "filter.h" 5385b542cfSBrian Somers #include "descriptor.h" 5485b542cfSBrian Somers #include "prompt.h" 55879ed6faSBrian Somers #include "lqr.h" 56503a7782SBrian Somers #include "hdlc.h" 57503a7782SBrian Somers #include "link.h" 583b0f8d2eSBrian Somers #include "mp.h" 593b0f8d2eSBrian Somers #include "bundle.h" 60503a7782SBrian Somers #include "chat.h" 61e2ebb036SBrian Somers #include "auth.h" 62e2ebb036SBrian Somers #include "chap.h" 633b0f8d2eSBrian Somers #include "async.h" 643b0f8d2eSBrian Somers #include "physical.h" 65503a7782SBrian Somers #include "datalink.h" 661ae349f5Scvs2svn 671ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *); 682267893fSBrian Somers static void CcpSentTerminateReq(struct fsm *); 692267893fSBrian Somers static void CcpSendTerminateAck(struct fsm *, u_char); 7030c2f2ffSBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int, 7130c2f2ffSBrian Somers struct fsm_decode *); 721ae349f5Scvs2svn static void CcpLayerStart(struct fsm *); 731ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *); 741ae349f5Scvs2svn static void CcpLayerUp(struct fsm *); 751ae349f5Scvs2svn static void CcpLayerDown(struct fsm *); 761ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *); 77503a7782SBrian Somers static void CcpRecvResetReq(struct fsm *); 78503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char); 791ae349f5Scvs2svn 8083d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 8183d1af55SBrian Somers CcpLayerUp, 8283d1af55SBrian Somers CcpLayerDown, 8383d1af55SBrian Somers CcpLayerStart, 846d666775SBrian Somers CcpLayerFinish, 8583d1af55SBrian Somers CcpInitRestartCounter, 8683d1af55SBrian Somers CcpSendConfigReq, 872267893fSBrian Somers CcpSentTerminateReq, 8883d1af55SBrian Somers CcpSendTerminateAck, 89503a7782SBrian Somers CcpDecodeConfig, 90503a7782SBrian Somers CcpRecvResetReq, 91503a7782SBrian Somers CcpRecvResetAck 9283d1af55SBrian Somers }; 9383d1af55SBrian Somers 941ae349f5Scvs2svn static char const *cftypes[] = { 951ae349f5Scvs2svn /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 961ae349f5Scvs2svn "OUI", /* 0: OUI */ 971ae349f5Scvs2svn "PRED1", /* 1: Predictor type 1 */ 981ae349f5Scvs2svn "PRED2", /* 2: Predictor type 2 */ 991ae349f5Scvs2svn "PUDDLE", /* 3: Puddle Jumber */ 1001ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 1011ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 1021ae349f5Scvs2svn "HWPPC", /* 16: Hewlett-Packard PPC */ 1031ae349f5Scvs2svn "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 1048f2e5827SBrian Somers "MPPC", /* 18: Microsoft PPC (rfc2118) */ 1051ae349f5Scvs2svn "GAND", /* 19: Gandalf FZA (rfc1993) */ 1061ae349f5Scvs2svn "V42BIS", /* 20: ARG->DATA.42bis compression */ 1071ae349f5Scvs2svn "BSD", /* 21: BSD LZW Compress */ 1081ae349f5Scvs2svn "???", 1091ae349f5Scvs2svn "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 1101ae349f5Scvs2svn "MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */ 1111ae349f5Scvs2svn /* 24: Deflate (according to pppd-2.3.1) */ 1121ae349f5Scvs2svn "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 1131ae349f5Scvs2svn "DEFLATE", /* 26: Deflate (rfc1979) */ 1141ae349f5Scvs2svn }; 1151ae349f5Scvs2svn 1161ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1171ae349f5Scvs2svn 1181ae349f5Scvs2svn static const char * 1191ae349f5Scvs2svn protoname(int proto) 1201ae349f5Scvs2svn { 1211ae349f5Scvs2svn if (proto < 0 || proto > NCFTYPES) 1221ae349f5Scvs2svn return "none"; 1231ae349f5Scvs2svn return cftypes[proto]; 1241ae349f5Scvs2svn } 1251ae349f5Scvs2svn 1261ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */ 1271ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = { 1281ae349f5Scvs2svn &DeflateAlgorithm, 1291ae349f5Scvs2svn &Pred1Algorithm, 1301ae349f5Scvs2svn &PppdDeflateAlgorithm 1311ae349f5Scvs2svn }; 1321ae349f5Scvs2svn 1331ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1341ae349f5Scvs2svn 1351ae349f5Scvs2svn int 136503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg) 1371ae349f5Scvs2svn { 138cd9647a1SBrian Somers struct link *l = ChooseLink(arg); 139cd9647a1SBrian Somers struct ccp *ccp = &l->ccp; 140503a7782SBrian Somers 141b6217683SBrian Somers prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 1421e991daaSBrian Somers State2Nam(ccp->fsm.state)); 143b6217683SBrian Somers prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 144503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 145b6217683SBrian Somers prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 146503a7782SBrian Somers ccp->uncompout, ccp->compout, 147503a7782SBrian Somers ccp->compin, ccp->uncompin); 148cd9647a1SBrian Somers 149b6217683SBrian Somers prompt_Printf(arg->prompt, "\n Defaults: "); 150b6217683SBrian Somers prompt_Printf(arg->prompt, "deflate windows: "); 151b6217683SBrian Somers prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 152b6217683SBrian Somers prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 153b6217683SBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us\n", ccp->cfg.fsmretry); 1541ae349f5Scvs2svn return 0; 1551ae349f5Scvs2svn } 1561ae349f5Scvs2svn 1571ae349f5Scvs2svn void 1586d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 1596d666775SBrian Somers const struct fsm_parent *parent) 1601ae349f5Scvs2svn { 1617308ec68SBrian Somers /* Initialise ourselves */ 1623b0f8d2eSBrian Somers static const char *timer_names[] = 1633b0f8d2eSBrian Somers {"CCP restart", "CCP openmode", "CCP stopped"}; 1643b0f8d2eSBrian Somers 1653b0f8d2eSBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, 10, LogCCP, 1663b0f8d2eSBrian Somers bundle, l, parent, &ccp_Callbacks, timer_names); 167cd9647a1SBrian Somers 16803036ec7SBrian Somers ccp->cfg.deflate.in.winsize = 0; 16903036ec7SBrian Somers ccp->cfg.deflate.out.winsize = 15; 170cd9647a1SBrian Somers ccp->cfg.fsmretry = DEF_FSMRETRY; 171cd9647a1SBrian Somers 172503a7782SBrian Somers ccp_Setup(ccp); 173503a7782SBrian Somers } 174503a7782SBrian Somers 175503a7782SBrian Somers void 176503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 177503a7782SBrian Somers { 178503a7782SBrian Somers /* Set ourselves up for a startup */ 179503a7782SBrian Somers ccp->fsm.open_mode = 0; 1805454ccd9SBrian Somers ccp->fsm.maxconfig = 10; 181503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 182503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 18303036ec7SBrian Somers ccp->in.algorithm = ccp->out.algorithm = -1; 18403036ec7SBrian Somers ccp->in.state = ccp->out.state = NULL; 18503036ec7SBrian Somers ccp->in.opt.id = -1; 18603036ec7SBrian Somers ccp->out.opt = NULL; 187503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 188503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 189503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 1901ae349f5Scvs2svn } 1911ae349f5Scvs2svn 1921ae349f5Scvs2svn static void 1931ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp) 1941ae349f5Scvs2svn { 1957308ec68SBrian Somers /* Set fsm timer load */ 196cd9647a1SBrian Somers struct ccp *ccp = fsm2ccp(fp); 197cd9647a1SBrian Somers 198cd9647a1SBrian Somers fp->FsmTimer.load = ccp->cfg.fsmretry * SECTICKS; 1991ae349f5Scvs2svn fp->restart = 5; 2001ae349f5Scvs2svn } 2011ae349f5Scvs2svn 2021ae349f5Scvs2svn static void 2031ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp) 2041ae349f5Scvs2svn { 2057308ec68SBrian Somers /* Send config REQ please */ 206aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 20703036ec7SBrian Somers struct ccp_opt **o; 20830c2f2ffSBrian Somers u_char *cp, buff[100]; 20903036ec7SBrian Somers int f, alloc; 2101ae349f5Scvs2svn 21130c2f2ffSBrian Somers cp = buff; 21203036ec7SBrian Somers o = &ccp->out.opt; 21303036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 21483d1af55SBrian Somers ccp->my_proto = -1; 21503036ec7SBrian Somers ccp->out.algorithm = -1; 2161ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 21783d1af55SBrian Somers if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) { 21803036ec7SBrian Somers if (alloc) { 21903036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 22003036ec7SBrian Somers (*o)->val.id = algorithm[f]->id; 22103036ec7SBrian Somers (*o)->val.len = 2; 22203036ec7SBrian Somers (*o)->next = NULL; 22303036ec7SBrian Somers (*o)->algorithm = f; 22403036ec7SBrian Somers (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 22503036ec7SBrian Somers } else { 22603036ec7SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 22703036ec7SBrian Somers if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 22803036ec7SBrian Somers break; 22903036ec7SBrian Somers if (*o == NULL) { 23003036ec7SBrian Somers LogPrintf(LogERROR, "CCP REQ buffer lost !\n"); 23103036ec7SBrian Somers break; 23203036ec7SBrian Somers } 23303036ec7SBrian Somers } 2341ae349f5Scvs2svn 23503036ec7SBrian Somers if (cp + (*o)->val.len > buff + sizeof buff) { 23630c2f2ffSBrian Somers LogPrintf(LogERROR, "CCP REQ buffer overrun !\n"); 23730c2f2ffSBrian Somers break; 23830c2f2ffSBrian Somers } 2392267893fSBrian Somers memcpy(cp, &(*o)->val, (*o)->val.len); 2402267893fSBrian Somers cp += (*o)->val.len; 24103036ec7SBrian Somers 24203036ec7SBrian Somers ccp->my_proto = (*o)->val.id; 24303036ec7SBrian Somers ccp->out.algorithm = f; 24403036ec7SBrian Somers 24503036ec7SBrian Somers if (alloc) 24603036ec7SBrian Somers o = &(*o)->next; 2471ae349f5Scvs2svn } 2482267893fSBrian Somers 2492267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff); 2501ae349f5Scvs2svn } 2511ae349f5Scvs2svn 2521ae349f5Scvs2svn void 2531ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp) 2541ae349f5Scvs2svn { 2557308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 256aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2572267893fSBrian Somers 25883d1af55SBrian Somers ccp->reset_sent = fp->reqid; 25983d1af55SBrian Somers ccp->last_reset = -1; 2601ae349f5Scvs2svn FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 2611ae349f5Scvs2svn } 2621ae349f5Scvs2svn 2631ae349f5Scvs2svn static void 2642267893fSBrian Somers CcpSentTerminateReq(struct fsm *fp) 2651ae349f5Scvs2svn { 2667308ec68SBrian Somers /* Term REQ just sent by FSM */ 2671ae349f5Scvs2svn } 2681ae349f5Scvs2svn 2691ae349f5Scvs2svn static void 2702267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 2711ae349f5Scvs2svn { 2727308ec68SBrian Somers /* Send Term ACK please */ 2732267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 2741ae349f5Scvs2svn } 2751ae349f5Scvs2svn 276503a7782SBrian Somers static void 2771ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp) 2781ae349f5Scvs2svn { 2797308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 280aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 28103036ec7SBrian Somers if (ccp->out.state != NULL) 28203036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 2831ae349f5Scvs2svn } 2841ae349f5Scvs2svn 2851ae349f5Scvs2svn static void 2861ae349f5Scvs2svn CcpLayerStart(struct fsm *fp) 2871ae349f5Scvs2svn { 2887308ec68SBrian Somers /* We're about to start up ! */ 2891ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerStart.\n"); 2901ae349f5Scvs2svn } 2911ae349f5Scvs2svn 2921ae349f5Scvs2svn static void 2931ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp) 2941ae349f5Scvs2svn { 2957308ec68SBrian Somers /* We're now down */ 296aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2971ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerFinish.\n"); 29803036ec7SBrian Somers if (ccp->in.state != NULL) { 29903036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 30003036ec7SBrian Somers ccp->in.state = NULL; 3017308ec68SBrian Somers } 30203036ec7SBrian Somers if (ccp->out.state != NULL) { 30303036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 30403036ec7SBrian Somers ccp->out.state = NULL; 3057308ec68SBrian Somers } 3061ae349f5Scvs2svn } 3071ae349f5Scvs2svn 3081ae349f5Scvs2svn static void 3091ae349f5Scvs2svn CcpLayerDown(struct fsm *fp) 3101ae349f5Scvs2svn { 3117308ec68SBrian Somers /* About to come down */ 3121ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerDown.\n"); 3131ae349f5Scvs2svn } 3141ae349f5Scvs2svn 3151ae349f5Scvs2svn /* 3161ae349f5Scvs2svn * Called when CCP has reached the OPEN state 3171ae349f5Scvs2svn */ 3181ae349f5Scvs2svn static void 3191ae349f5Scvs2svn CcpLayerUp(struct fsm *fp) 3201ae349f5Scvs2svn { 3217308ec68SBrian Somers /* We're now up */ 322aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 323455aabc3SBrian Somers LogPrintf(LogCCP, "CcpLayerUp.\n"); 32403036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 32503036ec7SBrian Somers ccp->in.algorithm < NALGORITHMS) { 32603036ec7SBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 32703036ec7SBrian Somers if (ccp->in.state == NULL) { 328247ab36dSBrian Somers LogPrintf(LogERROR, "%s (in) initialisation failure\n", 32983d1af55SBrian Somers protoname(ccp->his_proto)); 33083d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 331247ab36dSBrian Somers FsmClose(fp); 332247ab36dSBrian Somers } 33303036ec7SBrian Somers } 33403036ec7SBrian Somers 33503036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 33603036ec7SBrian Somers ccp->out.algorithm < NALGORITHMS) { 33703036ec7SBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 33803036ec7SBrian Somers (&ccp->out.opt->val); 33903036ec7SBrian Somers if (ccp->out.state == NULL) { 340247ab36dSBrian Somers LogPrintf(LogERROR, "%s (out) initialisation failure\n", 34183d1af55SBrian Somers protoname(ccp->my_proto)); 34283d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 343247ab36dSBrian Somers FsmClose(fp); 344247ab36dSBrian Somers } 34503036ec7SBrian Somers } 34603036ec7SBrian Somers 3471ae349f5Scvs2svn LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 34883d1af55SBrian Somers protoname(ccp->my_proto), ccp->my_proto, 34983d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 3501ae349f5Scvs2svn } 3511ae349f5Scvs2svn 3521ae349f5Scvs2svn static void 35330c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 35430c2f2ffSBrian Somers struct fsm_decode *dec) 3551ae349f5Scvs2svn { 3567308ec68SBrian Somers /* Deal with incoming data */ 357aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3581ae349f5Scvs2svn int type, length; 3591ae349f5Scvs2svn int f; 36003036ec7SBrian Somers const char *end; 3611ae349f5Scvs2svn 3621ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 3631ae349f5Scvs2svn type = *cp; 3641ae349f5Scvs2svn length = cp[1]; 36503036ec7SBrian Somers 36603036ec7SBrian Somers if (length > sizeof(struct lcp_opt)) { 36703036ec7SBrian Somers length = sizeof(struct lcp_opt); 36803036ec7SBrian Somers LogPrintf(LogCCP, "Warning: Truncating length to %d\n", length); 36903036ec7SBrian Somers } 3701ae349f5Scvs2svn 3711ae349f5Scvs2svn for (f = NALGORITHMS-1; f > -1; f--) 3721ae349f5Scvs2svn if (algorithm[f]->id == type) 3731ae349f5Scvs2svn break; 3741ae349f5Scvs2svn 37503036ec7SBrian Somers end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 37603036ec7SBrian Somers if (end == NULL) 37703036ec7SBrian Somers end = ""; 37803036ec7SBrian Somers 37903036ec7SBrian Somers if (type < NCFTYPES) 38003036ec7SBrian Somers LogPrintf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end); 38103036ec7SBrian Somers else 38203036ec7SBrian Somers LogPrintf(LogCCP, " ???[%d] %s\n", length, end); 38303036ec7SBrian Somers 3841ae349f5Scvs2svn if (f == -1) { 3851ae349f5Scvs2svn /* Don't understand that :-( */ 3861ae349f5Scvs2svn if (mode_type == MODE_REQ) { 38783d1af55SBrian Somers ccp->my_reject |= (1 << type); 38830c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 38930c2f2ffSBrian Somers dec->rejend += length; 3901ae349f5Scvs2svn } 3911ae349f5Scvs2svn } else { 39203036ec7SBrian Somers struct ccp_opt *o; 3931ae349f5Scvs2svn 3941ae349f5Scvs2svn switch (mode_type) { 3951ae349f5Scvs2svn case MODE_REQ: 39603036ec7SBrian Somers if (Acceptable(algorithm[f]->Conf) && ccp->in.algorithm == -1) { 39703036ec7SBrian Somers memcpy(&ccp->in.opt, cp, length); 39803036ec7SBrian Somers switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 3991ae349f5Scvs2svn case MODE_REJ: 40003036ec7SBrian Somers memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 40103036ec7SBrian Somers dec->rejend += ccp->in.opt.len; 4021ae349f5Scvs2svn break; 4031ae349f5Scvs2svn case MODE_NAK: 40403036ec7SBrian Somers memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 40503036ec7SBrian Somers dec->nakend += ccp->in.opt.len; 4061ae349f5Scvs2svn break; 4071ae349f5Scvs2svn case MODE_ACK: 40830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 40930c2f2ffSBrian Somers dec->ackend += length; 41083d1af55SBrian Somers ccp->his_proto = type; 41103036ec7SBrian Somers ccp->in.algorithm = f; /* This one'll do :-) */ 4121ae349f5Scvs2svn break; 4131ae349f5Scvs2svn } 4141ae349f5Scvs2svn } else { 41530c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 41630c2f2ffSBrian Somers dec->rejend += length; 4171ae349f5Scvs2svn } 4181ae349f5Scvs2svn break; 4191ae349f5Scvs2svn case MODE_NAK: 42003036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 42103036ec7SBrian Somers if (o->val.id == cp[0]) 42203036ec7SBrian Somers break; 42303036ec7SBrian Somers if (o == NULL) 42403036ec7SBrian Somers LogPrintf(LogCCP, "Warning: Ignoring peer NAK of unsent option\n"); 42503036ec7SBrian Somers else { 42603036ec7SBrian Somers memcpy(&o->val, cp, length); 42703036ec7SBrian Somers if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 42883d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 4291ae349f5Scvs2svn else { 43083d1af55SBrian Somers ccp->his_reject |= (1 << type); 43183d1af55SBrian Somers ccp->my_proto = -1; 4321ae349f5Scvs2svn } 43303036ec7SBrian Somers } 4341ae349f5Scvs2svn break; 4351ae349f5Scvs2svn case MODE_REJ: 43683d1af55SBrian Somers ccp->his_reject |= (1 << type); 43783d1af55SBrian Somers ccp->my_proto = -1; 4381ae349f5Scvs2svn break; 4391ae349f5Scvs2svn } 4401ae349f5Scvs2svn } 4411ae349f5Scvs2svn 44203036ec7SBrian Somers plen -= cp[1]; 44303036ec7SBrian Somers cp += cp[1]; 4441ae349f5Scvs2svn } 4451ae349f5Scvs2svn 44630c2f2ffSBrian Somers if (mode_type != MODE_NOP && dec->rejend != dec->rej) { 44703036ec7SBrian Somers /* rejects are preferred */ 44803036ec7SBrian Somers dec->ackend = dec->ack; 44903036ec7SBrian Somers dec->nakend = dec->nak; 45003036ec7SBrian Somers if (ccp->in.state == NULL) { 45183d1af55SBrian Somers ccp->his_proto = -1; 45203036ec7SBrian Somers ccp->in.algorithm = -1; 45303036ec7SBrian Somers } 45403036ec7SBrian Somers } else if (mode_type != MODE_NOP && dec->nakend != dec->nak) { 45503036ec7SBrian Somers /* then NAKs */ 45603036ec7SBrian Somers dec->ackend = dec->ack; 45703036ec7SBrian Somers if (ccp->in.state == NULL) { 45803036ec7SBrian Somers ccp->his_proto = -1; 45903036ec7SBrian Somers ccp->in.algorithm = -1; 460247ab36dSBrian Somers } 4611ae349f5Scvs2svn } 4621ae349f5Scvs2svn } 4631ae349f5Scvs2svn 4641ae349f5Scvs2svn void 465f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp) 4661ae349f5Scvs2svn { 4677308ec68SBrian Somers /* Got PROTO_CCP from link */ 468455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 469f4768038SBrian Somers FsmInput(&ccp->fsm, bp); 470455aabc3SBrian Somers else if (bundle_Phase(bundle) < PHASE_NETWORK) { 471455aabc3SBrian Somers LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n", 472455aabc3SBrian Somers bundle_PhaseName(bundle)); 4731ae349f5Scvs2svn pfree(bp); 4741ae349f5Scvs2svn } 4751ae349f5Scvs2svn } 4761ae349f5Scvs2svn 477503a7782SBrian Somers static void 478503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 4791ae349f5Scvs2svn { 4807308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 481f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 482f4768038SBrian Somers 483f4768038SBrian Somers if (ccp->reset_sent != -1) { 484f4768038SBrian Somers if (id != ccp->reset_sent) { 4851ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n", 486f4768038SBrian Somers id, ccp->reset_sent); 4871ae349f5Scvs2svn return; 4881ae349f5Scvs2svn } 4891ae349f5Scvs2svn /* Whaddaya know - a correct reset ack */ 490f4768038SBrian Somers } else if (id == ccp->last_reset) 4911ae349f5Scvs2svn LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n"); 4921ae349f5Scvs2svn else { 4931ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id); 4941ae349f5Scvs2svn return; 4951ae349f5Scvs2svn } 4961ae349f5Scvs2svn 497f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 498f4768038SBrian Somers ccp->reset_sent = -1; 49903036ec7SBrian Somers if (ccp->in.state != NULL) 50003036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 5011ae349f5Scvs2svn } 5021ae349f5Scvs2svn 5031ae349f5Scvs2svn int 5043b0f8d2eSBrian Somers ccp_Compress(struct ccp *ccp, struct link *l, int pri, u_short proto, 505503a7782SBrian Somers struct mbuf *m) 5061ae349f5Scvs2svn { 507503a7782SBrian Somers /* Compress outgoing Network Layer data */ 50803036ec7SBrian Somers if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && 50903036ec7SBrian Somers ccp->out.state != NULL) 51003036ec7SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Write) 51103036ec7SBrian Somers (ccp->out.state, ccp, l, pri, proto, m); 5121ae349f5Scvs2svn return 0; 5131ae349f5Scvs2svn } 5141ae349f5Scvs2svn 5151ae349f5Scvs2svn struct mbuf * 516503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp) 5171ae349f5Scvs2svn { 518ee6c193fSBrian Somers /* 519ee6c193fSBrian Somers * If proto isn't PROTO_COMPD, we still want to pass it to the 520ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 521ee6c193fSBrian Somers */ 522503a7782SBrian Somers if (ccp->fsm.state == ST_OPENED) 523ee6c193fSBrian Somers if (*proto == PROTO_COMPD) { 5247308ec68SBrian Somers /* Decompress incoming data */ 5252267893fSBrian Somers if (ccp->reset_sent != -1) 5261ae349f5Scvs2svn /* Send another REQ and put the packet in the bit bucket */ 527503a7782SBrian Somers FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0); 5282267893fSBrian Somers else if (ccp->in.state != NULL) 52903036ec7SBrian Somers return (*algorithm[ccp->in.algorithm]->i.Read) 53003036ec7SBrian Somers (ccp->in.state, ccp, proto, bp); 531ee6c193fSBrian Somers pfree(bp); 532ee6c193fSBrian Somers bp = NULL; 53303036ec7SBrian Somers } else if ((*proto & 0xfff1) == 0x21 && ccp->in.state != NULL) 534ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 53503036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.DictSetup) 53603036ec7SBrian Somers (ccp->in.state, ccp, *proto, bp); 5371ae349f5Scvs2svn 538ee6c193fSBrian Somers return bp; 5391ae349f5Scvs2svn } 540