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 * 203b0f8d2eSBrian Somers * $Id: ccp.c,v 1.30.2.28 1998/03/24 18:46:37 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 { 1383b0f8d2eSBrian Somers struct ccp *ccp = &ChooseLink(arg)->ccp; 139503a7782SBrian Somers 140503a7782SBrian Somers prompt_Printf(&prompt, "%s [%s]\n", ccp->fsm.name, 1411e991daaSBrian Somers State2Nam(ccp->fsm.state)); 14285b542cfSBrian Somers prompt_Printf(&prompt, "My protocol = %s, His protocol = %s\n", 143503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 14485b542cfSBrian Somers prompt_Printf(&prompt, "Output: %ld --> %ld, Input: %ld --> %ld\n", 145503a7782SBrian Somers ccp->uncompout, ccp->compout, 146503a7782SBrian Somers ccp->compin, ccp->uncompin); 1471ae349f5Scvs2svn return 0; 1481ae349f5Scvs2svn } 1491ae349f5Scvs2svn 1501ae349f5Scvs2svn void 1516d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 1526d666775SBrian Somers const struct fsm_parent *parent) 1531ae349f5Scvs2svn { 1547308ec68SBrian Somers /* Initialise ourselves */ 1553b0f8d2eSBrian Somers static const char *timer_names[] = 1563b0f8d2eSBrian Somers {"CCP restart", "CCP openmode", "CCP stopped"}; 1573b0f8d2eSBrian Somers 1583b0f8d2eSBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, 10, LogCCP, 1593b0f8d2eSBrian Somers bundle, l, parent, &ccp_Callbacks, timer_names); 16003036ec7SBrian Somers ccp->cfg.deflate.in.winsize = 0; 16103036ec7SBrian Somers ccp->cfg.deflate.out.winsize = 15; 162503a7782SBrian Somers ccp_Setup(ccp); 163503a7782SBrian Somers } 164503a7782SBrian Somers 165503a7782SBrian Somers void 166503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 167503a7782SBrian Somers { 168503a7782SBrian Somers /* Set ourselves up for a startup */ 169503a7782SBrian Somers ccp->fsm.open_mode = 0; 1705454ccd9SBrian Somers ccp->fsm.maxconfig = 10; 171503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 172503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 17303036ec7SBrian Somers ccp->in.algorithm = ccp->out.algorithm = -1; 17403036ec7SBrian Somers ccp->in.state = ccp->out.state = NULL; 17503036ec7SBrian Somers ccp->in.opt.id = -1; 17603036ec7SBrian Somers ccp->out.opt = NULL; 177503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 178503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 179503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 1801ae349f5Scvs2svn } 1811ae349f5Scvs2svn 1821ae349f5Scvs2svn static void 1831ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp) 1841ae349f5Scvs2svn { 1857308ec68SBrian Somers /* Set fsm timer load */ 1861ae349f5Scvs2svn fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 1871ae349f5Scvs2svn fp->restart = 5; 1881ae349f5Scvs2svn } 1891ae349f5Scvs2svn 1901ae349f5Scvs2svn static void 1911ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp) 1921ae349f5Scvs2svn { 1937308ec68SBrian Somers /* Send config REQ please */ 194aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 19503036ec7SBrian Somers struct ccp_opt **o; 19630c2f2ffSBrian Somers u_char *cp, buff[100]; 19703036ec7SBrian Somers int f, alloc; 1981ae349f5Scvs2svn 19930c2f2ffSBrian Somers cp = buff; 20003036ec7SBrian Somers o = &ccp->out.opt; 20103036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 20283d1af55SBrian Somers ccp->my_proto = -1; 20303036ec7SBrian Somers ccp->out.algorithm = -1; 2041ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 20583d1af55SBrian Somers if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) { 20603036ec7SBrian Somers if (alloc) { 20703036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 20803036ec7SBrian Somers (*o)->val.id = algorithm[f]->id; 20903036ec7SBrian Somers (*o)->val.len = 2; 21003036ec7SBrian Somers (*o)->next = NULL; 21103036ec7SBrian Somers (*o)->algorithm = f; 21203036ec7SBrian Somers (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 21303036ec7SBrian Somers } else { 21403036ec7SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 21503036ec7SBrian Somers if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 21603036ec7SBrian Somers break; 21703036ec7SBrian Somers if (*o == NULL) { 21803036ec7SBrian Somers LogPrintf(LogERROR, "CCP REQ buffer lost !\n"); 21903036ec7SBrian Somers break; 22003036ec7SBrian Somers } 22103036ec7SBrian Somers } 2221ae349f5Scvs2svn 22303036ec7SBrian Somers if (cp + (*o)->val.len > buff + sizeof buff) { 22430c2f2ffSBrian Somers LogPrintf(LogERROR, "CCP REQ buffer overrun !\n"); 22530c2f2ffSBrian Somers break; 22630c2f2ffSBrian Somers } 2272267893fSBrian Somers memcpy(cp, &(*o)->val, (*o)->val.len); 2282267893fSBrian Somers cp += (*o)->val.len; 22903036ec7SBrian Somers 23003036ec7SBrian Somers ccp->my_proto = (*o)->val.id; 23103036ec7SBrian Somers ccp->out.algorithm = f; 23203036ec7SBrian Somers 23303036ec7SBrian Somers if (alloc) 23403036ec7SBrian Somers o = &(*o)->next; 2351ae349f5Scvs2svn } 2362267893fSBrian Somers 2372267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff); 2381ae349f5Scvs2svn } 2391ae349f5Scvs2svn 2401ae349f5Scvs2svn void 2411ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp) 2421ae349f5Scvs2svn { 2437308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 244aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2452267893fSBrian Somers 24683d1af55SBrian Somers ccp->reset_sent = fp->reqid; 24783d1af55SBrian Somers ccp->last_reset = -1; 2481ae349f5Scvs2svn FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 2491ae349f5Scvs2svn } 2501ae349f5Scvs2svn 2511ae349f5Scvs2svn static void 2522267893fSBrian Somers CcpSentTerminateReq(struct fsm *fp) 2531ae349f5Scvs2svn { 2547308ec68SBrian Somers /* Term REQ just sent by FSM */ 2551ae349f5Scvs2svn } 2561ae349f5Scvs2svn 2571ae349f5Scvs2svn static void 2582267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 2591ae349f5Scvs2svn { 2607308ec68SBrian Somers /* Send Term ACK please */ 2612267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 2621ae349f5Scvs2svn } 2631ae349f5Scvs2svn 264503a7782SBrian Somers static void 2651ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp) 2661ae349f5Scvs2svn { 2677308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 268aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 26903036ec7SBrian Somers if (ccp->out.state != NULL) 27003036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 2711ae349f5Scvs2svn } 2721ae349f5Scvs2svn 2731ae349f5Scvs2svn static void 2741ae349f5Scvs2svn CcpLayerStart(struct fsm *fp) 2751ae349f5Scvs2svn { 2767308ec68SBrian Somers /* We're about to start up ! */ 2771ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerStart.\n"); 2781ae349f5Scvs2svn } 2791ae349f5Scvs2svn 2801ae349f5Scvs2svn static void 2811ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp) 2821ae349f5Scvs2svn { 2837308ec68SBrian Somers /* We're now down */ 284aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2851ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerFinish.\n"); 28603036ec7SBrian Somers if (ccp->in.state != NULL) { 28703036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 28803036ec7SBrian Somers ccp->in.state = NULL; 2897308ec68SBrian Somers } 29003036ec7SBrian Somers if (ccp->out.state != NULL) { 29103036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 29203036ec7SBrian Somers ccp->out.state = NULL; 2937308ec68SBrian Somers } 2941ae349f5Scvs2svn } 2951ae349f5Scvs2svn 2961ae349f5Scvs2svn static void 2971ae349f5Scvs2svn CcpLayerDown(struct fsm *fp) 2981ae349f5Scvs2svn { 2997308ec68SBrian Somers /* About to come down */ 3001ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerDown.\n"); 3011ae349f5Scvs2svn } 3021ae349f5Scvs2svn 3031ae349f5Scvs2svn /* 3041ae349f5Scvs2svn * Called when CCP has reached the OPEN state 3051ae349f5Scvs2svn */ 3061ae349f5Scvs2svn static void 3071ae349f5Scvs2svn CcpLayerUp(struct fsm *fp) 3081ae349f5Scvs2svn { 3097308ec68SBrian Somers /* We're now up */ 310aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 311455aabc3SBrian Somers LogPrintf(LogCCP, "CcpLayerUp.\n"); 31203036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 31303036ec7SBrian Somers ccp->in.algorithm < NALGORITHMS) { 31403036ec7SBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 31503036ec7SBrian Somers if (ccp->in.state == NULL) { 316247ab36dSBrian Somers LogPrintf(LogERROR, "%s (in) initialisation failure\n", 31783d1af55SBrian Somers protoname(ccp->his_proto)); 31883d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 319247ab36dSBrian Somers FsmClose(fp); 320247ab36dSBrian Somers } 32103036ec7SBrian Somers } 32203036ec7SBrian Somers 32303036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 32403036ec7SBrian Somers ccp->out.algorithm < NALGORITHMS) { 32503036ec7SBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 32603036ec7SBrian Somers (&ccp->out.opt->val); 32703036ec7SBrian Somers if (ccp->out.state == NULL) { 328247ab36dSBrian Somers LogPrintf(LogERROR, "%s (out) initialisation failure\n", 32983d1af55SBrian Somers protoname(ccp->my_proto)); 33083d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 331247ab36dSBrian Somers FsmClose(fp); 332247ab36dSBrian Somers } 33303036ec7SBrian Somers } 33403036ec7SBrian Somers 3351ae349f5Scvs2svn LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 33683d1af55SBrian Somers protoname(ccp->my_proto), ccp->my_proto, 33783d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 3381ae349f5Scvs2svn } 3391ae349f5Scvs2svn 3401ae349f5Scvs2svn static void 34130c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 34230c2f2ffSBrian Somers struct fsm_decode *dec) 3431ae349f5Scvs2svn { 3447308ec68SBrian Somers /* Deal with incoming data */ 345aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3461ae349f5Scvs2svn int type, length; 3471ae349f5Scvs2svn int f; 34803036ec7SBrian Somers const char *end; 3491ae349f5Scvs2svn 3501ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 3511ae349f5Scvs2svn type = *cp; 3521ae349f5Scvs2svn length = cp[1]; 35303036ec7SBrian Somers 35403036ec7SBrian Somers if (length > sizeof(struct lcp_opt)) { 35503036ec7SBrian Somers length = sizeof(struct lcp_opt); 35603036ec7SBrian Somers LogPrintf(LogCCP, "Warning: Truncating length to %d\n", length); 35703036ec7SBrian Somers } 3581ae349f5Scvs2svn 3591ae349f5Scvs2svn for (f = NALGORITHMS-1; f > -1; f--) 3601ae349f5Scvs2svn if (algorithm[f]->id == type) 3611ae349f5Scvs2svn break; 3621ae349f5Scvs2svn 36303036ec7SBrian Somers end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 36403036ec7SBrian Somers if (end == NULL) 36503036ec7SBrian Somers end = ""; 36603036ec7SBrian Somers 36703036ec7SBrian Somers if (type < NCFTYPES) 36803036ec7SBrian Somers LogPrintf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end); 36903036ec7SBrian Somers else 37003036ec7SBrian Somers LogPrintf(LogCCP, " ???[%d] %s\n", length, end); 37103036ec7SBrian Somers 3721ae349f5Scvs2svn if (f == -1) { 3731ae349f5Scvs2svn /* Don't understand that :-( */ 3741ae349f5Scvs2svn if (mode_type == MODE_REQ) { 37583d1af55SBrian Somers ccp->my_reject |= (1 << type); 37630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 37730c2f2ffSBrian Somers dec->rejend += length; 3781ae349f5Scvs2svn } 3791ae349f5Scvs2svn } else { 38003036ec7SBrian Somers struct ccp_opt *o; 3811ae349f5Scvs2svn 3821ae349f5Scvs2svn switch (mode_type) { 3831ae349f5Scvs2svn case MODE_REQ: 38403036ec7SBrian Somers if (Acceptable(algorithm[f]->Conf) && ccp->in.algorithm == -1) { 38503036ec7SBrian Somers memcpy(&ccp->in.opt, cp, length); 38603036ec7SBrian Somers switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 3871ae349f5Scvs2svn case MODE_REJ: 38803036ec7SBrian Somers memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 38903036ec7SBrian Somers dec->rejend += ccp->in.opt.len; 3901ae349f5Scvs2svn break; 3911ae349f5Scvs2svn case MODE_NAK: 39203036ec7SBrian Somers memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 39303036ec7SBrian Somers dec->nakend += ccp->in.opt.len; 3941ae349f5Scvs2svn break; 3951ae349f5Scvs2svn case MODE_ACK: 39630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 39730c2f2ffSBrian Somers dec->ackend += length; 39883d1af55SBrian Somers ccp->his_proto = type; 39903036ec7SBrian Somers ccp->in.algorithm = f; /* This one'll do :-) */ 4001ae349f5Scvs2svn break; 4011ae349f5Scvs2svn } 4021ae349f5Scvs2svn } else { 40330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 40430c2f2ffSBrian Somers dec->rejend += length; 4051ae349f5Scvs2svn } 4061ae349f5Scvs2svn break; 4071ae349f5Scvs2svn case MODE_NAK: 40803036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 40903036ec7SBrian Somers if (o->val.id == cp[0]) 41003036ec7SBrian Somers break; 41103036ec7SBrian Somers if (o == NULL) 41203036ec7SBrian Somers LogPrintf(LogCCP, "Warning: Ignoring peer NAK of unsent option\n"); 41303036ec7SBrian Somers else { 41403036ec7SBrian Somers memcpy(&o->val, cp, length); 41503036ec7SBrian Somers if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 41683d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 4171ae349f5Scvs2svn else { 41883d1af55SBrian Somers ccp->his_reject |= (1 << type); 41983d1af55SBrian Somers ccp->my_proto = -1; 4201ae349f5Scvs2svn } 42103036ec7SBrian Somers } 4221ae349f5Scvs2svn break; 4231ae349f5Scvs2svn case MODE_REJ: 42483d1af55SBrian Somers ccp->his_reject |= (1 << type); 42583d1af55SBrian Somers ccp->my_proto = -1; 4261ae349f5Scvs2svn break; 4271ae349f5Scvs2svn } 4281ae349f5Scvs2svn } 4291ae349f5Scvs2svn 43003036ec7SBrian Somers plen -= cp[1]; 43103036ec7SBrian Somers cp += cp[1]; 4321ae349f5Scvs2svn } 4331ae349f5Scvs2svn 43430c2f2ffSBrian Somers if (mode_type != MODE_NOP && dec->rejend != dec->rej) { 43503036ec7SBrian Somers /* rejects are preferred */ 43603036ec7SBrian Somers dec->ackend = dec->ack; 43703036ec7SBrian Somers dec->nakend = dec->nak; 43803036ec7SBrian Somers if (ccp->in.state == NULL) { 43983d1af55SBrian Somers ccp->his_proto = -1; 44003036ec7SBrian Somers ccp->in.algorithm = -1; 44103036ec7SBrian Somers } 44203036ec7SBrian Somers } else if (mode_type != MODE_NOP && dec->nakend != dec->nak) { 44303036ec7SBrian Somers /* then NAKs */ 44403036ec7SBrian Somers dec->ackend = dec->ack; 44503036ec7SBrian Somers if (ccp->in.state == NULL) { 44603036ec7SBrian Somers ccp->his_proto = -1; 44703036ec7SBrian Somers ccp->in.algorithm = -1; 448247ab36dSBrian Somers } 4491ae349f5Scvs2svn } 4501ae349f5Scvs2svn } 4511ae349f5Scvs2svn 4521ae349f5Scvs2svn void 453f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp) 4541ae349f5Scvs2svn { 4557308ec68SBrian Somers /* Got PROTO_CCP from link */ 456455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 457f4768038SBrian Somers FsmInput(&ccp->fsm, bp); 458455aabc3SBrian Somers else if (bundle_Phase(bundle) < PHASE_NETWORK) { 459455aabc3SBrian Somers LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n", 460455aabc3SBrian Somers bundle_PhaseName(bundle)); 4611ae349f5Scvs2svn pfree(bp); 4621ae349f5Scvs2svn } 4631ae349f5Scvs2svn } 4641ae349f5Scvs2svn 465503a7782SBrian Somers static void 466503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 4671ae349f5Scvs2svn { 4687308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 469f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 470f4768038SBrian Somers 471f4768038SBrian Somers if (ccp->reset_sent != -1) { 472f4768038SBrian Somers if (id != ccp->reset_sent) { 4731ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n", 474f4768038SBrian Somers id, ccp->reset_sent); 4751ae349f5Scvs2svn return; 4761ae349f5Scvs2svn } 4771ae349f5Scvs2svn /* Whaddaya know - a correct reset ack */ 478f4768038SBrian Somers } else if (id == ccp->last_reset) 4791ae349f5Scvs2svn LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n"); 4801ae349f5Scvs2svn else { 4811ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id); 4821ae349f5Scvs2svn return; 4831ae349f5Scvs2svn } 4841ae349f5Scvs2svn 485f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 486f4768038SBrian Somers ccp->reset_sent = -1; 48703036ec7SBrian Somers if (ccp->in.state != NULL) 48803036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 4891ae349f5Scvs2svn } 4901ae349f5Scvs2svn 4911ae349f5Scvs2svn int 4923b0f8d2eSBrian Somers ccp_Compress(struct ccp *ccp, struct link *l, int pri, u_short proto, 493503a7782SBrian Somers struct mbuf *m) 4941ae349f5Scvs2svn { 495503a7782SBrian Somers /* Compress outgoing Network Layer data */ 49603036ec7SBrian Somers if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && 49703036ec7SBrian Somers ccp->out.state != NULL) 49803036ec7SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Write) 49903036ec7SBrian Somers (ccp->out.state, ccp, l, pri, proto, m); 5001ae349f5Scvs2svn return 0; 5011ae349f5Scvs2svn } 5021ae349f5Scvs2svn 5031ae349f5Scvs2svn struct mbuf * 504503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp) 5051ae349f5Scvs2svn { 506ee6c193fSBrian Somers /* 507ee6c193fSBrian Somers * If proto isn't PROTO_COMPD, we still want to pass it to the 508ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 509ee6c193fSBrian Somers */ 510503a7782SBrian Somers if (ccp->fsm.state == ST_OPENED) 511ee6c193fSBrian Somers if (*proto == PROTO_COMPD) { 5127308ec68SBrian Somers /* Decompress incoming data */ 5132267893fSBrian Somers if (ccp->reset_sent != -1) 5141ae349f5Scvs2svn /* Send another REQ and put the packet in the bit bucket */ 515503a7782SBrian Somers FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0); 5162267893fSBrian Somers else if (ccp->in.state != NULL) 51703036ec7SBrian Somers return (*algorithm[ccp->in.algorithm]->i.Read) 51803036ec7SBrian Somers (ccp->in.state, ccp, proto, bp); 519ee6c193fSBrian Somers pfree(bp); 520ee6c193fSBrian Somers bp = NULL; 52103036ec7SBrian Somers } else if ((*proto & 0xfff1) == 0x21 && ccp->in.state != NULL) 522ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 52303036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.DictSetup) 52403036ec7SBrian Somers (ccp->in.state, ccp, *proto, bp); 5251ae349f5Scvs2svn 526ee6c193fSBrian Somers return bp; 5271ae349f5Scvs2svn } 528