165309e5cSBrian Somers /*- 265309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 365309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 465309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 565309e5cSBrian Somers * All rights reserved. 6af57ed9fSAtsushi Murai * 765309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 865309e5cSBrian Somers * modification, are permitted provided that the following conditions 965309e5cSBrian Somers * are met: 1065309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1165309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1265309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1465309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 15af57ed9fSAtsushi Murai * 1665309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1765309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1865309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1965309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2065309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2165309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2265309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2365309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2465309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2565309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2665309e5cSBrian Somers * SUCH DAMAGE. 27af57ed9fSAtsushi Murai * 2897d92980SPeter Wemm * $FreeBSD$ 29af57ed9fSAtsushi Murai */ 3065309e5cSBrian Somers 31972a1bcfSBrian Somers #include <sys/param.h> 3275240ed1SBrian Somers #include <netinet/in.h> 33eaa4df37SBrian Somers #include <netinet/in_systm.h> 34eaa4df37SBrian Somers #include <netinet/ip.h> 351fa665f5SBrian Somers #include <sys/un.h> 3675240ed1SBrian Somers 3775240ed1SBrian Somers #include <stdio.h> 3803036ec7SBrian Somers #include <stdlib.h> 39eb6e5e05SBrian Somers #include <string.h> /* memcpy() on some archs */ 4085b542cfSBrian Somers #include <termios.h> 4175240ed1SBrian Somers 425d9e6103SBrian Somers #include "layer.h" 43c9e11a11SBrian Somers #include "defs.h" 44b6e82f33SBrian Somers #include "command.h" 4575240ed1SBrian Somers #include "mbuf.h" 4675240ed1SBrian Somers #include "log.h" 4775240ed1SBrian Somers #include "timer.h" 48af57ed9fSAtsushi Murai #include "fsm.h" 495d9e6103SBrian Somers #include "proto.h" 50ed6a16c1SPoul-Henning Kamp #include "pred.h" 510053cc58SBrian Somers #include "deflate.h" 525828db6dSBrian Somers #include "throughput.h" 535828db6dSBrian Somers #include "iplist.h" 54eaa4df37SBrian Somers #include "slcompress.h" 555a72b6edSBrian Somers #include "lqr.h" 565a72b6edSBrian Somers #include "hdlc.h" 571038894eSBrian Somers #include "lcp.h" 581038894eSBrian Somers #include "ccp.h" 595828db6dSBrian Somers #include "ipcp.h" 605ca5389aSBrian Somers #include "filter.h" 6185b542cfSBrian Somers #include "descriptor.h" 6285b542cfSBrian Somers #include "prompt.h" 63503a7782SBrian Somers #include "link.h" 643b0f8d2eSBrian Somers #include "mp.h" 65ed32233cSBrian Somers #include "async.h" 66ed32233cSBrian Somers #include "physical.h" 67972a1bcfSBrian Somers #ifndef NORADIUS 68972a1bcfSBrian Somers #include "radius.h" 69972a1bcfSBrian Somers #endif 70a8d604abSBrian Somers #ifdef HAVE_DES 71a8d604abSBrian Somers #include "mppe.h" 72a8d604abSBrian Somers #endif 733b0f8d2eSBrian Somers #include "bundle.h" 74af57ed9fSAtsushi Murai 75927145beSBrian Somers static void CcpSendConfigReq(struct fsm *); 762267893fSBrian Somers static void CcpSentTerminateReq(struct fsm *); 772267893fSBrian Somers static void CcpSendTerminateAck(struct fsm *, u_char); 7830c2f2ffSBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int, 7930c2f2ffSBrian Somers struct fsm_decode *); 80927145beSBrian Somers static void CcpLayerStart(struct fsm *); 81927145beSBrian Somers static void CcpLayerFinish(struct fsm *); 826f384573SBrian Somers static int CcpLayerUp(struct fsm *); 83927145beSBrian Somers static void CcpLayerDown(struct fsm *); 84479508cfSBrian Somers static void CcpInitRestartCounter(struct fsm *, int); 856cf6ee76SBrian Somers static int CcpRecvResetReq(struct fsm *); 86503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char); 87af57ed9fSAtsushi Murai 8883d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 89af57ed9fSAtsushi Murai CcpLayerUp, 90af57ed9fSAtsushi Murai CcpLayerDown, 91af57ed9fSAtsushi Murai CcpLayerStart, 92af57ed9fSAtsushi Murai CcpLayerFinish, 93af57ed9fSAtsushi Murai CcpInitRestartCounter, 94af57ed9fSAtsushi Murai CcpSendConfigReq, 952267893fSBrian Somers CcpSentTerminateReq, 96af57ed9fSAtsushi Murai CcpSendTerminateAck, 97af57ed9fSAtsushi Murai CcpDecodeConfig, 98503a7782SBrian Somers CcpRecvResetReq, 99503a7782SBrian Somers CcpRecvResetAck 100af57ed9fSAtsushi Murai }; 101af57ed9fSAtsushi Murai 102182c898aSBrian Somers static const char * const ccp_TimerNames[] = 1036f384573SBrian Somers {"CCP restart", "CCP openmode", "CCP stopped"}; 1046f384573SBrian Somers 105d6d3eeabSBrian Somers static const char * 106d6d3eeabSBrian Somers protoname(int proto) 107d6d3eeabSBrian Somers { 108182c898aSBrian Somers static char const * const cftypes[] = { 109d6d3eeabSBrian Somers /* Check out the latest ``Compression Control Protocol'' rfc (1962) */ 1109e836af5SBrian Somers "OUI", /* 0: OUI */ 1119e836af5SBrian Somers "PRED1", /* 1: Predictor type 1 */ 1129e836af5SBrian Somers "PRED2", /* 2: Predictor type 2 */ 1139e836af5SBrian Somers "PUDDLE", /* 3: Puddle Jumber */ 114d6d3eeabSBrian Somers NULL, NULL, NULL, NULL, NULL, NULL, 115d6d3eeabSBrian Somers NULL, NULL, NULL, NULL, NULL, NULL, 1169e836af5SBrian Somers "HWPPC", /* 16: Hewlett-Packard PPC */ 1174bc84b8cSBrian Somers "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 118a8d604abSBrian Somers "MPPE", /* 18: Microsoft PPC (rfc2118) and */ 119a8d604abSBrian Somers /* Microsoft PPE (draft-ietf-pppext-mppe) */ 1204bc84b8cSBrian Somers "GAND", /* 19: Gandalf FZA (rfc1993) */ 121b6e82f33SBrian Somers "V42BIS", /* 20: ARG->DATA.42bis compression */ 1220053cc58SBrian Somers "BSD", /* 21: BSD LZW Compress */ 123d6d3eeabSBrian Somers NULL, 1244bc84b8cSBrian Somers "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 1254bc84b8cSBrian Somers "MAGNALINK/DEFLATE",/* 24: Magnalink Variable Resource (rfc1975) */ 1261342caedSBrian Somers /* 24: Deflate (according to pppd-2.3.*) */ 1274bc84b8cSBrian Somers "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 1284bc84b8cSBrian Somers "DEFLATE", /* 26: Deflate (rfc1979) */ 129af57ed9fSAtsushi Murai }; 130af57ed9fSAtsushi Murai 131d6d3eeabSBrian Somers if (proto < 0 || proto > sizeof cftypes / sizeof *cftypes || 132d6d3eeabSBrian Somers cftypes[proto] == NULL) 133d6d3eeabSBrian Somers return HexStr(proto, NULL, 0); 1349e836af5SBrian Somers 1350053cc58SBrian Somers return cftypes[proto]; 1360053cc58SBrian Somers } 1370053cc58SBrian Somers 1384bc84b8cSBrian Somers /* We support these algorithms, and Req them in the given order */ 139182c898aSBrian Somers static const struct ccp_algorithm * const algorithm[] = { 1404bc84b8cSBrian Somers &DeflateAlgorithm, 1410053cc58SBrian Somers &Pred1Algorithm, 1424bc84b8cSBrian Somers &PppdDeflateAlgorithm 143a8d604abSBrian Somers #ifdef HAVE_DES 144a8d604abSBrian Somers , &MPPEAlgorithm 145a8d604abSBrian Somers #endif 1460053cc58SBrian Somers }; 1470053cc58SBrian Somers 14870ee81ffSBrian Somers #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1490053cc58SBrian Somers 150274e766cSBrian Somers int 151503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg) 152af57ed9fSAtsushi Murai { 1536cf6ee76SBrian Somers struct ccp_opt **o; 154dd0645c5SBrian Somers struct link *l; 155dd0645c5SBrian Somers struct ccp *ccp; 1566cf6ee76SBrian Somers int f; 157dd0645c5SBrian Somers 1583a2e4f62SBrian Somers l = command_ChooseLink(arg); 159dd0645c5SBrian Somers ccp = &l->ccp; 160503a7782SBrian Somers 161b6217683SBrian Somers prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 1621e991daaSBrian Somers State2Nam(ccp->fsm.state)); 1635d9e6103SBrian Somers if (ccp->fsm.state == ST_OPENED) { 164b6217683SBrian Somers prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 165503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 166b6217683SBrian Somers prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 167503a7782SBrian Somers ccp->uncompout, ccp->compout, 168503a7782SBrian Somers ccp->compin, ccp->uncompin); 1695d9e6103SBrian Somers } 170cd9647a1SBrian Somers 1716cf6ee76SBrian Somers if (ccp->in.algorithm != -1) 1726cf6ee76SBrian Somers prompt_Printf(arg->prompt, "\n Input Options: %s\n", 1736cf6ee76SBrian Somers (*algorithm[ccp->in.algorithm]->Disp)(&ccp->in.opt)); 1746cf6ee76SBrian Somers 1756cf6ee76SBrian Somers if (ccp->out.algorithm != -1) { 1766cf6ee76SBrian Somers o = &ccp->out.opt; 1776cf6ee76SBrian Somers for (f = 0; f < ccp->out.algorithm; f++) 1786cf6ee76SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 1796cf6ee76SBrian Somers o = &(*o)->next; 1806cf6ee76SBrian Somers prompt_Printf(arg->prompt, " Output Options: %s\n", 1816cf6ee76SBrian Somers (*algorithm[ccp->out.algorithm]->Disp)(&(*o)->val)); 1826cf6ee76SBrian Somers } 1836cf6ee76SBrian Somers 184b6217683SBrian Somers prompt_Printf(arg->prompt, "\n Defaults: "); 185479508cfSBrian Somers prompt_Printf(arg->prompt, "FSM retry = %us, max %u Config" 186479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ccp->cfg.fsm.timeout, 187479508cfSBrian Somers ccp->cfg.fsm.maxreq, ccp->cfg.fsm.maxreq == 1 ? "" : "s", 188479508cfSBrian Somers ccp->cfg.fsm.maxtrm, ccp->cfg.fsm.maxtrm == 1 ? "" : "s"); 189b6217683SBrian Somers prompt_Printf(arg->prompt, " deflate windows: "); 190b6217683SBrian Somers prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 191b6217683SBrian Somers prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 1926cf6ee76SBrian Somers #ifdef HAVE_DES 1936cf6ee76SBrian Somers prompt_Printf(arg->prompt, " MPPE: "); 1946cf6ee76SBrian Somers if (ccp->cfg.mppe.keybits) 1956cf6ee76SBrian Somers prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits); 1966cf6ee76SBrian Somers else 1976cf6ee76SBrian Somers prompt_Printf(arg->prompt, "any bits, "); 1986cf6ee76SBrian Somers switch (ccp->cfg.mppe.state) { 1996cf6ee76SBrian Somers case MPPE_STATEFUL: 2006cf6ee76SBrian Somers prompt_Printf(arg->prompt, "statefull"); 2016cf6ee76SBrian Somers break; 2026cf6ee76SBrian Somers case MPPE_STATELESS: 2036cf6ee76SBrian Somers prompt_Printf(arg->prompt, "stateless"); 2046cf6ee76SBrian Somers break; 2056cf6ee76SBrian Somers case MPPE_ANYSTATE: 2066cf6ee76SBrian Somers prompt_Printf(arg->prompt, "any state"); 2076cf6ee76SBrian Somers break; 2086cf6ee76SBrian Somers } 2096cf6ee76SBrian Somers prompt_Printf(arg->prompt, "%s\n", 2106cf6ee76SBrian Somers ccp->cfg.mppe.required ? ", required" : ""); 2116cf6ee76SBrian Somers #endif 2126cf6ee76SBrian Somers 2136cf6ee76SBrian Somers prompt_Printf(arg->prompt, "\n DEFLATE: %s\n", 2141342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); 2151342caedSBrian Somers prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", 2161342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); 2171342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE24: %s\n", 2181342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); 219a8d604abSBrian Somers #ifdef HAVE_DES 2206cf6ee76SBrian Somers prompt_Printf(arg->prompt, " MPPE: %s\n", 221a8d604abSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE])); 222a8d604abSBrian Somers #endif 223274e766cSBrian Somers return 0; 224af57ed9fSAtsushi Murai } 225af57ed9fSAtsushi Murai 2261ae349f5Scvs2svn void 2276f384573SBrian Somers ccp_SetupCallbacks(struct ccp *ccp) 228af57ed9fSAtsushi Murai { 2296f384573SBrian Somers ccp->fsm.fn = &ccp_Callbacks; 2306f384573SBrian Somers ccp->fsm.FsmTimer.name = ccp_TimerNames[0]; 2316f384573SBrian Somers ccp->fsm.OpenTimer.name = ccp_TimerNames[1]; 2326f384573SBrian Somers ccp->fsm.StoppedTimer.name = ccp_TimerNames[2]; 233ea661041SBrian Somers } 234ea661041SBrian Somers 235ea661041SBrian Somers void 2366d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 2376d666775SBrian Somers const struct fsm_parent *parent) 238ea661041SBrian Somers { 2397308ec68SBrian Somers /* Initialise ourselves */ 2403b0f8d2eSBrian Somers 241479508cfSBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, LogCCP, 2426f384573SBrian Somers bundle, l, parent, &ccp_Callbacks, ccp_TimerNames); 243cd9647a1SBrian Somers 24403036ec7SBrian Somers ccp->cfg.deflate.in.winsize = 0; 24503036ec7SBrian Somers ccp->cfg.deflate.out.winsize = 15; 246479508cfSBrian Somers ccp->cfg.fsm.timeout = DEF_FSMRETRY; 247479508cfSBrian Somers ccp->cfg.fsm.maxreq = DEF_FSMTRIES; 248479508cfSBrian Somers ccp->cfg.fsm.maxtrm = DEF_FSMTRIES; 2491342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; 2501342caedSBrian Somers ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; 2511342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; 252a8d604abSBrian Somers #ifdef HAVE_DES 2536cf6ee76SBrian Somers ccp->cfg.mppe.keybits = 0; 2546cf6ee76SBrian Somers ccp->cfg.mppe.state = MPPE_ANYSTATE; 2556cf6ee76SBrian Somers ccp->cfg.mppe.required = 0; 256385167a6SBrian Somers ccp->cfg.neg[CCP_NEG_MPPE] = NEG_ENABLED|NEG_ACCEPTED; 257a8d604abSBrian Somers #endif 258cd9647a1SBrian Somers 259503a7782SBrian Somers ccp_Setup(ccp); 260503a7782SBrian Somers } 261503a7782SBrian Somers 262503a7782SBrian Somers void 263503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 264503a7782SBrian Somers { 265503a7782SBrian Somers /* Set ourselves up for a startup */ 266503a7782SBrian Somers ccp->fsm.open_mode = 0; 267503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 268503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 26903036ec7SBrian Somers ccp->in.algorithm = ccp->out.algorithm = -1; 27003036ec7SBrian Somers ccp->in.state = ccp->out.state = NULL; 27103036ec7SBrian Somers ccp->in.opt.id = -1; 27203036ec7SBrian Somers ccp->out.opt = NULL; 273503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 274503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 275503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 276af57ed9fSAtsushi Murai } 277af57ed9fSAtsushi Murai 2786cf6ee76SBrian Somers /* 2796cf6ee76SBrian Somers * Is ccp *REQUIRED* ? 2806cf6ee76SBrian Somers * We ask each of the configured ccp protocols if they're required and 2816cf6ee76SBrian Somers * return TRUE if they are. 2826cf6ee76SBrian Somers * 2836cf6ee76SBrian Somers * It's not possible for the peer to reject a required ccp protocol 2846cf6ee76SBrian Somers * without our state machine bringing the supporting lcp layer down. 2856cf6ee76SBrian Somers * 2866cf6ee76SBrian Somers * If ccp is required but not open, the NCP layer should not push 2876cf6ee76SBrian Somers * any data into the link. 2886cf6ee76SBrian Somers */ 2896cf6ee76SBrian Somers int 2906cf6ee76SBrian Somers ccp_Required(struct ccp *ccp) 2916cf6ee76SBrian Somers { 2926cf6ee76SBrian Somers int f; 2936cf6ee76SBrian Somers 2946cf6ee76SBrian Somers for (f = 0; f < NALGORITHMS; f++) 2956cf6ee76SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 2966cf6ee76SBrian Somers (*algorithm[f]->Required)(&ccp->fsm)) 2976cf6ee76SBrian Somers return 1; 2986cf6ee76SBrian Somers 2996cf6ee76SBrian Somers return 0; 3006cf6ee76SBrian Somers } 3016cf6ee76SBrian Somers 3026301d506SBrian Somers /* 3036301d506SBrian Somers * Report whether it's possible to increase a packet's size after 3046301d506SBrian Somers * compression (and by how much). 3056301d506SBrian Somers */ 3066301d506SBrian Somers int 3076301d506SBrian Somers ccp_MTUOverhead(struct ccp *ccp) 3086301d506SBrian Somers { 3096301d506SBrian Somers if (ccp->fsm.state == ST_OPENED) 3106301d506SBrian Somers return algorithm[ccp->out.algorithm]->o.MTUOverhead; 3116301d506SBrian Somers 3126301d506SBrian Somers return 0; 3136301d506SBrian Somers } 3146301d506SBrian Somers 315af57ed9fSAtsushi Murai static void 316479508cfSBrian Somers CcpInitRestartCounter(struct fsm *fp, int what) 317af57ed9fSAtsushi Murai { 3187308ec68SBrian Somers /* Set fsm timer load */ 319cd9647a1SBrian Somers struct ccp *ccp = fsm2ccp(fp); 320cd9647a1SBrian Somers 321479508cfSBrian Somers fp->FsmTimer.load = ccp->cfg.fsm.timeout * SECTICKS; 322479508cfSBrian Somers switch (what) { 323479508cfSBrian Somers case FSM_REQ_TIMER: 324479508cfSBrian Somers fp->restart = ccp->cfg.fsm.maxreq; 325479508cfSBrian Somers break; 326479508cfSBrian Somers case FSM_TRM_TIMER: 327479508cfSBrian Somers fp->restart = ccp->cfg.fsm.maxtrm; 328479508cfSBrian Somers break; 329479508cfSBrian Somers default: 330479508cfSBrian Somers fp->restart = 1; 331479508cfSBrian Somers break; 332479508cfSBrian Somers } 333af57ed9fSAtsushi Murai } 334af57ed9fSAtsushi Murai 335af57ed9fSAtsushi Murai static void 336944f7098SBrian Somers CcpSendConfigReq(struct fsm *fp) 337af57ed9fSAtsushi Murai { 3387308ec68SBrian Somers /* Send config REQ please */ 339aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 34003036ec7SBrian Somers struct ccp_opt **o; 34130c2f2ffSBrian Somers u_char *cp, buff[100]; 34203036ec7SBrian Somers int f, alloc; 343af57ed9fSAtsushi Murai 34430c2f2ffSBrian Somers cp = buff; 34503036ec7SBrian Somers o = &ccp->out.opt; 34603036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 34783d1af55SBrian Somers ccp->my_proto = -1; 34803036ec7SBrian Somers ccp->out.algorithm = -1; 3490053cc58SBrian Somers for (f = 0; f < NALGORITHMS; f++) 3501342caedSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 3517f89db65SBrian Somers !REJECTED(ccp, algorithm[f]->id) && 3527f89db65SBrian Somers (*algorithm[f]->Usable)(fp)) { 3530053cc58SBrian Somers 354ba081e43SBrian Somers if (!alloc) 355ba081e43SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 356ba081e43SBrian Somers if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 357ba081e43SBrian Somers break; 358ba081e43SBrian Somers 359ba081e43SBrian Somers if (alloc || *o == NULL) { 36003036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 36103036ec7SBrian Somers (*o)->val.id = algorithm[f]->id; 36203036ec7SBrian Somers (*o)->val.len = 2; 36303036ec7SBrian Somers (*o)->next = NULL; 36403036ec7SBrian Somers (*o)->algorithm = f; 36503036ec7SBrian Somers (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 366af57ed9fSAtsushi Murai } 3671ae349f5Scvs2svn 36803036ec7SBrian Somers if (cp + (*o)->val.len > buff + sizeof buff) { 369dd7e2610SBrian Somers log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 37030c2f2ffSBrian Somers break; 37130c2f2ffSBrian Somers } 3722267893fSBrian Somers memcpy(cp, &(*o)->val, (*o)->val.len); 3732267893fSBrian Somers cp += (*o)->val.len; 37403036ec7SBrian Somers 37503036ec7SBrian Somers ccp->my_proto = (*o)->val.id; 37603036ec7SBrian Somers ccp->out.algorithm = f; 37703036ec7SBrian Somers 37803036ec7SBrian Somers if (alloc) 37903036ec7SBrian Somers o = &(*o)->next; 3801ae349f5Scvs2svn } 3812267893fSBrian Somers 382411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT); 383af57ed9fSAtsushi Murai } 384af57ed9fSAtsushi Murai 385af57ed9fSAtsushi Murai void 386dd7e2610SBrian Somers ccp_SendResetReq(struct fsm *fp) 387af57ed9fSAtsushi Murai { 3887308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 389aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3902267893fSBrian Somers 39183d1af55SBrian Somers ccp->reset_sent = fp->reqid; 39283d1af55SBrian Somers ccp->last_reset = -1; 393411675baSBrian Somers fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT); 394af57ed9fSAtsushi Murai } 395af57ed9fSAtsushi Murai 396af57ed9fSAtsushi Murai static void 3972267893fSBrian Somers CcpSentTerminateReq(struct fsm *fp) 398af57ed9fSAtsushi Murai { 3997308ec68SBrian Somers /* Term REQ just sent by FSM */ 400af57ed9fSAtsushi Murai } 401af57ed9fSAtsushi Murai 402af57ed9fSAtsushi Murai static void 4032267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 404af57ed9fSAtsushi Murai { 4057308ec68SBrian Somers /* Send Term ACK please */ 406411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); 407af57ed9fSAtsushi Murai } 408af57ed9fSAtsushi Murai 4096cf6ee76SBrian Somers static int 410944f7098SBrian Somers CcpRecvResetReq(struct fsm *fp) 411af57ed9fSAtsushi Murai { 4127308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 413aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 4146cf6ee76SBrian Somers if (ccp->out.state == NULL) 4156cf6ee76SBrian Somers return 1; 4166cf6ee76SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 417af57ed9fSAtsushi Murai } 418af57ed9fSAtsushi Murai 419af57ed9fSAtsushi Murai static void 420944f7098SBrian Somers CcpLayerStart(struct fsm *fp) 421af57ed9fSAtsushi Murai { 4227308ec68SBrian Somers /* We're about to start up ! */ 423479508cfSBrian Somers struct ccp *ccp = fsm2ccp(fp); 424479508cfSBrian Somers 4253a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name); 426479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 427af57ed9fSAtsushi Murai } 428af57ed9fSAtsushi Murai 429af57ed9fSAtsushi Murai static void 430897f9429SBrian Somers CcpLayerDown(struct fsm *fp) 431af57ed9fSAtsushi Murai { 432897f9429SBrian Somers /* About to come down */ 433aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 434ba081e43SBrian Somers struct ccp_opt *next; 435ba081e43SBrian Somers 4363a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name); 43703036ec7SBrian Somers if (ccp->in.state != NULL) { 43803036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 43903036ec7SBrian Somers ccp->in.state = NULL; 4408d9b9867SBrian Somers ccp->in.algorithm = -1; 4417308ec68SBrian Somers } 44203036ec7SBrian Somers if (ccp->out.state != NULL) { 44303036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 44403036ec7SBrian Somers ccp->out.state = NULL; 4458d9b9867SBrian Somers ccp->out.algorithm = -1; 4467308ec68SBrian Somers } 4478d9b9867SBrian Somers ccp->his_reject = ccp->my_reject = 0; 448ba081e43SBrian Somers 449ba081e43SBrian Somers while (ccp->out.opt) { 450ba081e43SBrian Somers next = ccp->out.opt->next; 451ba081e43SBrian Somers free(ccp->out.opt); 452ba081e43SBrian Somers ccp->out.opt = next; 453ba081e43SBrian Somers } 454897f9429SBrian Somers ccp_Setup(ccp); 455af57ed9fSAtsushi Murai } 456af57ed9fSAtsushi Murai 457af57ed9fSAtsushi Murai static void 458897f9429SBrian Somers CcpLayerFinish(struct fsm *fp) 459af57ed9fSAtsushi Murai { 460897f9429SBrian Somers /* We're now down */ 461e1e8b15eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 462e1e8b15eSBrian Somers struct ccp_opt *next; 463e1e8b15eSBrian Somers 4643a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 465e1e8b15eSBrian Somers 466e1e8b15eSBrian Somers /* 467e1e8b15eSBrian Somers * Nuke options that may be left over from sending a REQ but never 468e1e8b15eSBrian Somers * coming up. 469e1e8b15eSBrian Somers */ 470e1e8b15eSBrian Somers while (ccp->out.opt) { 471e1e8b15eSBrian Somers next = ccp->out.opt->next; 472e1e8b15eSBrian Somers free(ccp->out.opt); 473e1e8b15eSBrian Somers ccp->out.opt = next; 474e1e8b15eSBrian Somers } 4756cf6ee76SBrian Somers 4766cf6ee76SBrian Somers if (ccp_Required(ccp)) { 4776cf6ee76SBrian Somers if (fp->link->lcp.fsm.state == ST_OPENED) 4786cf6ee76SBrian Somers log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name); 4796cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 4806cf6ee76SBrian Somers } 481af57ed9fSAtsushi Murai } 482af57ed9fSAtsushi Murai 4833377c28cSBrian Somers /* Called when CCP has reached the OPEN state */ 4846f384573SBrian Somers static int 485944f7098SBrian Somers CcpLayerUp(struct fsm *fp) 486af57ed9fSAtsushi Murai { 4877308ec68SBrian Somers /* We're now up */ 488aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 489e1e8b15eSBrian Somers struct ccp_opt **o; 4906301d506SBrian Somers int f, fail; 4916301d506SBrian Somers 4926301d506SBrian Somers for (f = fail = 0; f < NALGORITHMS; f++) 4936301d506SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 4946301d506SBrian Somers (*algorithm[f]->Required)(&ccp->fsm) && 4956301d506SBrian Somers (ccp->in.algorithm != f || ccp->out.algorithm != f)) { 4966301d506SBrian Somers /* Blow it all away - we haven't negotiated a required algorithm */ 4976301d506SBrian Somers log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n", 4986301d506SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 4996301d506SBrian Somers fail = 1; 5006301d506SBrian Somers } 5016301d506SBrian Somers 5026301d506SBrian Somers if (fail) { 5036301d506SBrian Somers ccp->his_proto = ccp->my_proto = -1; 5046301d506SBrian Somers fsm_Close(fp); 5056301d506SBrian Somers fsm_Close(&fp->link->lcp.fsm); 5066301d506SBrian Somers return 0; 5076301d506SBrian Somers } 508479508cfSBrian Somers 5093a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 510479508cfSBrian Somers 51103036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 51203036ec7SBrian Somers ccp->in.algorithm < NALGORITHMS) { 51303036ec7SBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 51403036ec7SBrian Somers if (ccp->in.state == NULL) { 515dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 516d47dceb8SBrian Somers fp->link->name, protoname(ccp->his_proto)); 51783d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 518dd7e2610SBrian Somers fsm_Close(fp); 519479508cfSBrian Somers return 0; 52079d1bdaeSBrian Somers } 521af57ed9fSAtsushi Murai } 522af57ed9fSAtsushi Murai 523e1e8b15eSBrian Somers o = &ccp->out.opt; 524e1e8b15eSBrian Somers for (f = 0; f < ccp->out.algorithm; f++) 525e1e8b15eSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 526e1e8b15eSBrian Somers o = &(*o)->next; 527e1e8b15eSBrian Somers 52803036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 52903036ec7SBrian Somers ccp->out.algorithm < NALGORITHMS) { 530e1e8b15eSBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)(&(*o)->val); 53103036ec7SBrian Somers if (ccp->out.state == NULL) { 532dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 533d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto)); 53483d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 535dd7e2610SBrian Somers fsm_Close(fp); 536479508cfSBrian Somers return 0; 537247ab36dSBrian Somers } 538af57ed9fSAtsushi Murai } 539af57ed9fSAtsushi Murai 540479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 541479508cfSBrian Somers 542dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 543d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 54483d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 545479508cfSBrian Somers 5466f384573SBrian Somers return 1; 547af57ed9fSAtsushi Murai } 548af57ed9fSAtsushi Murai 549af57ed9fSAtsushi Murai static void 55030c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 55130c2f2ffSBrian Somers struct fsm_decode *dec) 552af57ed9fSAtsushi Murai { 5537308ec68SBrian Somers /* Deal with incoming data */ 554aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 55531516407SBrian Somers int type, length, f; 55603036ec7SBrian Somers const char *end; 557af57ed9fSAtsushi Murai 55831516407SBrian Somers if (mode_type == MODE_REQ) 55931516407SBrian Somers ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 56031516407SBrian Somers 561af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 562af57ed9fSAtsushi Murai type = *cp; 563af57ed9fSAtsushi Murai length = cp[1]; 56403036ec7SBrian Somers 565d47dceb8SBrian Somers if (length == 0) { 566dd7e2610SBrian Somers log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name); 567d47dceb8SBrian Somers break; 568d47dceb8SBrian Somers } 569d47dceb8SBrian Somers 57003036ec7SBrian Somers if (length > sizeof(struct lcp_opt)) { 57103036ec7SBrian Somers length = sizeof(struct lcp_opt); 572dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n", 573d47dceb8SBrian Somers fp->link->name, length); 57403036ec7SBrian Somers } 575af57ed9fSAtsushi Murai 5760053cc58SBrian Somers for (f = NALGORITHMS-1; f > -1; f--) 5770053cc58SBrian Somers if (algorithm[f]->id == type) 5780053cc58SBrian Somers break; 579af57ed9fSAtsushi Murai 58003036ec7SBrian Somers end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 58103036ec7SBrian Somers if (end == NULL) 58203036ec7SBrian Somers end = ""; 58303036ec7SBrian Somers 584d6d3eeabSBrian Somers log_Printf(LogCCP, " %s[%d] %s\n", protoname(type), length, end); 58503036ec7SBrian Somers 5860053cc58SBrian Somers if (f == -1) { 5870053cc58SBrian Somers /* Don't understand that :-( */ 5880053cc58SBrian Somers if (mode_type == MODE_REQ) { 58983d1af55SBrian Somers ccp->my_reject |= (1 << type); 59030c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 59130c2f2ffSBrian Somers dec->rejend += length; 5920053cc58SBrian Somers } 5930053cc58SBrian Somers } else { 59403036ec7SBrian Somers struct ccp_opt *o; 5950053cc58SBrian Somers 5969780ef31SBrian Somers switch (mode_type) { 597af57ed9fSAtsushi Murai case MODE_REQ: 5981342caedSBrian Somers if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 5997f89db65SBrian Somers (*algorithm[f]->Usable)(fp) && 6001342caedSBrian Somers ccp->in.algorithm == -1) { 60103036ec7SBrian Somers memcpy(&ccp->in.opt, cp, length); 60203036ec7SBrian Somers switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 6030053cc58SBrian Somers case MODE_REJ: 60403036ec7SBrian Somers memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 60503036ec7SBrian Somers dec->rejend += ccp->in.opt.len; 6060053cc58SBrian Somers break; 6070053cc58SBrian Somers case MODE_NAK: 60803036ec7SBrian Somers memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 60903036ec7SBrian Somers dec->nakend += ccp->in.opt.len; 6100053cc58SBrian Somers break; 6110053cc58SBrian Somers case MODE_ACK: 61230c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 61330c2f2ffSBrian Somers dec->ackend += length; 61483d1af55SBrian Somers ccp->his_proto = type; 61503036ec7SBrian Somers ccp->in.algorithm = f; /* This one'll do :-) */ 6160053cc58SBrian Somers break; 6170053cc58SBrian Somers } 618af57ed9fSAtsushi Murai } else { 61930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 62030c2f2ffSBrian Somers dec->rejend += length; 621af57ed9fSAtsushi Murai } 622af57ed9fSAtsushi Murai break; 623af57ed9fSAtsushi Murai case MODE_NAK: 62403036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 62503036ec7SBrian Somers if (o->val.id == cp[0]) 62603036ec7SBrian Somers break; 62703036ec7SBrian Somers if (o == NULL) 6289b996792SBrian Somers log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" 6299b996792SBrian Somers " option\n", fp->link->name); 6300053cc58SBrian Somers else { 63103036ec7SBrian Somers memcpy(&o->val, cp, length); 6326cf6ee76SBrian Somers if ((*algorithm[f]->o.Set)(&o->val, &ccp->cfg) == MODE_ACK) 63383d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 6341ae349f5Scvs2svn else { 63583d1af55SBrian Somers ccp->his_reject |= (1 << type); 63683d1af55SBrian Somers ccp->my_proto = -1; 6376cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6386cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Cannot understand peers (required)" 6396cf6ee76SBrian Somers " %s negotiation\n", fp->link->name, 6406cf6ee76SBrian Somers protoname(algorithm[f]->id)); 6416cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6426cf6ee76SBrian Somers } 6431ae349f5Scvs2svn } 6440053cc58SBrian Somers } 6450053cc58SBrian Somers break; 646af57ed9fSAtsushi Murai case MODE_REJ: 64783d1af55SBrian Somers ccp->his_reject |= (1 << type); 64883d1af55SBrian Somers ccp->my_proto = -1; 6496cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6506cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n", 6516cf6ee76SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 6526cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6536cf6ee76SBrian Somers } 654af57ed9fSAtsushi Murai break; 655af57ed9fSAtsushi Murai } 656af57ed9fSAtsushi Murai } 6570053cc58SBrian Somers 65803036ec7SBrian Somers plen -= cp[1]; 65903036ec7SBrian Somers cp += cp[1]; 660af57ed9fSAtsushi Murai } 6610053cc58SBrian Somers 662e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 6631342caedSBrian Somers if (dec->rejend != dec->rej) { 66403036ec7SBrian Somers /* rejects are preferred */ 66503036ec7SBrian Somers dec->ackend = dec->ack; 66603036ec7SBrian Somers dec->nakend = dec->nak; 66703036ec7SBrian Somers if (ccp->in.state == NULL) { 66883d1af55SBrian Somers ccp->his_proto = -1; 66903036ec7SBrian Somers ccp->in.algorithm = -1; 67003036ec7SBrian Somers } 6711342caedSBrian Somers } else if (dec->nakend != dec->nak) { 67203036ec7SBrian Somers /* then NAKs */ 67303036ec7SBrian Somers dec->ackend = dec->ack; 67403036ec7SBrian Somers if (ccp->in.state == NULL) { 67503036ec7SBrian Somers ccp->his_proto = -1; 67603036ec7SBrian Somers ccp->in.algorithm = -1; 677247ab36dSBrian Somers } 6781ae349f5Scvs2svn } 6790053cc58SBrian Somers } 680af57ed9fSAtsushi Murai } 681af57ed9fSAtsushi Murai 6825d9e6103SBrian Somers extern struct mbuf * 6835d9e6103SBrian Somers ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 684af57ed9fSAtsushi Murai { 6857308ec68SBrian Somers /* Got PROTO_CCP from link */ 68626af0ae9SBrian Somers m_settype(bp, MB_CCPIN); 687455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 6885d9e6103SBrian Somers fsm_Input(&l->ccp.fsm, bp); 689af57ed9fSAtsushi Murai else { 690641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 691dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 6925d9e6103SBrian Somers l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 69326af0ae9SBrian Somers m_freem(bp); 694af57ed9fSAtsushi Murai } 6955d9e6103SBrian Somers return NULL; 696af57ed9fSAtsushi Murai } 6970053cc58SBrian Somers 698503a7782SBrian Somers static void 699503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 7000053cc58SBrian Somers { 7017308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 702f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 703f4768038SBrian Somers 704f4768038SBrian Somers if (ccp->reset_sent != -1) { 705f4768038SBrian Somers if (id != ccp->reset_sent) { 706a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 707d47dceb8SBrian Somers " ignored\n", fp->link->name, id, ccp->reset_sent); 70898baf7c8SBrian Somers return; 70998baf7c8SBrian Somers } 71098baf7c8SBrian Somers /* Whaddaya know - a correct reset ack */ 711f4768038SBrian Somers } else if (id == ccp->last_reset) 712dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 713d47dceb8SBrian Somers fp->link->name); 71498baf7c8SBrian Somers else { 715a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 716d47dceb8SBrian Somers fp->link->name, id); 71798baf7c8SBrian Somers return; 71898baf7c8SBrian Somers } 71998baf7c8SBrian Somers 720f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 721f4768038SBrian Somers ccp->reset_sent = -1; 72203036ec7SBrian Somers if (ccp->in.state != NULL) 72303036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 7240053cc58SBrian Somers } 7250053cc58SBrian Somers 7265d9e6103SBrian Somers static struct mbuf * 7275d9e6103SBrian Somers ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, 7285d9e6103SBrian Somers int pri, u_short *proto) 7290053cc58SBrian Somers { 7306cf6ee76SBrian Somers if (PROTO_COMPRESSIBLE(*proto)) { 7316cf6ee76SBrian Somers if (l->ccp.fsm.state != ST_OPENED) { 7326cf6ee76SBrian Somers if (ccp_Required(&l->ccp)) { 7336cf6ee76SBrian Somers /* The NCP layer shouldn't have let this happen ! */ 7346cf6ee76SBrian Somers log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and" 7356cf6ee76SBrian Somers " required CCP layer\n", l->name); 7366cf6ee76SBrian Somers m_freem(bp); 7376cf6ee76SBrian Somers bp = NULL; 7386cf6ee76SBrian Somers } 7396cf6ee76SBrian Somers } else if (l->ccp.out.state != NULL) { 740411675baSBrian Somers bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 7415d9e6103SBrian Somers (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 742411675baSBrian Somers switch (*proto) { 743411675baSBrian Somers case PROTO_ICOMPD: 74426af0ae9SBrian Somers m_settype(bp, MB_ICOMPDOUT); 745411675baSBrian Somers break; 746411675baSBrian Somers case PROTO_COMPD: 74726af0ae9SBrian Somers m_settype(bp, MB_COMPDOUT); 748411675baSBrian Somers break; 749411675baSBrian Somers } 750411675baSBrian Somers } 7516cf6ee76SBrian Somers } 7525d9e6103SBrian Somers 7535d9e6103SBrian Somers return bp; 7540053cc58SBrian Somers } 7550053cc58SBrian Somers 7565d9e6103SBrian Somers static struct mbuf * 7575d9e6103SBrian Somers ccp_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto) 7580053cc58SBrian Somers { 759ee6c193fSBrian Somers /* 760ed32233cSBrian Somers * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 761ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 762ee6c193fSBrian Somers */ 7635d9e6103SBrian Somers if (l->ccp.fsm.state == ST_OPENED) { 764ed32233cSBrian Somers if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 7656815097bSBrian Somers log_Printf(LogDEBUG, "ccp_LayerPull: PROTO_%sCOMPDP -> PROTO_IP\n", 7666815097bSBrian Somers *proto == PROTO_ICOMPD ? "I" : ""); 7677308ec68SBrian Somers /* Decompress incoming data */ 7685d9e6103SBrian Somers if (l->ccp.reset_sent != -1) 76998baf7c8SBrian Somers /* Send another REQ and put the packet in the bit bucket */ 770411675baSBrian Somers fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 771411675baSBrian Somers MB_CCPOUT); 772411675baSBrian Somers else if (l->ccp.in.state != NULL) { 773411675baSBrian Somers bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 7745d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, proto, bp); 775411675baSBrian Somers switch (*proto) { 776411675baSBrian Somers case PROTO_ICOMPD: 77726af0ae9SBrian Somers m_settype(bp, MB_ICOMPDIN); 778411675baSBrian Somers break; 779411675baSBrian Somers case PROTO_COMPD: 78026af0ae9SBrian Somers m_settype(bp, MB_COMPDIN); 781411675baSBrian Somers break; 782411675baSBrian Somers } 783411675baSBrian Somers return bp; 784411675baSBrian Somers } 78526af0ae9SBrian Somers m_freem(bp); 786ee6c193fSBrian Somers bp = NULL; 7876815097bSBrian Somers } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 7886815097bSBrian Somers log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet (dict only)\n"); 789ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 7905d9e6103SBrian Somers (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 7915d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, *proto, bp); 7926815097bSBrian Somers } else 7936815097bSBrian Somers log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet\n"); 7940053cc58SBrian Somers } 7950053cc58SBrian Somers 796ee6c193fSBrian Somers return bp; 7971ae349f5Scvs2svn } 798ed32233cSBrian Somers 799ed32233cSBrian Somers u_short 800ed32233cSBrian Somers ccp_Proto(struct ccp *ccp) 8010053cc58SBrian Somers { 802ed32233cSBrian Somers return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 803ed32233cSBrian Somers PROTO_COMPD : PROTO_ICOMPD; 8040053cc58SBrian Somers } 8051df0a3b9SBrian Somers 80606337856SBrian Somers int 8071df0a3b9SBrian Somers ccp_SetOpenMode(struct ccp *ccp) 8081df0a3b9SBrian Somers { 8091df0a3b9SBrian Somers int f; 8101df0a3b9SBrian Somers 8111df0a3b9SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 81206337856SBrian Somers if (IsEnabled(ccp->cfg.neg[f])) { 8131df0a3b9SBrian Somers ccp->fsm.open_mode = 0; 81406337856SBrian Somers return 1; 81506337856SBrian Somers } 8161df0a3b9SBrian Somers 81706337856SBrian Somers ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 81806337856SBrian Somers 81906337856SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 82006337856SBrian Somers if (IsAccepted(ccp->cfg.neg[f])) 82106337856SBrian Somers return 1; 82206337856SBrian Somers 82306337856SBrian Somers return 0; /* No CCP at all */ 8241df0a3b9SBrian Somers } 8255d9e6103SBrian Somers 8267f89db65SBrian Somers int 8276cf6ee76SBrian Somers ccp_DefaultUsable(struct fsm *fp) 8287f89db65SBrian Somers { 8297f89db65SBrian Somers return 1; 8307f89db65SBrian Somers } 8317f89db65SBrian Somers 8326cf6ee76SBrian Somers int 8336cf6ee76SBrian Somers ccp_DefaultRequired(struct fsm *fp) 8346cf6ee76SBrian Somers { 8356cf6ee76SBrian Somers return 0; 8366cf6ee76SBrian Somers } 8376cf6ee76SBrian Somers 8385d9e6103SBrian Somers struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 839