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 * 201342caedSBrian Somers * $Id: ccp.c,v 1.30.2.33 1998/04/07 00:53:22 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o Support other compression protocols 241ae349f5Scvs2svn */ 252764b86aSBrian Somers #include <sys/types.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> 3285b542cfSBrian Somers #include <termios.h> 331ae349f5Scvs2svn 341ae349f5Scvs2svn #include "command.h" 351ae349f5Scvs2svn #include "mbuf.h" 361ae349f5Scvs2svn #include "log.h" 371ae349f5Scvs2svn #include "defs.h" 381ae349f5Scvs2svn #include "timer.h" 391ae349f5Scvs2svn #include "fsm.h" 401ae349f5Scvs2svn #include "lcpproto.h" 411ae349f5Scvs2svn #include "lcp.h" 421ae349f5Scvs2svn #include "ccp.h" 431ae349f5Scvs2svn #include "pred.h" 441ae349f5Scvs2svn #include "deflate.h" 455828db6dSBrian Somers #include "throughput.h" 465828db6dSBrian Somers #include "iplist.h" 47eaa4df37SBrian Somers #include "slcompress.h" 485828db6dSBrian Somers #include "ipcp.h" 495ca5389aSBrian Somers #include "filter.h" 5085b542cfSBrian Somers #include "descriptor.h" 5185b542cfSBrian Somers #include "prompt.h" 52879ed6faSBrian Somers #include "lqr.h" 53503a7782SBrian Somers #include "hdlc.h" 54503a7782SBrian Somers #include "link.h" 553b0f8d2eSBrian Somers #include "mp.h" 563b0f8d2eSBrian Somers #include "bundle.h" 571ae349f5Scvs2svn 581ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *); 592267893fSBrian Somers static void CcpSentTerminateReq(struct fsm *); 602267893fSBrian Somers static void CcpSendTerminateAck(struct fsm *, u_char); 6130c2f2ffSBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int, 6230c2f2ffSBrian Somers struct fsm_decode *); 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, 782267893fSBrian Somers CcpSentTerminateReq, 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) */ 958f2e5827SBrian Somers "MPPC", /* 18: Microsoft PPC (rfc2118) */ 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) */ 1021342caedSBrian Somers /* 24: Deflate (according to pppd-2.3.*) */ 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 { 129cd9647a1SBrian Somers struct link *l = ChooseLink(arg); 130cd9647a1SBrian Somers struct ccp *ccp = &l->ccp; 131503a7782SBrian Somers 132b6217683SBrian Somers prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 1331e991daaSBrian Somers State2Nam(ccp->fsm.state)); 134b6217683SBrian Somers prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 135503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 136b6217683SBrian Somers prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 137503a7782SBrian Somers ccp->uncompout, ccp->compout, 138503a7782SBrian Somers ccp->compin, ccp->uncompin); 139cd9647a1SBrian Somers 140b6217683SBrian Somers prompt_Printf(arg->prompt, "\n Defaults: "); 1411342caedSBrian Somers prompt_Printf(arg->prompt, "FSM retry = %us\n", ccp->cfg.fsmretry); 142b6217683SBrian Somers prompt_Printf(arg->prompt, " deflate windows: "); 143b6217683SBrian Somers prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 144b6217683SBrian Somers prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 1451342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE: %s\n", 1461342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); 1471342caedSBrian Somers prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", 1481342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); 1491342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE24: %s\n", 1501342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); 1511ae349f5Scvs2svn return 0; 1521ae349f5Scvs2svn } 1531ae349f5Scvs2svn 1541ae349f5Scvs2svn void 1556d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 1566d666775SBrian Somers const struct fsm_parent *parent) 1571ae349f5Scvs2svn { 1587308ec68SBrian Somers /* Initialise ourselves */ 1593b0f8d2eSBrian Somers static const char *timer_names[] = 1603b0f8d2eSBrian Somers {"CCP restart", "CCP openmode", "CCP stopped"}; 1613b0f8d2eSBrian Somers 1623b0f8d2eSBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, 10, LogCCP, 1633b0f8d2eSBrian Somers bundle, l, parent, &ccp_Callbacks, timer_names); 164cd9647a1SBrian Somers 16503036ec7SBrian Somers ccp->cfg.deflate.in.winsize = 0; 16603036ec7SBrian Somers ccp->cfg.deflate.out.winsize = 15; 167cd9647a1SBrian Somers ccp->cfg.fsmretry = DEF_FSMRETRY; 1681342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; 1691342caedSBrian Somers ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; 1701342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; 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++) 2171342caedSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 2181342caedSBrian Somers !REJECTED(ccp, algorithm[f]->id)) { 21903036ec7SBrian Somers if (alloc) { 22003036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 22103036ec7SBrian Somers (*o)->val.id = algorithm[f]->id; 22203036ec7SBrian Somers (*o)->val.len = 2; 22303036ec7SBrian Somers (*o)->next = NULL; 22403036ec7SBrian Somers (*o)->algorithm = f; 22503036ec7SBrian Somers (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 22603036ec7SBrian Somers } else { 22703036ec7SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 22803036ec7SBrian Somers if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 22903036ec7SBrian Somers break; 23003036ec7SBrian Somers if (*o == NULL) { 23103036ec7SBrian Somers LogPrintf(LogERROR, "CCP REQ buffer lost !\n"); 23203036ec7SBrian Somers break; 23303036ec7SBrian Somers } 23403036ec7SBrian Somers } 2351ae349f5Scvs2svn 23603036ec7SBrian Somers if (cp + (*o)->val.len > buff + sizeof buff) { 23730c2f2ffSBrian Somers LogPrintf(LogERROR, "CCP REQ buffer overrun !\n"); 23830c2f2ffSBrian Somers break; 23930c2f2ffSBrian Somers } 2402267893fSBrian Somers memcpy(cp, &(*o)->val, (*o)->val.len); 2412267893fSBrian Somers cp += (*o)->val.len; 24203036ec7SBrian Somers 24303036ec7SBrian Somers ccp->my_proto = (*o)->val.id; 24403036ec7SBrian Somers ccp->out.algorithm = f; 24503036ec7SBrian Somers 24603036ec7SBrian Somers if (alloc) 24703036ec7SBrian Somers o = &(*o)->next; 2481ae349f5Scvs2svn } 2492267893fSBrian Somers 2502267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff); 2511ae349f5Scvs2svn } 2521ae349f5Scvs2svn 2531ae349f5Scvs2svn void 2541ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp) 2551ae349f5Scvs2svn { 2567308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 257aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2582267893fSBrian Somers 25983d1af55SBrian Somers ccp->reset_sent = fp->reqid; 26083d1af55SBrian Somers ccp->last_reset = -1; 2611ae349f5Scvs2svn FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 2621ae349f5Scvs2svn } 2631ae349f5Scvs2svn 2641ae349f5Scvs2svn static void 2652267893fSBrian Somers CcpSentTerminateReq(struct fsm *fp) 2661ae349f5Scvs2svn { 2677308ec68SBrian Somers /* Term REQ just sent by FSM */ 2681ae349f5Scvs2svn } 2691ae349f5Scvs2svn 2701ae349f5Scvs2svn static void 2712267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 2721ae349f5Scvs2svn { 2737308ec68SBrian Somers /* Send Term ACK please */ 2742267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 2751ae349f5Scvs2svn } 2761ae349f5Scvs2svn 277503a7782SBrian Somers static void 2781ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp) 2791ae349f5Scvs2svn { 2807308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 281aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 28203036ec7SBrian Somers if (ccp->out.state != NULL) 28303036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 2841ae349f5Scvs2svn } 2851ae349f5Scvs2svn 2861ae349f5Scvs2svn static void 2871ae349f5Scvs2svn CcpLayerStart(struct fsm *fp) 2881ae349f5Scvs2svn { 2897308ec68SBrian Somers /* We're about to start up ! */ 2901ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerStart.\n"); 2911ae349f5Scvs2svn } 2921ae349f5Scvs2svn 2931ae349f5Scvs2svn static void 2941ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp) 2951ae349f5Scvs2svn { 2967308ec68SBrian Somers /* We're now down */ 297aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2981ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerFinish.\n"); 29903036ec7SBrian Somers if (ccp->in.state != NULL) { 30003036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 30103036ec7SBrian Somers ccp->in.state = NULL; 3027308ec68SBrian Somers } 30303036ec7SBrian Somers if (ccp->out.state != NULL) { 30403036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 30503036ec7SBrian Somers ccp->out.state = NULL; 3067308ec68SBrian Somers } 3071ae349f5Scvs2svn } 3081ae349f5Scvs2svn 3091ae349f5Scvs2svn static void 3101ae349f5Scvs2svn CcpLayerDown(struct fsm *fp) 3111ae349f5Scvs2svn { 3127308ec68SBrian Somers /* About to come down */ 3131ae349f5Scvs2svn LogPrintf(LogCCP, "CcpLayerDown.\n"); 3141ae349f5Scvs2svn } 3151ae349f5Scvs2svn 3161ae349f5Scvs2svn /* 3171ae349f5Scvs2svn * Called when CCP has reached the OPEN state 3181ae349f5Scvs2svn */ 3191ae349f5Scvs2svn static void 3201ae349f5Scvs2svn CcpLayerUp(struct fsm *fp) 3211ae349f5Scvs2svn { 3227308ec68SBrian Somers /* We're now up */ 323aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 324455aabc3SBrian Somers LogPrintf(LogCCP, "CcpLayerUp.\n"); 32503036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 32603036ec7SBrian Somers ccp->in.algorithm < NALGORITHMS) { 32703036ec7SBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 32803036ec7SBrian Somers if (ccp->in.state == NULL) { 329247ab36dSBrian Somers LogPrintf(LogERROR, "%s (in) initialisation failure\n", 33083d1af55SBrian Somers protoname(ccp->his_proto)); 33183d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 332247ab36dSBrian Somers FsmClose(fp); 333247ab36dSBrian Somers } 33403036ec7SBrian Somers } 33503036ec7SBrian Somers 33603036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 33703036ec7SBrian Somers ccp->out.algorithm < NALGORITHMS) { 33803036ec7SBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 33903036ec7SBrian Somers (&ccp->out.opt->val); 34003036ec7SBrian Somers if (ccp->out.state == NULL) { 341247ab36dSBrian Somers LogPrintf(LogERROR, "%s (out) initialisation failure\n", 34283d1af55SBrian Somers protoname(ccp->my_proto)); 34383d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 344247ab36dSBrian Somers FsmClose(fp); 345247ab36dSBrian Somers } 34603036ec7SBrian Somers } 34703036ec7SBrian Somers 3481ae349f5Scvs2svn LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", 34983d1af55SBrian Somers protoname(ccp->my_proto), ccp->my_proto, 35083d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 3511ae349f5Scvs2svn } 3521ae349f5Scvs2svn 3531ae349f5Scvs2svn static void 35430c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 35530c2f2ffSBrian Somers struct fsm_decode *dec) 3561ae349f5Scvs2svn { 3577308ec68SBrian Somers /* Deal with incoming data */ 358aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3591ae349f5Scvs2svn int type, length; 3601ae349f5Scvs2svn int f; 36103036ec7SBrian Somers const char *end; 3621ae349f5Scvs2svn 3631ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 3641ae349f5Scvs2svn type = *cp; 3651ae349f5Scvs2svn length = cp[1]; 36603036ec7SBrian Somers 36703036ec7SBrian Somers if (length > sizeof(struct lcp_opt)) { 36803036ec7SBrian Somers length = sizeof(struct lcp_opt); 36903036ec7SBrian Somers LogPrintf(LogCCP, "Warning: Truncating length to %d\n", length); 37003036ec7SBrian Somers } 3711ae349f5Scvs2svn 3721ae349f5Scvs2svn for (f = NALGORITHMS-1; f > -1; f--) 3731ae349f5Scvs2svn if (algorithm[f]->id == type) 3741ae349f5Scvs2svn break; 3751ae349f5Scvs2svn 37603036ec7SBrian Somers end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 37703036ec7SBrian Somers if (end == NULL) 37803036ec7SBrian Somers end = ""; 37903036ec7SBrian Somers 38003036ec7SBrian Somers if (type < NCFTYPES) 38103036ec7SBrian Somers LogPrintf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end); 38203036ec7SBrian Somers else 38303036ec7SBrian Somers LogPrintf(LogCCP, " ???[%d] %s\n", length, end); 38403036ec7SBrian Somers 3851ae349f5Scvs2svn if (f == -1) { 3861ae349f5Scvs2svn /* Don't understand that :-( */ 3871ae349f5Scvs2svn if (mode_type == MODE_REQ) { 38883d1af55SBrian Somers ccp->my_reject |= (1 << type); 38930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 39030c2f2ffSBrian Somers dec->rejend += length; 3911ae349f5Scvs2svn } 3921ae349f5Scvs2svn } else { 39303036ec7SBrian Somers struct ccp_opt *o; 3941ae349f5Scvs2svn 3951ae349f5Scvs2svn switch (mode_type) { 3961ae349f5Scvs2svn case MODE_REQ: 3971342caedSBrian Somers if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 3981342caedSBrian Somers ccp->in.algorithm == -1) { 39903036ec7SBrian Somers memcpy(&ccp->in.opt, cp, length); 40003036ec7SBrian Somers switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 4011ae349f5Scvs2svn case MODE_REJ: 40203036ec7SBrian Somers memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 40303036ec7SBrian Somers dec->rejend += ccp->in.opt.len; 4041ae349f5Scvs2svn break; 4051ae349f5Scvs2svn case MODE_NAK: 40603036ec7SBrian Somers memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 40703036ec7SBrian Somers dec->nakend += ccp->in.opt.len; 4081ae349f5Scvs2svn break; 4091ae349f5Scvs2svn case MODE_ACK: 41030c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 41130c2f2ffSBrian Somers dec->ackend += length; 41283d1af55SBrian Somers ccp->his_proto = type; 41303036ec7SBrian Somers ccp->in.algorithm = f; /* This one'll do :-) */ 4141ae349f5Scvs2svn break; 4151ae349f5Scvs2svn } 4161ae349f5Scvs2svn } else { 41730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 41830c2f2ffSBrian Somers dec->rejend += length; 4191ae349f5Scvs2svn } 4201ae349f5Scvs2svn break; 4211ae349f5Scvs2svn case MODE_NAK: 42203036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 42303036ec7SBrian Somers if (o->val.id == cp[0]) 42403036ec7SBrian Somers break; 42503036ec7SBrian Somers if (o == NULL) 42603036ec7SBrian Somers LogPrintf(LogCCP, "Warning: Ignoring peer NAK of unsent option\n"); 42703036ec7SBrian Somers else { 42803036ec7SBrian Somers memcpy(&o->val, cp, length); 42903036ec7SBrian Somers if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 43083d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 4311ae349f5Scvs2svn else { 43283d1af55SBrian Somers ccp->his_reject |= (1 << type); 43383d1af55SBrian Somers ccp->my_proto = -1; 4341ae349f5Scvs2svn } 43503036ec7SBrian Somers } 4361ae349f5Scvs2svn break; 4371ae349f5Scvs2svn case MODE_REJ: 43883d1af55SBrian Somers ccp->his_reject |= (1 << type); 43983d1af55SBrian Somers ccp->my_proto = -1; 4401ae349f5Scvs2svn break; 4411ae349f5Scvs2svn } 4421ae349f5Scvs2svn } 4431ae349f5Scvs2svn 44403036ec7SBrian Somers plen -= cp[1]; 44503036ec7SBrian Somers cp += cp[1]; 4461ae349f5Scvs2svn } 4471ae349f5Scvs2svn 4481342caedSBrian Somers if (mode_type != MODE_NOP) 4491342caedSBrian Somers if (dec->rejend != dec->rej) { 45003036ec7SBrian Somers /* rejects are preferred */ 45103036ec7SBrian Somers dec->ackend = dec->ack; 45203036ec7SBrian Somers dec->nakend = dec->nak; 45303036ec7SBrian Somers if (ccp->in.state == NULL) { 45483d1af55SBrian Somers ccp->his_proto = -1; 45503036ec7SBrian Somers ccp->in.algorithm = -1; 45603036ec7SBrian Somers } 4571342caedSBrian Somers } else if (dec->nakend != dec->nak) { 45803036ec7SBrian Somers /* then NAKs */ 45903036ec7SBrian Somers dec->ackend = dec->ack; 46003036ec7SBrian Somers if (ccp->in.state == NULL) { 46103036ec7SBrian Somers ccp->his_proto = -1; 46203036ec7SBrian Somers ccp->in.algorithm = -1; 463247ab36dSBrian Somers } 4641ae349f5Scvs2svn } 4651ae349f5Scvs2svn } 4661ae349f5Scvs2svn 4671ae349f5Scvs2svn void 468f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp) 4691ae349f5Scvs2svn { 4707308ec68SBrian Somers /* Got PROTO_CCP from link */ 471455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 472f4768038SBrian Somers FsmInput(&ccp->fsm, bp); 473455aabc3SBrian Somers else if (bundle_Phase(bundle) < PHASE_NETWORK) { 474455aabc3SBrian Somers LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n", 475455aabc3SBrian Somers bundle_PhaseName(bundle)); 4761ae349f5Scvs2svn pfree(bp); 4771ae349f5Scvs2svn } 4781ae349f5Scvs2svn } 4791ae349f5Scvs2svn 480503a7782SBrian Somers static void 481503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 4821ae349f5Scvs2svn { 4837308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 484f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 485f4768038SBrian Somers 486f4768038SBrian Somers if (ccp->reset_sent != -1) { 487f4768038SBrian Somers if (id != ccp->reset_sent) { 4881ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n", 489f4768038SBrian Somers id, ccp->reset_sent); 4901ae349f5Scvs2svn return; 4911ae349f5Scvs2svn } 4921ae349f5Scvs2svn /* Whaddaya know - a correct reset ack */ 493f4768038SBrian Somers } else if (id == ccp->last_reset) 4941ae349f5Scvs2svn LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n"); 4951ae349f5Scvs2svn else { 4961ae349f5Scvs2svn LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id); 4971ae349f5Scvs2svn return; 4981ae349f5Scvs2svn } 4991ae349f5Scvs2svn 500f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 501f4768038SBrian Somers ccp->reset_sent = -1; 50203036ec7SBrian Somers if (ccp->in.state != NULL) 50303036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 5041ae349f5Scvs2svn } 5051ae349f5Scvs2svn 5061ae349f5Scvs2svn int 5073b0f8d2eSBrian Somers ccp_Compress(struct ccp *ccp, struct link *l, int pri, u_short proto, 508503a7782SBrian Somers struct mbuf *m) 5091ae349f5Scvs2svn { 510503a7782SBrian Somers /* Compress outgoing Network Layer data */ 51103036ec7SBrian Somers if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && 51203036ec7SBrian Somers ccp->out.state != NULL) 51303036ec7SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Write) 51403036ec7SBrian Somers (ccp->out.state, ccp, l, pri, proto, m); 5151ae349f5Scvs2svn return 0; 5161ae349f5Scvs2svn } 5171ae349f5Scvs2svn 5181ae349f5Scvs2svn struct mbuf * 519503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp) 5201ae349f5Scvs2svn { 521ee6c193fSBrian Somers /* 522ee6c193fSBrian Somers * If proto isn't PROTO_COMPD, we still want to pass it to the 523ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 524ee6c193fSBrian Somers */ 525503a7782SBrian Somers if (ccp->fsm.state == ST_OPENED) 526ee6c193fSBrian Somers if (*proto == PROTO_COMPD) { 5277308ec68SBrian Somers /* Decompress incoming data */ 5282267893fSBrian Somers if (ccp->reset_sent != -1) 5291ae349f5Scvs2svn /* Send another REQ and put the packet in the bit bucket */ 530503a7782SBrian Somers FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0); 5312267893fSBrian Somers else if (ccp->in.state != NULL) 53203036ec7SBrian Somers return (*algorithm[ccp->in.algorithm]->i.Read) 53303036ec7SBrian Somers (ccp->in.state, ccp, proto, bp); 534ee6c193fSBrian Somers pfree(bp); 535ee6c193fSBrian Somers bp = NULL; 53603036ec7SBrian Somers } else if ((*proto & 0xfff1) == 0x21 && ccp->in.state != NULL) 537ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 53803036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.DictSetup) 53903036ec7SBrian Somers (ccp->in.state, ccp, *proto, bp); 5401ae349f5Scvs2svn 541ee6c193fSBrian Somers return bp; 5421ae349f5Scvs2svn } 543