165309e5cSBrian Somers /*- 2*1de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*1de7b4b8SPedro F. Giffuni * 465309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 565309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 665309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 765309e5cSBrian Somers * All rights reserved. 8af57ed9fSAtsushi Murai * 965309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 1065309e5cSBrian Somers * modification, are permitted provided that the following conditions 1165309e5cSBrian Somers * are met: 1265309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1465309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1565309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1665309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 17af57ed9fSAtsushi Murai * 1865309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1965309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2065309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2165309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2265309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2365309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2465309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2565309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2665309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2765309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2865309e5cSBrian Somers * SUCH DAMAGE. 29af57ed9fSAtsushi Murai * 3097d92980SPeter Wemm * $FreeBSD$ 31af57ed9fSAtsushi Murai */ 3265309e5cSBrian Somers 33972a1bcfSBrian Somers #include <sys/param.h> 3475240ed1SBrian Somers #include <netinet/in.h> 35eaa4df37SBrian Somers #include <netinet/in_systm.h> 36eaa4df37SBrian Somers #include <netinet/ip.h> 3730949fd4SBrian Somers #include <sys/socket.h> 381fa665f5SBrian Somers #include <sys/un.h> 3975240ed1SBrian Somers 406eafd353SBrian Somers #include <stdarg.h> 4175240ed1SBrian Somers #include <stdio.h> 4203036ec7SBrian Somers #include <stdlib.h> 43eb6e5e05SBrian Somers #include <string.h> /* memcpy() on some archs */ 4485b542cfSBrian Somers #include <termios.h> 4575240ed1SBrian Somers 465d9e6103SBrian Somers #include "layer.h" 47c9e11a11SBrian Somers #include "defs.h" 48b6e82f33SBrian Somers #include "command.h" 4975240ed1SBrian Somers #include "mbuf.h" 5075240ed1SBrian Somers #include "log.h" 5175240ed1SBrian Somers #include "timer.h" 52af57ed9fSAtsushi Murai #include "fsm.h" 535d9e6103SBrian Somers #include "proto.h" 54ed6a16c1SPoul-Henning Kamp #include "pred.h" 550053cc58SBrian Somers #include "deflate.h" 565828db6dSBrian Somers #include "throughput.h" 575828db6dSBrian Somers #include "iplist.h" 58eaa4df37SBrian Somers #include "slcompress.h" 595a72b6edSBrian Somers #include "lqr.h" 605a72b6edSBrian Somers #include "hdlc.h" 611038894eSBrian Somers #include "lcp.h" 621038894eSBrian Somers #include "ccp.h" 6330949fd4SBrian Somers #include "ncpaddr.h" 645828db6dSBrian Somers #include "ipcp.h" 655ca5389aSBrian Somers #include "filter.h" 6685b542cfSBrian Somers #include "descriptor.h" 6785b542cfSBrian Somers #include "prompt.h" 68503a7782SBrian Somers #include "link.h" 693b0f8d2eSBrian Somers #include "mp.h" 70ed32233cSBrian Somers #include "async.h" 71ed32233cSBrian Somers #include "physical.h" 72972a1bcfSBrian Somers #ifndef NORADIUS 73972a1bcfSBrian Somers #include "radius.h" 74972a1bcfSBrian Somers #endif 75fb11a9c2SBrian Somers #ifndef NODES 76a8d604abSBrian Somers #include "mppe.h" 77a8d604abSBrian Somers #endif 7830949fd4SBrian Somers #include "ipv6cp.h" 7930949fd4SBrian Somers #include "ncp.h" 803b0f8d2eSBrian Somers #include "bundle.h" 81af57ed9fSAtsushi Murai 82927145beSBrian Somers static void CcpSendConfigReq(struct fsm *); 832267893fSBrian Somers static void CcpSentTerminateReq(struct fsm *); 842267893fSBrian Somers static void CcpSendTerminateAck(struct fsm *, u_char); 85ff360cc9SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, u_char *, int, 8630c2f2ffSBrian Somers struct fsm_decode *); 87927145beSBrian Somers static void CcpLayerStart(struct fsm *); 88927145beSBrian Somers static void CcpLayerFinish(struct fsm *); 896f384573SBrian Somers static int CcpLayerUp(struct fsm *); 90927145beSBrian Somers static void CcpLayerDown(struct fsm *); 91479508cfSBrian Somers static void CcpInitRestartCounter(struct fsm *, int); 926cf6ee76SBrian Somers static int CcpRecvResetReq(struct fsm *); 93503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char); 94af57ed9fSAtsushi Murai 9583d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 96af57ed9fSAtsushi Murai CcpLayerUp, 97af57ed9fSAtsushi Murai CcpLayerDown, 98af57ed9fSAtsushi Murai CcpLayerStart, 99af57ed9fSAtsushi Murai CcpLayerFinish, 100af57ed9fSAtsushi Murai CcpInitRestartCounter, 101af57ed9fSAtsushi Murai CcpSendConfigReq, 1022267893fSBrian Somers CcpSentTerminateReq, 103af57ed9fSAtsushi Murai CcpSendTerminateAck, 104af57ed9fSAtsushi Murai CcpDecodeConfig, 105503a7782SBrian Somers CcpRecvResetReq, 106503a7782SBrian Somers CcpRecvResetAck 107af57ed9fSAtsushi Murai }; 108af57ed9fSAtsushi Murai 109182c898aSBrian Somers static const char * const ccp_TimerNames[] = 1106f384573SBrian Somers {"CCP restart", "CCP openmode", "CCP stopped"}; 1116f384573SBrian Somers 112d6d3eeabSBrian Somers static const char * 113d6d3eeabSBrian Somers protoname(int proto) 114d6d3eeabSBrian Somers { 115182c898aSBrian Somers static char const * const cftypes[] = { 116d6d3eeabSBrian Somers /* Check out the latest ``Compression Control Protocol'' rfc (1962) */ 1179e836af5SBrian Somers "OUI", /* 0: OUI */ 1189e836af5SBrian Somers "PRED1", /* 1: Predictor type 1 */ 1199e836af5SBrian Somers "PRED2", /* 2: Predictor type 2 */ 1209e836af5SBrian Somers "PUDDLE", /* 3: Puddle Jumber */ 121d6d3eeabSBrian Somers NULL, NULL, NULL, NULL, NULL, NULL, 122d6d3eeabSBrian Somers NULL, NULL, NULL, NULL, NULL, NULL, 1239e836af5SBrian Somers "HWPPC", /* 16: Hewlett-Packard PPC */ 1244bc84b8cSBrian Somers "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 125a8d604abSBrian Somers "MPPE", /* 18: Microsoft PPC (rfc2118) and */ 126a8d604abSBrian Somers /* Microsoft PPE (draft-ietf-pppext-mppe) */ 1274bc84b8cSBrian Somers "GAND", /* 19: Gandalf FZA (rfc1993) */ 128b6e82f33SBrian Somers "V42BIS", /* 20: ARG->DATA.42bis compression */ 1290053cc58SBrian Somers "BSD", /* 21: BSD LZW Compress */ 130d6d3eeabSBrian Somers NULL, 1314bc84b8cSBrian Somers "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 1324bc84b8cSBrian Somers "MAGNALINK/DEFLATE",/* 24: Magnalink Variable Resource (rfc1975) */ 1331342caedSBrian Somers /* 24: Deflate (according to pppd-2.3.*) */ 1344bc84b8cSBrian Somers "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 1354bc84b8cSBrian Somers "DEFLATE", /* 26: Deflate (rfc1979) */ 136af57ed9fSAtsushi Murai }; 137af57ed9fSAtsushi Murai 138057f1760SBrian Somers if (proto < 0 || (unsigned)proto > sizeof cftypes / sizeof *cftypes || 1399ea69707SBrian Somers cftypes[proto] == NULL) { 1409ea69707SBrian Somers if (proto == -1) 1419ea69707SBrian Somers return "none"; 142d6d3eeabSBrian Somers return HexStr(proto, NULL, 0); 1439ea69707SBrian Somers } 1449e836af5SBrian Somers 1450053cc58SBrian Somers return cftypes[proto]; 1460053cc58SBrian Somers } 1470053cc58SBrian Somers 1484bc84b8cSBrian Somers /* We support these algorithms, and Req them in the given order */ 149182c898aSBrian Somers static const struct ccp_algorithm * const algorithm[] = { 1504bc84b8cSBrian Somers &DeflateAlgorithm, 1510053cc58SBrian Somers &Pred1Algorithm, 1524bc84b8cSBrian Somers &PppdDeflateAlgorithm 153fb11a9c2SBrian Somers #ifndef NODES 154a8d604abSBrian Somers , &MPPEAlgorithm 155a8d604abSBrian Somers #endif 1560053cc58SBrian Somers }; 1570053cc58SBrian Somers 15870ee81ffSBrian Somers #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1590053cc58SBrian Somers 160274e766cSBrian Somers int 161503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg) 162af57ed9fSAtsushi Murai { 1636cf6ee76SBrian Somers struct ccp_opt **o; 164dd0645c5SBrian Somers struct link *l; 165dd0645c5SBrian Somers struct ccp *ccp; 1666cf6ee76SBrian Somers int f; 167dd0645c5SBrian Somers 1683a2e4f62SBrian Somers l = command_ChooseLink(arg); 169dd0645c5SBrian Somers ccp = &l->ccp; 170503a7782SBrian Somers 171b6217683SBrian Somers prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 1721e991daaSBrian Somers State2Nam(ccp->fsm.state)); 1735d9e6103SBrian Somers if (ccp->fsm.state == ST_OPENED) { 174b6217683SBrian Somers prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 175503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 176b6217683SBrian Somers prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 177503a7782SBrian Somers ccp->uncompout, ccp->compout, 178503a7782SBrian Somers ccp->compin, ccp->uncompin); 1795d9e6103SBrian Somers } 180cd9647a1SBrian Somers 1816cf6ee76SBrian Somers if (ccp->in.algorithm != -1) 1826cf6ee76SBrian Somers prompt_Printf(arg->prompt, "\n Input Options: %s\n", 1836cf6ee76SBrian Somers (*algorithm[ccp->in.algorithm]->Disp)(&ccp->in.opt)); 1846cf6ee76SBrian Somers 1856cf6ee76SBrian Somers if (ccp->out.algorithm != -1) { 1866cf6ee76SBrian Somers o = &ccp->out.opt; 1876cf6ee76SBrian Somers for (f = 0; f < ccp->out.algorithm; f++) 1886cf6ee76SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 1896cf6ee76SBrian Somers o = &(*o)->next; 1906cf6ee76SBrian Somers prompt_Printf(arg->prompt, " Output Options: %s\n", 1916cf6ee76SBrian Somers (*algorithm[ccp->out.algorithm]->Disp)(&(*o)->val)); 1926cf6ee76SBrian Somers } 1936cf6ee76SBrian Somers 194b6217683SBrian Somers prompt_Printf(arg->prompt, "\n Defaults: "); 195479508cfSBrian Somers prompt_Printf(arg->prompt, "FSM retry = %us, max %u Config" 196479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ccp->cfg.fsm.timeout, 197479508cfSBrian Somers ccp->cfg.fsm.maxreq, ccp->cfg.fsm.maxreq == 1 ? "" : "s", 198479508cfSBrian Somers ccp->cfg.fsm.maxtrm, ccp->cfg.fsm.maxtrm == 1 ? "" : "s"); 199b6217683SBrian Somers prompt_Printf(arg->prompt, " deflate windows: "); 200b6217683SBrian Somers prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 201b6217683SBrian Somers prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 202fb11a9c2SBrian Somers #ifndef NODES 2036cf6ee76SBrian Somers prompt_Printf(arg->prompt, " MPPE: "); 2046cf6ee76SBrian Somers if (ccp->cfg.mppe.keybits) 2056cf6ee76SBrian Somers prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits); 2066cf6ee76SBrian Somers else 2076cf6ee76SBrian Somers prompt_Printf(arg->prompt, "any bits, "); 2086cf6ee76SBrian Somers switch (ccp->cfg.mppe.state) { 2096cf6ee76SBrian Somers case MPPE_STATEFUL: 21080a18377SBrian Somers prompt_Printf(arg->prompt, "stateful"); 2116cf6ee76SBrian Somers break; 2126cf6ee76SBrian Somers case MPPE_STATELESS: 2136cf6ee76SBrian Somers prompt_Printf(arg->prompt, "stateless"); 2146cf6ee76SBrian Somers break; 2156cf6ee76SBrian Somers case MPPE_ANYSTATE: 2166cf6ee76SBrian Somers prompt_Printf(arg->prompt, "any state"); 2176cf6ee76SBrian Somers break; 2186cf6ee76SBrian Somers } 2196cf6ee76SBrian Somers prompt_Printf(arg->prompt, "%s\n", 2206cf6ee76SBrian Somers ccp->cfg.mppe.required ? ", required" : ""); 2216cf6ee76SBrian Somers #endif 2226cf6ee76SBrian Somers 2236cf6ee76SBrian Somers prompt_Printf(arg->prompt, "\n DEFLATE: %s\n", 2241342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); 2251342caedSBrian Somers prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", 2261342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); 2271342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE24: %s\n", 2281342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); 229fb11a9c2SBrian Somers #ifndef NODES 2306cf6ee76SBrian Somers prompt_Printf(arg->prompt, " MPPE: %s\n", 231a8d604abSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE])); 232a8d604abSBrian Somers #endif 233274e766cSBrian Somers return 0; 234af57ed9fSAtsushi Murai } 235af57ed9fSAtsushi Murai 2361ae349f5Scvs2svn void 2376f384573SBrian Somers ccp_SetupCallbacks(struct ccp *ccp) 238af57ed9fSAtsushi Murai { 2396f384573SBrian Somers ccp->fsm.fn = &ccp_Callbacks; 2406f384573SBrian Somers ccp->fsm.FsmTimer.name = ccp_TimerNames[0]; 2416f384573SBrian Somers ccp->fsm.OpenTimer.name = ccp_TimerNames[1]; 2426f384573SBrian Somers ccp->fsm.StoppedTimer.name = ccp_TimerNames[2]; 243ea661041SBrian Somers } 244ea661041SBrian Somers 245ea661041SBrian Somers void 2466d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 2476d666775SBrian Somers const struct fsm_parent *parent) 248ea661041SBrian Somers { 2497308ec68SBrian Somers /* Initialise ourselves */ 2503b0f8d2eSBrian Somers 251479508cfSBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, LogCCP, 2526f384573SBrian Somers bundle, l, parent, &ccp_Callbacks, ccp_TimerNames); 253cd9647a1SBrian Somers 25403036ec7SBrian Somers ccp->cfg.deflate.in.winsize = 0; 25503036ec7SBrian Somers ccp->cfg.deflate.out.winsize = 15; 256479508cfSBrian Somers ccp->cfg.fsm.timeout = DEF_FSMRETRY; 257479508cfSBrian Somers ccp->cfg.fsm.maxreq = DEF_FSMTRIES; 258479508cfSBrian Somers ccp->cfg.fsm.maxtrm = DEF_FSMTRIES; 2591342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; 2601342caedSBrian Somers ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; 2611342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; 262fb11a9c2SBrian Somers #ifndef NODES 2636cf6ee76SBrian Somers ccp->cfg.mppe.keybits = 0; 2646cf6ee76SBrian Somers ccp->cfg.mppe.state = MPPE_ANYSTATE; 2656cf6ee76SBrian Somers ccp->cfg.mppe.required = 0; 266385167a6SBrian Somers ccp->cfg.neg[CCP_NEG_MPPE] = NEG_ENABLED|NEG_ACCEPTED; 267a8d604abSBrian Somers #endif 268cd9647a1SBrian Somers 269503a7782SBrian Somers ccp_Setup(ccp); 270503a7782SBrian Somers } 271503a7782SBrian Somers 272503a7782SBrian Somers void 273503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 274503a7782SBrian Somers { 275503a7782SBrian Somers /* Set ourselves up for a startup */ 276503a7782SBrian Somers ccp->fsm.open_mode = 0; 277503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 278503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 27903036ec7SBrian Somers ccp->in.algorithm = ccp->out.algorithm = -1; 28003036ec7SBrian Somers ccp->in.state = ccp->out.state = NULL; 281ff360cc9SBrian Somers ccp->in.opt.hdr.id = -1; 28203036ec7SBrian Somers ccp->out.opt = NULL; 283503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 284503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 285503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 286af57ed9fSAtsushi Murai } 287af57ed9fSAtsushi Murai 2886cf6ee76SBrian Somers /* 2896cf6ee76SBrian Somers * Is ccp *REQUIRED* ? 2906cf6ee76SBrian Somers * We ask each of the configured ccp protocols if they're required and 2916cf6ee76SBrian Somers * return TRUE if they are. 2926cf6ee76SBrian Somers * 2936cf6ee76SBrian Somers * It's not possible for the peer to reject a required ccp protocol 2946cf6ee76SBrian Somers * without our state machine bringing the supporting lcp layer down. 2956cf6ee76SBrian Somers * 2966cf6ee76SBrian Somers * If ccp is required but not open, the NCP layer should not push 2976cf6ee76SBrian Somers * any data into the link. 2986cf6ee76SBrian Somers */ 2996cf6ee76SBrian Somers int 3006cf6ee76SBrian Somers ccp_Required(struct ccp *ccp) 3016cf6ee76SBrian Somers { 302057f1760SBrian Somers unsigned f; 3036cf6ee76SBrian Somers 3046cf6ee76SBrian Somers for (f = 0; f < NALGORITHMS; f++) 3056cf6ee76SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 3066cf6ee76SBrian Somers (*algorithm[f]->Required)(&ccp->fsm)) 3076cf6ee76SBrian Somers return 1; 3086cf6ee76SBrian Somers 3096cf6ee76SBrian Somers return 0; 3106cf6ee76SBrian Somers } 3116cf6ee76SBrian Somers 3126301d506SBrian Somers /* 3136301d506SBrian Somers * Report whether it's possible to increase a packet's size after 3146301d506SBrian Somers * compression (and by how much). 3156301d506SBrian Somers */ 3166301d506SBrian Somers int 3176301d506SBrian Somers ccp_MTUOverhead(struct ccp *ccp) 3186301d506SBrian Somers { 3197e62c638SBrian Somers if (ccp->fsm.state == ST_OPENED && ccp->out.algorithm >= 0) 3206301d506SBrian Somers return algorithm[ccp->out.algorithm]->o.MTUOverhead; 3216301d506SBrian Somers 3226301d506SBrian Somers return 0; 3236301d506SBrian Somers } 3246301d506SBrian Somers 325af57ed9fSAtsushi Murai static void 326479508cfSBrian Somers CcpInitRestartCounter(struct fsm *fp, int what) 327af57ed9fSAtsushi Murai { 3287308ec68SBrian Somers /* Set fsm timer load */ 329cd9647a1SBrian Somers struct ccp *ccp = fsm2ccp(fp); 330cd9647a1SBrian Somers 331479508cfSBrian Somers fp->FsmTimer.load = ccp->cfg.fsm.timeout * SECTICKS; 332479508cfSBrian Somers switch (what) { 333479508cfSBrian Somers case FSM_REQ_TIMER: 334479508cfSBrian Somers fp->restart = ccp->cfg.fsm.maxreq; 335479508cfSBrian Somers break; 336479508cfSBrian Somers case FSM_TRM_TIMER: 337479508cfSBrian Somers fp->restart = ccp->cfg.fsm.maxtrm; 338479508cfSBrian Somers break; 339479508cfSBrian Somers default: 340479508cfSBrian Somers fp->restart = 1; 341479508cfSBrian Somers break; 342479508cfSBrian Somers } 343af57ed9fSAtsushi Murai } 344af57ed9fSAtsushi Murai 345af57ed9fSAtsushi Murai static void 346944f7098SBrian Somers CcpSendConfigReq(struct fsm *fp) 347af57ed9fSAtsushi Murai { 3487308ec68SBrian Somers /* Send config REQ please */ 349aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 35003036ec7SBrian Somers struct ccp_opt **o; 35130c2f2ffSBrian Somers u_char *cp, buff[100]; 352057f1760SBrian Somers unsigned f; 353057f1760SBrian Somers int alloc; 354af57ed9fSAtsushi Murai 35530c2f2ffSBrian Somers cp = buff; 35603036ec7SBrian Somers o = &ccp->out.opt; 35703036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 35883d1af55SBrian Somers ccp->my_proto = -1; 35903036ec7SBrian Somers ccp->out.algorithm = -1; 3600053cc58SBrian Somers for (f = 0; f < NALGORITHMS; f++) 3611342caedSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 3627f89db65SBrian Somers !REJECTED(ccp, algorithm[f]->id) && 3637f89db65SBrian Somers (*algorithm[f]->Usable)(fp)) { 3640053cc58SBrian Somers 365ba081e43SBrian Somers if (!alloc) 366ba081e43SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 367057f1760SBrian Somers if ((*o)->val.hdr.id == algorithm[f]->id && (*o)->algorithm == (int)f) 368ba081e43SBrian Somers break; 369ba081e43SBrian Somers 370ba081e43SBrian Somers if (alloc || *o == NULL) { 3715d604c11SBrian Somers if ((*o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt))) == NULL) { 3725d604c11SBrian Somers log_Printf(LogERROR, "%s: Not enough memory for CCP REQ !\n", 3735d604c11SBrian Somers fp->link->name); 3745d604c11SBrian Somers break; 3755d604c11SBrian Somers } 376ff360cc9SBrian Somers (*o)->val.hdr.id = algorithm[f]->id; 377ff360cc9SBrian Somers (*o)->val.hdr.len = 2; 37803036ec7SBrian Somers (*o)->next = NULL; 37903036ec7SBrian Somers (*o)->algorithm = f; 3808fb5ef5aSBrian Somers (*algorithm[f]->o.OptInit)(fp->bundle, &(*o)->val, &ccp->cfg); 381af57ed9fSAtsushi Murai } 3821ae349f5Scvs2svn 383ff360cc9SBrian Somers if (cp + (*o)->val.hdr.len > buff + sizeof buff) { 384dd7e2610SBrian Somers log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 38530c2f2ffSBrian Somers break; 38630c2f2ffSBrian Somers } 387ff360cc9SBrian Somers memcpy(cp, &(*o)->val, (*o)->val.hdr.len); 388ff360cc9SBrian Somers cp += (*o)->val.hdr.len; 38903036ec7SBrian Somers 390ff360cc9SBrian Somers ccp->my_proto = (*o)->val.hdr.id; 39103036ec7SBrian Somers ccp->out.algorithm = f; 39203036ec7SBrian Somers 39303036ec7SBrian Somers if (alloc) 39403036ec7SBrian Somers o = &(*o)->next; 3951ae349f5Scvs2svn } 3962267893fSBrian Somers 397411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT); 398af57ed9fSAtsushi Murai } 399af57ed9fSAtsushi Murai 400af57ed9fSAtsushi Murai void 401dd7e2610SBrian Somers ccp_SendResetReq(struct fsm *fp) 402af57ed9fSAtsushi Murai { 4037308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 404aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 4052267893fSBrian Somers 40683d1af55SBrian Somers ccp->reset_sent = fp->reqid; 40783d1af55SBrian Somers ccp->last_reset = -1; 408411675baSBrian Somers fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT); 409af57ed9fSAtsushi Murai } 410af57ed9fSAtsushi Murai 411af57ed9fSAtsushi Murai static void 412057f1760SBrian Somers CcpSentTerminateReq(struct fsm *fp __unused) 413af57ed9fSAtsushi Murai { 4147308ec68SBrian Somers /* Term REQ just sent by FSM */ 415af57ed9fSAtsushi Murai } 416af57ed9fSAtsushi Murai 417af57ed9fSAtsushi Murai static void 4182267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 419af57ed9fSAtsushi Murai { 4207308ec68SBrian Somers /* Send Term ACK please */ 421411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); 422af57ed9fSAtsushi Murai } 423af57ed9fSAtsushi Murai 4246cf6ee76SBrian Somers static int 425944f7098SBrian Somers CcpRecvResetReq(struct fsm *fp) 426af57ed9fSAtsushi Murai { 4277308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 428aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 4296cf6ee76SBrian Somers if (ccp->out.state == NULL) 4306cf6ee76SBrian Somers return 1; 4316cf6ee76SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 432af57ed9fSAtsushi Murai } 433af57ed9fSAtsushi Murai 434af57ed9fSAtsushi Murai static void 435944f7098SBrian Somers CcpLayerStart(struct fsm *fp) 436af57ed9fSAtsushi Murai { 4377308ec68SBrian Somers /* We're about to start up ! */ 438479508cfSBrian Somers struct ccp *ccp = fsm2ccp(fp); 439479508cfSBrian Somers 4403a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name); 441479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 442af57ed9fSAtsushi Murai } 443af57ed9fSAtsushi Murai 444af57ed9fSAtsushi Murai static void 445897f9429SBrian Somers CcpLayerDown(struct fsm *fp) 446af57ed9fSAtsushi Murai { 447897f9429SBrian Somers /* About to come down */ 448aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 449ba081e43SBrian Somers struct ccp_opt *next; 450ba081e43SBrian Somers 4513a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name); 45203036ec7SBrian Somers if (ccp->in.state != NULL) { 45303036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 45403036ec7SBrian Somers ccp->in.state = NULL; 4558d9b9867SBrian Somers ccp->in.algorithm = -1; 4567308ec68SBrian Somers } 45703036ec7SBrian Somers if (ccp->out.state != NULL) { 45803036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 45903036ec7SBrian Somers ccp->out.state = NULL; 4608d9b9867SBrian Somers ccp->out.algorithm = -1; 4617308ec68SBrian Somers } 4628d9b9867SBrian Somers ccp->his_reject = ccp->my_reject = 0; 463ba081e43SBrian Somers 464ba081e43SBrian Somers while (ccp->out.opt) { 465ba081e43SBrian Somers next = ccp->out.opt->next; 466ba081e43SBrian Somers free(ccp->out.opt); 467ba081e43SBrian Somers ccp->out.opt = next; 468ba081e43SBrian Somers } 469897f9429SBrian Somers ccp_Setup(ccp); 470af57ed9fSAtsushi Murai } 471af57ed9fSAtsushi Murai 472af57ed9fSAtsushi Murai static void 473897f9429SBrian Somers CcpLayerFinish(struct fsm *fp) 474af57ed9fSAtsushi Murai { 475897f9429SBrian Somers /* We're now down */ 476e1e8b15eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 477e1e8b15eSBrian Somers struct ccp_opt *next; 478e1e8b15eSBrian Somers 4793a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 480e1e8b15eSBrian Somers 481e1e8b15eSBrian Somers /* 482e1e8b15eSBrian Somers * Nuke options that may be left over from sending a REQ but never 483e1e8b15eSBrian Somers * coming up. 484e1e8b15eSBrian Somers */ 485e1e8b15eSBrian Somers while (ccp->out.opt) { 486e1e8b15eSBrian Somers next = ccp->out.opt->next; 487e1e8b15eSBrian Somers free(ccp->out.opt); 488e1e8b15eSBrian Somers ccp->out.opt = next; 489e1e8b15eSBrian Somers } 4906cf6ee76SBrian Somers 4916cf6ee76SBrian Somers if (ccp_Required(ccp)) { 4926cf6ee76SBrian Somers if (fp->link->lcp.fsm.state == ST_OPENED) 4936cf6ee76SBrian Somers log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name); 4946cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 4956cf6ee76SBrian Somers } 496af57ed9fSAtsushi Murai } 497af57ed9fSAtsushi Murai 4983377c28cSBrian Somers /* Called when CCP has reached the OPEN state */ 4996f384573SBrian Somers static int 500944f7098SBrian Somers CcpLayerUp(struct fsm *fp) 501af57ed9fSAtsushi Murai { 5027308ec68SBrian Somers /* We're now up */ 503aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 504e1e8b15eSBrian Somers struct ccp_opt **o; 505057f1760SBrian Somers unsigned f, fail; 5066301d506SBrian Somers 5076301d506SBrian Somers for (f = fail = 0; f < NALGORITHMS; f++) 5086301d506SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 5096301d506SBrian Somers (*algorithm[f]->Required)(&ccp->fsm) && 510057f1760SBrian Somers (ccp->in.algorithm != (int)f || ccp->out.algorithm != (int)f)) { 5116301d506SBrian Somers /* Blow it all away - we haven't negotiated a required algorithm */ 5126301d506SBrian Somers log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n", 5136301d506SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 5146301d506SBrian Somers fail = 1; 5156301d506SBrian Somers } 5166301d506SBrian Somers 5176301d506SBrian Somers if (fail) { 5186301d506SBrian Somers ccp->his_proto = ccp->my_proto = -1; 5196301d506SBrian Somers fsm_Close(fp); 5206301d506SBrian Somers fsm_Close(&fp->link->lcp.fsm); 5216301d506SBrian Somers return 0; 5226301d506SBrian Somers } 523479508cfSBrian Somers 5243a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 525479508cfSBrian Somers 52603036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 527057f1760SBrian Somers ccp->in.algorithm < (int)NALGORITHMS) { 5288fb5ef5aSBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init) 5298fb5ef5aSBrian Somers (fp->bundle, &ccp->in.opt); 53003036ec7SBrian Somers if (ccp->in.state == NULL) { 531dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 532d47dceb8SBrian Somers fp->link->name, protoname(ccp->his_proto)); 53383d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 534dd7e2610SBrian Somers fsm_Close(fp); 535479508cfSBrian Somers return 0; 53679d1bdaeSBrian Somers } 537af57ed9fSAtsushi Murai } 538af57ed9fSAtsushi Murai 539e1e8b15eSBrian Somers o = &ccp->out.opt; 540057f1760SBrian Somers if (ccp->out.algorithm > 0) 541057f1760SBrian Somers for (f = 0; f < (unsigned)ccp->out.algorithm; f++) 542e1e8b15eSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 543e1e8b15eSBrian Somers o = &(*o)->next; 544e1e8b15eSBrian Somers 54503036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 546057f1760SBrian Somers ccp->out.algorithm < (int)NALGORITHMS) { 5478fb5ef5aSBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 5488fb5ef5aSBrian Somers (fp->bundle, &(*o)->val); 54903036ec7SBrian Somers if (ccp->out.state == NULL) { 550dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 551d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto)); 55283d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 553dd7e2610SBrian Somers fsm_Close(fp); 554479508cfSBrian Somers return 0; 555247ab36dSBrian Somers } 556af57ed9fSAtsushi Murai } 557af57ed9fSAtsushi Murai 558479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 559479508cfSBrian Somers 560dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 561d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 56283d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 563479508cfSBrian Somers 5646f384573SBrian Somers return 1; 565af57ed9fSAtsushi Murai } 566af57ed9fSAtsushi Murai 567af57ed9fSAtsushi Murai static void 568ff360cc9SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 56930c2f2ffSBrian Somers struct fsm_decode *dec) 570af57ed9fSAtsushi Murai { 5717308ec68SBrian Somers /* Deal with incoming data */ 572aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 573ff360cc9SBrian Somers int f; 574ff360cc9SBrian Somers const char *disp; 575ff360cc9SBrian Somers struct fsm_opt *opt; 576af57ed9fSAtsushi Murai 57731516407SBrian Somers if (mode_type == MODE_REQ) 57831516407SBrian Somers ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 57931516407SBrian Somers 580057f1760SBrian Somers while (end >= cp + sizeof(opt->hdr)) { 581ff360cc9SBrian Somers if ((opt = fsm_readopt(&cp)) == NULL) 582d47dceb8SBrian Somers break; 583af57ed9fSAtsushi Murai 5840053cc58SBrian Somers for (f = NALGORITHMS-1; f > -1; f--) 585ff360cc9SBrian Somers if (algorithm[f]->id == opt->hdr.id) 5860053cc58SBrian Somers break; 587af57ed9fSAtsushi Murai 588ff360cc9SBrian Somers disp = f == -1 ? "" : (*algorithm[f]->Disp)(opt); 589ff360cc9SBrian Somers if (disp == NULL) 590ff360cc9SBrian Somers disp = ""; 59103036ec7SBrian Somers 592ff360cc9SBrian Somers log_Printf(LogCCP, " %s[%d] %s\n", protoname(opt->hdr.id), 593ff360cc9SBrian Somers opt->hdr.len, disp); 59403036ec7SBrian Somers 5950053cc58SBrian Somers if (f == -1) { 5960053cc58SBrian Somers /* Don't understand that :-( */ 5970053cc58SBrian Somers if (mode_type == MODE_REQ) { 598ff360cc9SBrian Somers ccp->my_reject |= (1 << opt->hdr.id); 599ff360cc9SBrian Somers fsm_rej(dec, opt); 6000053cc58SBrian Somers } 6010053cc58SBrian Somers } else { 60203036ec7SBrian Somers struct ccp_opt *o; 6030053cc58SBrian Somers 6049780ef31SBrian Somers switch (mode_type) { 605af57ed9fSAtsushi Murai case MODE_REQ: 6061342caedSBrian Somers if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 6077f89db65SBrian Somers (*algorithm[f]->Usable)(fp) && 6081342caedSBrian Somers ccp->in.algorithm == -1) { 609ff360cc9SBrian Somers memcpy(&ccp->in.opt, opt, opt->hdr.len); 6108fb5ef5aSBrian Somers switch ((*algorithm[f]->i.Set)(fp->bundle, &ccp->in.opt, &ccp->cfg)) { 6110053cc58SBrian Somers case MODE_REJ: 612ff360cc9SBrian Somers fsm_rej(dec, &ccp->in.opt); 6130053cc58SBrian Somers break; 6140053cc58SBrian Somers case MODE_NAK: 615ff360cc9SBrian Somers fsm_nak(dec, &ccp->in.opt); 6160053cc58SBrian Somers break; 6170053cc58SBrian Somers case MODE_ACK: 618ff360cc9SBrian Somers fsm_ack(dec, &ccp->in.opt); 619ff360cc9SBrian Somers ccp->his_proto = opt->hdr.id; 620057f1760SBrian Somers ccp->in.algorithm = (int)f; /* This one'll do :-) */ 6210053cc58SBrian Somers break; 6220053cc58SBrian Somers } 623af57ed9fSAtsushi Murai } else { 624ff360cc9SBrian Somers fsm_rej(dec, opt); 625af57ed9fSAtsushi Murai } 626af57ed9fSAtsushi Murai break; 627af57ed9fSAtsushi Murai case MODE_NAK: 62803036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 629ff360cc9SBrian Somers if (o->val.hdr.id == opt->hdr.id) 63003036ec7SBrian Somers break; 63103036ec7SBrian Somers if (o == NULL) 6329b996792SBrian Somers log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" 6339b996792SBrian Somers " option\n", fp->link->name); 6340053cc58SBrian Somers else { 635ff360cc9SBrian Somers memcpy(&o->val, opt, opt->hdr.len); 6368fb5ef5aSBrian Somers if ((*algorithm[f]->o.Set)(fp->bundle, &o->val, &ccp->cfg) == 6378fb5ef5aSBrian Somers MODE_ACK) 63883d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 6391ae349f5Scvs2svn else { 640ff360cc9SBrian Somers ccp->his_reject |= (1 << opt->hdr.id); 64183d1af55SBrian Somers ccp->my_proto = -1; 6426cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6436cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Cannot understand peers (required)" 6446cf6ee76SBrian Somers " %s negotiation\n", fp->link->name, 6456cf6ee76SBrian Somers protoname(algorithm[f]->id)); 6466cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6476cf6ee76SBrian Somers } 6481ae349f5Scvs2svn } 6490053cc58SBrian Somers } 6500053cc58SBrian Somers break; 651af57ed9fSAtsushi Murai case MODE_REJ: 652ff360cc9SBrian Somers ccp->his_reject |= (1 << opt->hdr.id); 65383d1af55SBrian Somers ccp->my_proto = -1; 6546cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6556cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n", 6566cf6ee76SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 6576cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6586cf6ee76SBrian Somers } 659af57ed9fSAtsushi Murai break; 660af57ed9fSAtsushi Murai } 661af57ed9fSAtsushi Murai } 662af57ed9fSAtsushi Murai } 6630053cc58SBrian Somers 664e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 665ff360cc9SBrian Somers fsm_opt_normalise(dec); 666ff360cc9SBrian Somers if (dec->rejend != dec->rej || dec->nakend != dec->nak) { 66703036ec7SBrian Somers if (ccp->in.state == NULL) { 66803036ec7SBrian Somers ccp->his_proto = -1; 66903036ec7SBrian Somers ccp->in.algorithm = -1; 670247ab36dSBrian Somers } 6711ae349f5Scvs2svn } 6720053cc58SBrian Somers } 673af57ed9fSAtsushi Murai } 674af57ed9fSAtsushi Murai 6755d9e6103SBrian Somers extern struct mbuf * 6765d9e6103SBrian Somers ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 677af57ed9fSAtsushi Murai { 6787308ec68SBrian Somers /* Got PROTO_CCP from link */ 67926af0ae9SBrian Somers m_settype(bp, MB_CCPIN); 680455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 6815d9e6103SBrian Somers fsm_Input(&l->ccp.fsm, bp); 682af57ed9fSAtsushi Murai else { 683641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 684dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 6855d9e6103SBrian Somers l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 68626af0ae9SBrian Somers m_freem(bp); 687af57ed9fSAtsushi Murai } 6885d9e6103SBrian Somers return NULL; 689af57ed9fSAtsushi Murai } 6900053cc58SBrian Somers 691503a7782SBrian Somers static void 692503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 6930053cc58SBrian Somers { 6947308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 695f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 696f4768038SBrian Somers 697f4768038SBrian Somers if (ccp->reset_sent != -1) { 698f4768038SBrian Somers if (id != ccp->reset_sent) { 699a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 700d47dceb8SBrian Somers " ignored\n", fp->link->name, id, ccp->reset_sent); 70198baf7c8SBrian Somers return; 70298baf7c8SBrian Somers } 70398baf7c8SBrian Somers /* Whaddaya know - a correct reset ack */ 704f4768038SBrian Somers } else if (id == ccp->last_reset) 705dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 706d47dceb8SBrian Somers fp->link->name); 70798baf7c8SBrian Somers else { 708a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 709d47dceb8SBrian Somers fp->link->name, id); 71098baf7c8SBrian Somers return; 71198baf7c8SBrian Somers } 71298baf7c8SBrian Somers 713f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 714f4768038SBrian Somers ccp->reset_sent = -1; 71503036ec7SBrian Somers if (ccp->in.state != NULL) 71603036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 7170053cc58SBrian Somers } 7180053cc58SBrian Somers 7195d9e6103SBrian Somers static struct mbuf * 720057f1760SBrian Somers ccp_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp, 7215d9e6103SBrian Somers int pri, u_short *proto) 7220053cc58SBrian Somers { 7236cf6ee76SBrian Somers if (PROTO_COMPRESSIBLE(*proto)) { 7246cf6ee76SBrian Somers if (l->ccp.fsm.state != ST_OPENED) { 7256cf6ee76SBrian Somers if (ccp_Required(&l->ccp)) { 7266cf6ee76SBrian Somers /* The NCP layer shouldn't have let this happen ! */ 7276cf6ee76SBrian Somers log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and" 7286cf6ee76SBrian Somers " required CCP layer\n", l->name); 7296cf6ee76SBrian Somers m_freem(bp); 7306cf6ee76SBrian Somers bp = NULL; 7316cf6ee76SBrian Somers } 7326cf6ee76SBrian Somers } else if (l->ccp.out.state != NULL) { 733411675baSBrian Somers bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 7345d9e6103SBrian Somers (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 735411675baSBrian Somers switch (*proto) { 736411675baSBrian Somers case PROTO_ICOMPD: 73726af0ae9SBrian Somers m_settype(bp, MB_ICOMPDOUT); 738411675baSBrian Somers break; 739411675baSBrian Somers case PROTO_COMPD: 74026af0ae9SBrian Somers m_settype(bp, MB_COMPDOUT); 741411675baSBrian Somers break; 742411675baSBrian Somers } 743411675baSBrian Somers } 7446cf6ee76SBrian Somers } 7455d9e6103SBrian Somers 7465d9e6103SBrian Somers return bp; 7470053cc58SBrian Somers } 7480053cc58SBrian Somers 7495d9e6103SBrian Somers static struct mbuf * 750057f1760SBrian Somers ccp_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp, 751057f1760SBrian Somers u_short *proto) 7520053cc58SBrian Somers { 753ee6c193fSBrian Somers /* 754ed32233cSBrian Somers * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 755ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 756ee6c193fSBrian Somers */ 7575d9e6103SBrian Somers if (l->ccp.fsm.state == ST_OPENED) { 758ed32233cSBrian Somers if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 7597308ec68SBrian Somers /* Decompress incoming data */ 7605d9e6103SBrian Somers if (l->ccp.reset_sent != -1) 76198baf7c8SBrian Somers /* Send another REQ and put the packet in the bit bucket */ 762411675baSBrian Somers fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 763411675baSBrian Somers MB_CCPOUT); 764411675baSBrian Somers else if (l->ccp.in.state != NULL) { 765411675baSBrian Somers bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 7665d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, proto, bp); 767411675baSBrian Somers switch (*proto) { 768411675baSBrian Somers case PROTO_ICOMPD: 76926af0ae9SBrian Somers m_settype(bp, MB_ICOMPDIN); 770411675baSBrian Somers break; 771411675baSBrian Somers case PROTO_COMPD: 77226af0ae9SBrian Somers m_settype(bp, MB_COMPDIN); 773411675baSBrian Somers break; 774411675baSBrian Somers } 775411675baSBrian Somers return bp; 776411675baSBrian Somers } 77726af0ae9SBrian Somers m_freem(bp); 778ee6c193fSBrian Somers bp = NULL; 7796815097bSBrian Somers } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 780ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 7815d9e6103SBrian Somers (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 7825d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, *proto, bp); 783e0efa796SBrian Somers } 7840053cc58SBrian Somers } 7850053cc58SBrian Somers 786ee6c193fSBrian Somers return bp; 7871ae349f5Scvs2svn } 788ed32233cSBrian Somers 789ed32233cSBrian Somers u_short 790ed32233cSBrian Somers ccp_Proto(struct ccp *ccp) 7910053cc58SBrian Somers { 792ed32233cSBrian Somers return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 793ed32233cSBrian Somers PROTO_COMPD : PROTO_ICOMPD; 7940053cc58SBrian Somers } 7951df0a3b9SBrian Somers 79606337856SBrian Somers int 7971df0a3b9SBrian Somers ccp_SetOpenMode(struct ccp *ccp) 7981df0a3b9SBrian Somers { 7991df0a3b9SBrian Somers int f; 8001df0a3b9SBrian Somers 8011df0a3b9SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 80206337856SBrian Somers if (IsEnabled(ccp->cfg.neg[f])) { 8031df0a3b9SBrian Somers ccp->fsm.open_mode = 0; 80406337856SBrian Somers return 1; 80506337856SBrian Somers } 8061df0a3b9SBrian Somers 80706337856SBrian Somers ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 80806337856SBrian Somers 80906337856SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 81006337856SBrian Somers if (IsAccepted(ccp->cfg.neg[f])) 81106337856SBrian Somers return 1; 81206337856SBrian Somers 81306337856SBrian Somers return 0; /* No CCP at all */ 8141df0a3b9SBrian Somers } 8155d9e6103SBrian Somers 8167f89db65SBrian Somers int 817057f1760SBrian Somers ccp_DefaultUsable(struct fsm *fp __unused) 8187f89db65SBrian Somers { 8197f89db65SBrian Somers return 1; 8207f89db65SBrian Somers } 8217f89db65SBrian Somers 8226cf6ee76SBrian Somers int 823057f1760SBrian Somers ccp_DefaultRequired(struct fsm *fp __unused) 8246cf6ee76SBrian Somers { 8256cf6ee76SBrian Somers return 0; 8266cf6ee76SBrian Somers } 8276cf6ee76SBrian Somers 8285d9e6103SBrian Somers struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 829