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 * 201fa665f5SBrian Somers * $Id: ccp.c,v 1.30.2.39 1998/04/25 10:48:49 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> 291fa665f5SBrian Somers #include <sys/un.h> 301ae349f5Scvs2svn 311ae349f5Scvs2svn #include <stdio.h> 3203036ec7SBrian Somers #include <stdlib.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 "pred.h" 451ae349f5Scvs2svn #include "deflate.h" 465828db6dSBrian Somers #include "throughput.h" 475828db6dSBrian Somers #include "iplist.h" 48eaa4df37SBrian Somers #include "slcompress.h" 495828db6dSBrian Somers #include "ipcp.h" 505ca5389aSBrian Somers #include "filter.h" 5185b542cfSBrian Somers #include "descriptor.h" 5285b542cfSBrian Somers #include "prompt.h" 53879ed6faSBrian Somers #include "lqr.h" 54503a7782SBrian Somers #include "hdlc.h" 55503a7782SBrian Somers #include "link.h" 563b0f8d2eSBrian Somers #include "mp.h" 57ed32233cSBrian Somers #include "async.h" 58ed32233cSBrian Somers #include "physical.h" 593b0f8d2eSBrian Somers #include "bundle.h" 601ae349f5Scvs2svn 611ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *); 622267893fSBrian Somers static void CcpSentTerminateReq(struct fsm *); 632267893fSBrian Somers static void CcpSendTerminateAck(struct fsm *, u_char); 6430c2f2ffSBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int, 6530c2f2ffSBrian Somers struct fsm_decode *); 661ae349f5Scvs2svn static void CcpLayerStart(struct fsm *); 671ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *); 681ae349f5Scvs2svn static void CcpLayerUp(struct fsm *); 691ae349f5Scvs2svn static void CcpLayerDown(struct fsm *); 701ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *); 71503a7782SBrian Somers static void CcpRecvResetReq(struct fsm *); 72503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char); 731ae349f5Scvs2svn 7483d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 7583d1af55SBrian Somers CcpLayerUp, 7683d1af55SBrian Somers CcpLayerDown, 7783d1af55SBrian Somers CcpLayerStart, 786d666775SBrian Somers CcpLayerFinish, 7983d1af55SBrian Somers CcpInitRestartCounter, 8083d1af55SBrian Somers CcpSendConfigReq, 812267893fSBrian Somers CcpSentTerminateReq, 8283d1af55SBrian Somers CcpSendTerminateAck, 83503a7782SBrian Somers CcpDecodeConfig, 84503a7782SBrian Somers CcpRecvResetReq, 85503a7782SBrian Somers CcpRecvResetAck 8683d1af55SBrian Somers }; 8783d1af55SBrian Somers 881ae349f5Scvs2svn static char const *cftypes[] = { 891ae349f5Scvs2svn /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 901ae349f5Scvs2svn "OUI", /* 0: OUI */ 911ae349f5Scvs2svn "PRED1", /* 1: Predictor type 1 */ 921ae349f5Scvs2svn "PRED2", /* 2: Predictor type 2 */ 931ae349f5Scvs2svn "PUDDLE", /* 3: Puddle Jumber */ 941ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 951ae349f5Scvs2svn "???", "???", "???", "???", "???", "???", 961ae349f5Scvs2svn "HWPPC", /* 16: Hewlett-Packard PPC */ 971ae349f5Scvs2svn "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 988f2e5827SBrian Somers "MPPC", /* 18: Microsoft PPC (rfc2118) */ 991ae349f5Scvs2svn "GAND", /* 19: Gandalf FZA (rfc1993) */ 1001ae349f5Scvs2svn "V42BIS", /* 20: ARG->DATA.42bis compression */ 1011ae349f5Scvs2svn "BSD", /* 21: BSD LZW Compress */ 1021ae349f5Scvs2svn "???", 1031ae349f5Scvs2svn "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 1041ae349f5Scvs2svn "MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */ 1051342caedSBrian Somers /* 24: Deflate (according to pppd-2.3.*) */ 1061ae349f5Scvs2svn "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 1071ae349f5Scvs2svn "DEFLATE", /* 26: Deflate (rfc1979) */ 1081ae349f5Scvs2svn }; 1091ae349f5Scvs2svn 1101ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1111ae349f5Scvs2svn 1121ae349f5Scvs2svn static const char * 1131ae349f5Scvs2svn protoname(int proto) 1141ae349f5Scvs2svn { 1151ae349f5Scvs2svn if (proto < 0 || proto > NCFTYPES) 1161ae349f5Scvs2svn return "none"; 1171ae349f5Scvs2svn return cftypes[proto]; 1181ae349f5Scvs2svn } 1191ae349f5Scvs2svn 1201ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */ 1211ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = { 1221ae349f5Scvs2svn &DeflateAlgorithm, 1231ae349f5Scvs2svn &Pred1Algorithm, 1241ae349f5Scvs2svn &PppdDeflateAlgorithm 1251ae349f5Scvs2svn }; 1261ae349f5Scvs2svn 1271ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1281ae349f5Scvs2svn 1291ae349f5Scvs2svn int 130503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg) 1311ae349f5Scvs2svn { 132cd9647a1SBrian Somers struct link *l = ChooseLink(arg); 133cd9647a1SBrian Somers struct ccp *ccp = &l->ccp; 134503a7782SBrian Somers 135b6217683SBrian Somers prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 1361e991daaSBrian Somers State2Nam(ccp->fsm.state)); 137b6217683SBrian Somers prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 138503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 139b6217683SBrian Somers prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 140503a7782SBrian Somers ccp->uncompout, ccp->compout, 141503a7782SBrian Somers ccp->compin, ccp->uncompin); 142cd9647a1SBrian Somers 143b6217683SBrian Somers prompt_Printf(arg->prompt, "\n Defaults: "); 1441342caedSBrian Somers prompt_Printf(arg->prompt, "FSM retry = %us\n", ccp->cfg.fsmretry); 145b6217683SBrian Somers prompt_Printf(arg->prompt, " deflate windows: "); 146b6217683SBrian Somers prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 147b6217683SBrian Somers prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 1481342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE: %s\n", 1491342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); 1501342caedSBrian Somers prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", 1511342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); 1521342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE24: %s\n", 1531342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); 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; 1711342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; 1721342caedSBrian Somers ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; 1731342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; 174cd9647a1SBrian Somers 175503a7782SBrian Somers ccp_Setup(ccp); 176503a7782SBrian Somers } 177503a7782SBrian Somers 178503a7782SBrian Somers void 179503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 180503a7782SBrian Somers { 181503a7782SBrian Somers /* Set ourselves up for a startup */ 182503a7782SBrian Somers ccp->fsm.open_mode = 0; 1835454ccd9SBrian Somers ccp->fsm.maxconfig = 10; 184503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 185503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 18603036ec7SBrian Somers ccp->in.algorithm = ccp->out.algorithm = -1; 18703036ec7SBrian Somers ccp->in.state = ccp->out.state = NULL; 18803036ec7SBrian Somers ccp->in.opt.id = -1; 18903036ec7SBrian Somers ccp->out.opt = NULL; 190503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 191503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 192503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 1931ae349f5Scvs2svn } 1941ae349f5Scvs2svn 1951ae349f5Scvs2svn static void 1961ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp) 1971ae349f5Scvs2svn { 1987308ec68SBrian Somers /* Set fsm timer load */ 199cd9647a1SBrian Somers struct ccp *ccp = fsm2ccp(fp); 200cd9647a1SBrian Somers 201cd9647a1SBrian Somers fp->FsmTimer.load = ccp->cfg.fsmretry * SECTICKS; 2021ae349f5Scvs2svn fp->restart = 5; 2031ae349f5Scvs2svn } 2041ae349f5Scvs2svn 2051ae349f5Scvs2svn static void 2061ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp) 2071ae349f5Scvs2svn { 2087308ec68SBrian Somers /* Send config REQ please */ 209aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 21003036ec7SBrian Somers struct ccp_opt **o; 21130c2f2ffSBrian Somers u_char *cp, buff[100]; 21203036ec7SBrian Somers int f, alloc; 2131ae349f5Scvs2svn 21430c2f2ffSBrian Somers cp = buff; 21503036ec7SBrian Somers o = &ccp->out.opt; 21603036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 21783d1af55SBrian Somers ccp->my_proto = -1; 21803036ec7SBrian Somers ccp->out.algorithm = -1; 2191ae349f5Scvs2svn for (f = 0; f < NALGORITHMS; f++) 2201342caedSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 2211342caedSBrian Somers !REJECTED(ccp, algorithm[f]->id)) { 222ba081e43SBrian Somers 223ba081e43SBrian Somers if (!alloc) 224ba081e43SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 225ba081e43SBrian Somers if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 226ba081e43SBrian Somers break; 227ba081e43SBrian Somers 228ba081e43SBrian Somers if (alloc || *o == NULL) { 22903036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 23003036ec7SBrian Somers (*o)->val.id = algorithm[f]->id; 23103036ec7SBrian Somers (*o)->val.len = 2; 23203036ec7SBrian Somers (*o)->next = NULL; 23303036ec7SBrian Somers (*o)->algorithm = f; 23403036ec7SBrian Somers (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 23503036ec7SBrian Somers } 2361ae349f5Scvs2svn 23703036ec7SBrian Somers if (cp + (*o)->val.len > buff + sizeof buff) { 238d47dceb8SBrian Somers LogPrintf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 23930c2f2ffSBrian Somers break; 24030c2f2ffSBrian Somers } 2412267893fSBrian Somers memcpy(cp, &(*o)->val, (*o)->val.len); 2422267893fSBrian Somers cp += (*o)->val.len; 24303036ec7SBrian Somers 24403036ec7SBrian Somers ccp->my_proto = (*o)->val.id; 24503036ec7SBrian Somers ccp->out.algorithm = f; 24603036ec7SBrian Somers 24703036ec7SBrian Somers if (alloc) 24803036ec7SBrian Somers o = &(*o)->next; 2491ae349f5Scvs2svn } 2502267893fSBrian Somers 2512267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff); 2521ae349f5Scvs2svn } 2531ae349f5Scvs2svn 2541ae349f5Scvs2svn void 2551ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp) 2561ae349f5Scvs2svn { 2577308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 258aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 2592267893fSBrian Somers 26083d1af55SBrian Somers ccp->reset_sent = fp->reqid; 26183d1af55SBrian Somers ccp->last_reset = -1; 2621ae349f5Scvs2svn FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0); 2631ae349f5Scvs2svn } 2641ae349f5Scvs2svn 2651ae349f5Scvs2svn static void 2662267893fSBrian Somers CcpSentTerminateReq(struct fsm *fp) 2671ae349f5Scvs2svn { 2687308ec68SBrian Somers /* Term REQ just sent by FSM */ 2691ae349f5Scvs2svn } 2701ae349f5Scvs2svn 2711ae349f5Scvs2svn static void 2722267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 2731ae349f5Scvs2svn { 2747308ec68SBrian Somers /* Send Term ACK please */ 2752267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 2761ae349f5Scvs2svn } 2771ae349f5Scvs2svn 278503a7782SBrian Somers static void 2791ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp) 2801ae349f5Scvs2svn { 2817308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 282aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 28303036ec7SBrian Somers if (ccp->out.state != NULL) 28403036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 2851ae349f5Scvs2svn } 2861ae349f5Scvs2svn 2871ae349f5Scvs2svn static void 2881ae349f5Scvs2svn CcpLayerStart(struct fsm *fp) 2891ae349f5Scvs2svn { 2907308ec68SBrian Somers /* We're about to start up ! */ 291d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: CcpLayerStart.\n", fp->link->name); 2921ae349f5Scvs2svn } 2931ae349f5Scvs2svn 2941ae349f5Scvs2svn static void 2951ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp) 2961ae349f5Scvs2svn { 2977308ec68SBrian Somers /* We're now down */ 298aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 299ba081e43SBrian Somers struct ccp_opt *next; 300ba081e43SBrian Somers 301d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: CcpLayerFinish.\n", fp->link->name); 30203036ec7SBrian Somers if (ccp->in.state != NULL) { 30303036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 30403036ec7SBrian Somers ccp->in.state = NULL; 3058d9b9867SBrian Somers ccp->in.algorithm = -1; 3067308ec68SBrian Somers } 30703036ec7SBrian Somers if (ccp->out.state != NULL) { 30803036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 30903036ec7SBrian Somers ccp->out.state = NULL; 3108d9b9867SBrian Somers ccp->out.algorithm = -1; 3117308ec68SBrian Somers } 3128d9b9867SBrian Somers ccp->his_reject = ccp->my_reject = 0; 313ba081e43SBrian Somers 314ba081e43SBrian Somers while (ccp->out.opt) { 315ba081e43SBrian Somers next = ccp->out.opt->next; 316ba081e43SBrian Somers free(ccp->out.opt); 317ba081e43SBrian Somers ccp->out.opt = next; 318ba081e43SBrian Somers } 3191ae349f5Scvs2svn } 3201ae349f5Scvs2svn 3211ae349f5Scvs2svn static void 3221ae349f5Scvs2svn CcpLayerDown(struct fsm *fp) 3231ae349f5Scvs2svn { 3247308ec68SBrian Somers /* About to come down */ 325d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: CcpLayerDown.\n", fp->link->name); 3261ae349f5Scvs2svn } 3271ae349f5Scvs2svn 3281ae349f5Scvs2svn /* 3291ae349f5Scvs2svn * Called when CCP has reached the OPEN state 3301ae349f5Scvs2svn */ 3311ae349f5Scvs2svn static void 3321ae349f5Scvs2svn CcpLayerUp(struct fsm *fp) 3331ae349f5Scvs2svn { 3347308ec68SBrian Somers /* We're now up */ 335aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 336d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: CcpLayerUp.\n", fp->link->name); 33703036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 33803036ec7SBrian Somers ccp->in.algorithm < NALGORITHMS) { 33903036ec7SBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 34003036ec7SBrian Somers if (ccp->in.state == NULL) { 341d47dceb8SBrian Somers LogPrintf(LogERROR, "%s: %s (in) initialisation failure\n", 342d47dceb8SBrian Somers fp->link->name, protoname(ccp->his_proto)); 34383d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 344247ab36dSBrian Somers FsmClose(fp); 345247ab36dSBrian Somers } 34603036ec7SBrian Somers } 34703036ec7SBrian Somers 34803036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 34903036ec7SBrian Somers ccp->out.algorithm < NALGORITHMS) { 35003036ec7SBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 35103036ec7SBrian Somers (&ccp->out.opt->val); 35203036ec7SBrian Somers if (ccp->out.state == NULL) { 353d47dceb8SBrian Somers LogPrintf(LogERROR, "%s: %s (out) initialisation failure\n", 354d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto)); 35583d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 356247ab36dSBrian Somers FsmClose(fp); 357247ab36dSBrian Somers } 35803036ec7SBrian Somers } 35903036ec7SBrian Somers 360d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 361d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 36283d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 3631ae349f5Scvs2svn } 3641ae349f5Scvs2svn 3651ae349f5Scvs2svn static void 36630c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 36730c2f2ffSBrian Somers struct fsm_decode *dec) 3681ae349f5Scvs2svn { 3697308ec68SBrian Somers /* Deal with incoming data */ 370aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3711ae349f5Scvs2svn int type, length; 3721ae349f5Scvs2svn int f; 37303036ec7SBrian Somers const char *end; 3741ae349f5Scvs2svn 3751ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 3761ae349f5Scvs2svn type = *cp; 3771ae349f5Scvs2svn length = cp[1]; 37803036ec7SBrian Somers 379d47dceb8SBrian Somers if (length == 0) { 380d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: CCP size zero\n", fp->link->name); 381d47dceb8SBrian Somers break; 382d47dceb8SBrian Somers } 383d47dceb8SBrian Somers 38403036ec7SBrian Somers if (length > sizeof(struct lcp_opt)) { 38503036ec7SBrian Somers length = sizeof(struct lcp_opt); 386d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: Warning: Truncating length to %d\n", 387d47dceb8SBrian Somers fp->link->name, length); 38803036ec7SBrian Somers } 3891ae349f5Scvs2svn 3901ae349f5Scvs2svn for (f = NALGORITHMS-1; f > -1; f--) 3911ae349f5Scvs2svn if (algorithm[f]->id == type) 3921ae349f5Scvs2svn break; 3931ae349f5Scvs2svn 39403036ec7SBrian Somers end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 39503036ec7SBrian Somers if (end == NULL) 39603036ec7SBrian Somers end = ""; 39703036ec7SBrian Somers 39803036ec7SBrian Somers if (type < NCFTYPES) 39903036ec7SBrian Somers LogPrintf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end); 40003036ec7SBrian Somers else 40103036ec7SBrian Somers LogPrintf(LogCCP, " ???[%d] %s\n", length, end); 40203036ec7SBrian Somers 4031ae349f5Scvs2svn if (f == -1) { 4041ae349f5Scvs2svn /* Don't understand that :-( */ 4051ae349f5Scvs2svn if (mode_type == MODE_REQ) { 40683d1af55SBrian Somers ccp->my_reject |= (1 << type); 40730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 40830c2f2ffSBrian Somers dec->rejend += length; 4091ae349f5Scvs2svn } 4101ae349f5Scvs2svn } else { 41103036ec7SBrian Somers struct ccp_opt *o; 4121ae349f5Scvs2svn 4131ae349f5Scvs2svn switch (mode_type) { 4141ae349f5Scvs2svn case MODE_REQ: 4151342caedSBrian Somers if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 4161342caedSBrian Somers ccp->in.algorithm == -1) { 41703036ec7SBrian Somers memcpy(&ccp->in.opt, cp, length); 41803036ec7SBrian Somers switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 4191ae349f5Scvs2svn case MODE_REJ: 42003036ec7SBrian Somers memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 42103036ec7SBrian Somers dec->rejend += ccp->in.opt.len; 4221ae349f5Scvs2svn break; 4231ae349f5Scvs2svn case MODE_NAK: 42403036ec7SBrian Somers memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 42503036ec7SBrian Somers dec->nakend += ccp->in.opt.len; 4261ae349f5Scvs2svn break; 4271ae349f5Scvs2svn case MODE_ACK: 42830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 42930c2f2ffSBrian Somers dec->ackend += length; 43083d1af55SBrian Somers ccp->his_proto = type; 43103036ec7SBrian Somers ccp->in.algorithm = f; /* This one'll do :-) */ 4321ae349f5Scvs2svn break; 4331ae349f5Scvs2svn } 4341ae349f5Scvs2svn } else { 43530c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 43630c2f2ffSBrian Somers dec->rejend += length; 4371ae349f5Scvs2svn } 4381ae349f5Scvs2svn break; 4391ae349f5Scvs2svn case MODE_NAK: 44003036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 44103036ec7SBrian Somers if (o->val.id == cp[0]) 44203036ec7SBrian Somers break; 44303036ec7SBrian Somers if (o == NULL) 444d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent option\n", 445d47dceb8SBrian Somers fp->link->name); 44603036ec7SBrian Somers else { 44703036ec7SBrian Somers memcpy(&o->val, cp, length); 44803036ec7SBrian Somers if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 44983d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 4501ae349f5Scvs2svn else { 45183d1af55SBrian Somers ccp->his_reject |= (1 << type); 45283d1af55SBrian Somers ccp->my_proto = -1; 4531ae349f5Scvs2svn } 45403036ec7SBrian Somers } 4551ae349f5Scvs2svn break; 4561ae349f5Scvs2svn case MODE_REJ: 45783d1af55SBrian Somers ccp->his_reject |= (1 << type); 45883d1af55SBrian Somers ccp->my_proto = -1; 4591ae349f5Scvs2svn break; 4601ae349f5Scvs2svn } 4611ae349f5Scvs2svn } 4621ae349f5Scvs2svn 46303036ec7SBrian Somers plen -= cp[1]; 46403036ec7SBrian Somers cp += cp[1]; 4651ae349f5Scvs2svn } 4661ae349f5Scvs2svn 467e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 4681342caedSBrian Somers if (dec->rejend != dec->rej) { 46903036ec7SBrian Somers /* rejects are preferred */ 47003036ec7SBrian Somers dec->ackend = dec->ack; 47103036ec7SBrian Somers dec->nakend = dec->nak; 47203036ec7SBrian Somers if (ccp->in.state == NULL) { 47383d1af55SBrian Somers ccp->his_proto = -1; 47403036ec7SBrian Somers ccp->in.algorithm = -1; 47503036ec7SBrian Somers } 4761342caedSBrian Somers } else if (dec->nakend != dec->nak) { 47703036ec7SBrian Somers /* then NAKs */ 47803036ec7SBrian Somers dec->ackend = dec->ack; 47903036ec7SBrian Somers if (ccp->in.state == NULL) { 48003036ec7SBrian Somers ccp->his_proto = -1; 48103036ec7SBrian Somers ccp->in.algorithm = -1; 482247ab36dSBrian Somers } 4831ae349f5Scvs2svn } 4841ae349f5Scvs2svn } 485e43ebac1SBrian Somers } 4861ae349f5Scvs2svn 4871ae349f5Scvs2svn void 488f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp) 4891ae349f5Scvs2svn { 4907308ec68SBrian Somers /* Got PROTO_CCP from link */ 491455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 492f4768038SBrian Somers FsmInput(&ccp->fsm, bp); 493455aabc3SBrian Somers else if (bundle_Phase(bundle) < PHASE_NETWORK) { 494d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 495d47dceb8SBrian Somers ccp->fsm.link->name, bundle_PhaseName(bundle)); 4961ae349f5Scvs2svn pfree(bp); 4971ae349f5Scvs2svn } 4981ae349f5Scvs2svn } 4991ae349f5Scvs2svn 500503a7782SBrian Somers static void 501503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 5021ae349f5Scvs2svn { 5037308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 504f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 505f4768038SBrian Somers 506f4768038SBrian Somers if (ccp->reset_sent != -1) { 507f4768038SBrian Somers if (id != ccp->reset_sent) { 508d47dceb8SBrian Somers LogPrintf(LogWARN, "CCP: %s: Incorrect ResetAck (id %d, not %d)" 509d47dceb8SBrian Somers " ignored\n", fp->link->name, id, ccp->reset_sent); 5101ae349f5Scvs2svn return; 5111ae349f5Scvs2svn } 5121ae349f5Scvs2svn /* Whaddaya know - a correct reset ack */ 513f4768038SBrian Somers } else if (id == ccp->last_reset) 514d47dceb8SBrian Somers LogPrintf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 515d47dceb8SBrian Somers fp->link->name); 5161ae349f5Scvs2svn else { 517d47dceb8SBrian Somers LogPrintf(LogWARN, "CCP: %s: Unexpected ResetAck (id %d) ignored\n", 518d47dceb8SBrian Somers fp->link->name, id); 5191ae349f5Scvs2svn return; 5201ae349f5Scvs2svn } 5211ae349f5Scvs2svn 522f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 523f4768038SBrian Somers ccp->reset_sent = -1; 52403036ec7SBrian Somers if (ccp->in.state != NULL) 52503036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 5261ae349f5Scvs2svn } 5271ae349f5Scvs2svn 5281ae349f5Scvs2svn int 5293b0f8d2eSBrian Somers ccp_Compress(struct ccp *ccp, struct link *l, int pri, u_short proto, 530503a7782SBrian Somers struct mbuf *m) 5311ae349f5Scvs2svn { 532503a7782SBrian Somers /* Compress outgoing Network Layer data */ 53303036ec7SBrian Somers if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && 53403036ec7SBrian Somers ccp->out.state != NULL) 53503036ec7SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Write) 53603036ec7SBrian Somers (ccp->out.state, ccp, l, pri, proto, m); 5371ae349f5Scvs2svn return 0; 5381ae349f5Scvs2svn } 5391ae349f5Scvs2svn 5401ae349f5Scvs2svn struct mbuf * 541503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp) 5421ae349f5Scvs2svn { 543ee6c193fSBrian Somers /* 544ed32233cSBrian Somers * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 545ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 546ee6c193fSBrian Somers */ 547e43ebac1SBrian Somers if (ccp->fsm.state == ST_OPENED) { 548ed32233cSBrian Somers if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 5497308ec68SBrian Somers /* Decompress incoming data */ 5502267893fSBrian Somers if (ccp->reset_sent != -1) 5511ae349f5Scvs2svn /* Send another REQ and put the packet in the bit bucket */ 552503a7782SBrian Somers FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0); 5532267893fSBrian Somers else if (ccp->in.state != NULL) 55403036ec7SBrian Somers return (*algorithm[ccp->in.algorithm]->i.Read) 55503036ec7SBrian Somers (ccp->in.state, ccp, proto, bp); 556ee6c193fSBrian Somers pfree(bp); 557ee6c193fSBrian Somers bp = NULL; 55803036ec7SBrian Somers } else if ((*proto & 0xfff1) == 0x21 && ccp->in.state != NULL) 559ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 56003036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.DictSetup) 56103036ec7SBrian Somers (ccp->in.state, ccp, *proto, bp); 562e43ebac1SBrian Somers } 5631ae349f5Scvs2svn 564ee6c193fSBrian Somers return bp; 5651ae349f5Scvs2svn } 566ed32233cSBrian Somers 567ed32233cSBrian Somers u_short 568ed32233cSBrian Somers ccp_Proto(struct ccp *ccp) 569ed32233cSBrian Somers { 570ed32233cSBrian Somers return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 571ed32233cSBrian Somers PROTO_COMPD : PROTO_ICOMPD; 572ed32233cSBrian Somers } 573