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> 3530949fd4SBrian Somers #include <sys/socket.h> 361fa665f5SBrian Somers #include <sys/un.h> 3775240ed1SBrian Somers 386eafd353SBrian Somers #include <stdarg.h> 3975240ed1SBrian Somers #include <stdio.h> 4003036ec7SBrian Somers #include <stdlib.h> 41eb6e5e05SBrian Somers #include <string.h> /* memcpy() on some archs */ 4285b542cfSBrian Somers #include <termios.h> 4375240ed1SBrian Somers 445d9e6103SBrian Somers #include "layer.h" 45c9e11a11SBrian Somers #include "defs.h" 46b6e82f33SBrian Somers #include "command.h" 4775240ed1SBrian Somers #include "mbuf.h" 4875240ed1SBrian Somers #include "log.h" 4975240ed1SBrian Somers #include "timer.h" 50af57ed9fSAtsushi Murai #include "fsm.h" 515d9e6103SBrian Somers #include "proto.h" 52ed6a16c1SPoul-Henning Kamp #include "pred.h" 530053cc58SBrian Somers #include "deflate.h" 545828db6dSBrian Somers #include "throughput.h" 555828db6dSBrian Somers #include "iplist.h" 56eaa4df37SBrian Somers #include "slcompress.h" 575a72b6edSBrian Somers #include "lqr.h" 585a72b6edSBrian Somers #include "hdlc.h" 591038894eSBrian Somers #include "lcp.h" 601038894eSBrian Somers #include "ccp.h" 6130949fd4SBrian Somers #include "ncpaddr.h" 625828db6dSBrian Somers #include "ipcp.h" 635ca5389aSBrian Somers #include "filter.h" 6485b542cfSBrian Somers #include "descriptor.h" 6585b542cfSBrian Somers #include "prompt.h" 66503a7782SBrian Somers #include "link.h" 673b0f8d2eSBrian Somers #include "mp.h" 68ed32233cSBrian Somers #include "async.h" 69ed32233cSBrian Somers #include "physical.h" 70972a1bcfSBrian Somers #ifndef NORADIUS 71972a1bcfSBrian Somers #include "radius.h" 72972a1bcfSBrian Somers #endif 73fb11a9c2SBrian Somers #ifndef NODES 74a8d604abSBrian Somers #include "mppe.h" 75a8d604abSBrian Somers #endif 7630949fd4SBrian Somers #include "ipv6cp.h" 7730949fd4SBrian Somers #include "ncp.h" 783b0f8d2eSBrian Somers #include "bundle.h" 79af57ed9fSAtsushi Murai 80927145beSBrian Somers static void CcpSendConfigReq(struct fsm *); 812267893fSBrian Somers static void CcpSentTerminateReq(struct fsm *); 822267893fSBrian Somers static void CcpSendTerminateAck(struct fsm *, u_char); 83ff360cc9SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, u_char *, int, 8430c2f2ffSBrian Somers struct fsm_decode *); 85927145beSBrian Somers static void CcpLayerStart(struct fsm *); 86927145beSBrian Somers static void CcpLayerFinish(struct fsm *); 876f384573SBrian Somers static int CcpLayerUp(struct fsm *); 88927145beSBrian Somers static void CcpLayerDown(struct fsm *); 89479508cfSBrian Somers static void CcpInitRestartCounter(struct fsm *, int); 906cf6ee76SBrian Somers static int CcpRecvResetReq(struct fsm *); 91503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char); 92af57ed9fSAtsushi Murai 9383d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = { 94af57ed9fSAtsushi Murai CcpLayerUp, 95af57ed9fSAtsushi Murai CcpLayerDown, 96af57ed9fSAtsushi Murai CcpLayerStart, 97af57ed9fSAtsushi Murai CcpLayerFinish, 98af57ed9fSAtsushi Murai CcpInitRestartCounter, 99af57ed9fSAtsushi Murai CcpSendConfigReq, 1002267893fSBrian Somers CcpSentTerminateReq, 101af57ed9fSAtsushi Murai CcpSendTerminateAck, 102af57ed9fSAtsushi Murai CcpDecodeConfig, 103503a7782SBrian Somers CcpRecvResetReq, 104503a7782SBrian Somers CcpRecvResetAck 105af57ed9fSAtsushi Murai }; 106af57ed9fSAtsushi Murai 107182c898aSBrian Somers static const char * const ccp_TimerNames[] = 1086f384573SBrian Somers {"CCP restart", "CCP openmode", "CCP stopped"}; 1096f384573SBrian Somers 110d6d3eeabSBrian Somers static const char * 111d6d3eeabSBrian Somers protoname(int proto) 112d6d3eeabSBrian Somers { 113182c898aSBrian Somers static char const * const cftypes[] = { 114d6d3eeabSBrian Somers /* Check out the latest ``Compression Control Protocol'' rfc (1962) */ 1159e836af5SBrian Somers "OUI", /* 0: OUI */ 1169e836af5SBrian Somers "PRED1", /* 1: Predictor type 1 */ 1179e836af5SBrian Somers "PRED2", /* 2: Predictor type 2 */ 1189e836af5SBrian Somers "PUDDLE", /* 3: Puddle Jumber */ 119d6d3eeabSBrian Somers NULL, NULL, NULL, NULL, NULL, NULL, 120d6d3eeabSBrian Somers NULL, NULL, NULL, NULL, NULL, NULL, 1219e836af5SBrian Somers "HWPPC", /* 16: Hewlett-Packard PPC */ 1224bc84b8cSBrian Somers "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 123a8d604abSBrian Somers "MPPE", /* 18: Microsoft PPC (rfc2118) and */ 124a8d604abSBrian Somers /* Microsoft PPE (draft-ietf-pppext-mppe) */ 1254bc84b8cSBrian Somers "GAND", /* 19: Gandalf FZA (rfc1993) */ 126b6e82f33SBrian Somers "V42BIS", /* 20: ARG->DATA.42bis compression */ 1270053cc58SBrian Somers "BSD", /* 21: BSD LZW Compress */ 128d6d3eeabSBrian Somers NULL, 1294bc84b8cSBrian Somers "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 1304bc84b8cSBrian Somers "MAGNALINK/DEFLATE",/* 24: Magnalink Variable Resource (rfc1975) */ 1311342caedSBrian Somers /* 24: Deflate (according to pppd-2.3.*) */ 1324bc84b8cSBrian Somers "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 1334bc84b8cSBrian Somers "DEFLATE", /* 26: Deflate (rfc1979) */ 134af57ed9fSAtsushi Murai }; 135af57ed9fSAtsushi Murai 136057f1760SBrian Somers if (proto < 0 || (unsigned)proto > sizeof cftypes / sizeof *cftypes || 1379ea69707SBrian Somers cftypes[proto] == NULL) { 1389ea69707SBrian Somers if (proto == -1) 1399ea69707SBrian Somers return "none"; 140d6d3eeabSBrian Somers return HexStr(proto, NULL, 0); 1419ea69707SBrian Somers } 1429e836af5SBrian Somers 1430053cc58SBrian Somers return cftypes[proto]; 1440053cc58SBrian Somers } 1450053cc58SBrian Somers 1464bc84b8cSBrian Somers /* We support these algorithms, and Req them in the given order */ 147182c898aSBrian Somers static const struct ccp_algorithm * const algorithm[] = { 1484bc84b8cSBrian Somers &DeflateAlgorithm, 1490053cc58SBrian Somers &Pred1Algorithm, 1504bc84b8cSBrian Somers &PppdDeflateAlgorithm 151fb11a9c2SBrian Somers #ifndef NODES 152a8d604abSBrian Somers , &MPPEAlgorithm 153a8d604abSBrian Somers #endif 1540053cc58SBrian Somers }; 1550053cc58SBrian Somers 15670ee81ffSBrian Somers #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 1570053cc58SBrian Somers 158274e766cSBrian Somers int 159503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg) 160af57ed9fSAtsushi Murai { 1616cf6ee76SBrian Somers struct ccp_opt **o; 162dd0645c5SBrian Somers struct link *l; 163dd0645c5SBrian Somers struct ccp *ccp; 1646cf6ee76SBrian Somers int f; 165dd0645c5SBrian Somers 1663a2e4f62SBrian Somers l = command_ChooseLink(arg); 167dd0645c5SBrian Somers ccp = &l->ccp; 168503a7782SBrian Somers 169b6217683SBrian Somers prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 1701e991daaSBrian Somers State2Nam(ccp->fsm.state)); 1715d9e6103SBrian Somers if (ccp->fsm.state == ST_OPENED) { 172b6217683SBrian Somers prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 173503a7782SBrian Somers protoname(ccp->my_proto), protoname(ccp->his_proto)); 174b6217683SBrian Somers prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 175503a7782SBrian Somers ccp->uncompout, ccp->compout, 176503a7782SBrian Somers ccp->compin, ccp->uncompin); 1775d9e6103SBrian Somers } 178cd9647a1SBrian Somers 1796cf6ee76SBrian Somers if (ccp->in.algorithm != -1) 1806cf6ee76SBrian Somers prompt_Printf(arg->prompt, "\n Input Options: %s\n", 1816cf6ee76SBrian Somers (*algorithm[ccp->in.algorithm]->Disp)(&ccp->in.opt)); 1826cf6ee76SBrian Somers 1836cf6ee76SBrian Somers if (ccp->out.algorithm != -1) { 1846cf6ee76SBrian Somers o = &ccp->out.opt; 1856cf6ee76SBrian Somers for (f = 0; f < ccp->out.algorithm; f++) 1866cf6ee76SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 1876cf6ee76SBrian Somers o = &(*o)->next; 1886cf6ee76SBrian Somers prompt_Printf(arg->prompt, " Output Options: %s\n", 1896cf6ee76SBrian Somers (*algorithm[ccp->out.algorithm]->Disp)(&(*o)->val)); 1906cf6ee76SBrian Somers } 1916cf6ee76SBrian Somers 192b6217683SBrian Somers prompt_Printf(arg->prompt, "\n Defaults: "); 193479508cfSBrian Somers prompt_Printf(arg->prompt, "FSM retry = %us, max %u Config" 194479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ccp->cfg.fsm.timeout, 195479508cfSBrian Somers ccp->cfg.fsm.maxreq, ccp->cfg.fsm.maxreq == 1 ? "" : "s", 196479508cfSBrian Somers ccp->cfg.fsm.maxtrm, ccp->cfg.fsm.maxtrm == 1 ? "" : "s"); 197b6217683SBrian Somers prompt_Printf(arg->prompt, " deflate windows: "); 198b6217683SBrian Somers prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 199b6217683SBrian Somers prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 200fb11a9c2SBrian Somers #ifndef NODES 2016cf6ee76SBrian Somers prompt_Printf(arg->prompt, " MPPE: "); 2026cf6ee76SBrian Somers if (ccp->cfg.mppe.keybits) 2036cf6ee76SBrian Somers prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits); 2046cf6ee76SBrian Somers else 2056cf6ee76SBrian Somers prompt_Printf(arg->prompt, "any bits, "); 2066cf6ee76SBrian Somers switch (ccp->cfg.mppe.state) { 2076cf6ee76SBrian Somers case MPPE_STATEFUL: 20880a18377SBrian Somers prompt_Printf(arg->prompt, "stateful"); 2096cf6ee76SBrian Somers break; 2106cf6ee76SBrian Somers case MPPE_STATELESS: 2116cf6ee76SBrian Somers prompt_Printf(arg->prompt, "stateless"); 2126cf6ee76SBrian Somers break; 2136cf6ee76SBrian Somers case MPPE_ANYSTATE: 2146cf6ee76SBrian Somers prompt_Printf(arg->prompt, "any state"); 2156cf6ee76SBrian Somers break; 2166cf6ee76SBrian Somers } 2176cf6ee76SBrian Somers prompt_Printf(arg->prompt, "%s\n", 2186cf6ee76SBrian Somers ccp->cfg.mppe.required ? ", required" : ""); 2196cf6ee76SBrian Somers #endif 2206cf6ee76SBrian Somers 2216cf6ee76SBrian Somers prompt_Printf(arg->prompt, "\n DEFLATE: %s\n", 2221342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); 2231342caedSBrian Somers prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", 2241342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); 2251342caedSBrian Somers prompt_Printf(arg->prompt, " DEFLATE24: %s\n", 2261342caedSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); 227fb11a9c2SBrian Somers #ifndef NODES 2286cf6ee76SBrian Somers prompt_Printf(arg->prompt, " MPPE: %s\n", 229a8d604abSBrian Somers command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE])); 230a8d604abSBrian Somers #endif 231274e766cSBrian Somers return 0; 232af57ed9fSAtsushi Murai } 233af57ed9fSAtsushi Murai 2341ae349f5Scvs2svn void 2356f384573SBrian Somers ccp_SetupCallbacks(struct ccp *ccp) 236af57ed9fSAtsushi Murai { 2376f384573SBrian Somers ccp->fsm.fn = &ccp_Callbacks; 2386f384573SBrian Somers ccp->fsm.FsmTimer.name = ccp_TimerNames[0]; 2396f384573SBrian Somers ccp->fsm.OpenTimer.name = ccp_TimerNames[1]; 2406f384573SBrian Somers ccp->fsm.StoppedTimer.name = ccp_TimerNames[2]; 241ea661041SBrian Somers } 242ea661041SBrian Somers 243ea661041SBrian Somers void 2446d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 2456d666775SBrian Somers const struct fsm_parent *parent) 246ea661041SBrian Somers { 2477308ec68SBrian Somers /* Initialise ourselves */ 2483b0f8d2eSBrian Somers 249479508cfSBrian Somers fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, LogCCP, 2506f384573SBrian Somers bundle, l, parent, &ccp_Callbacks, ccp_TimerNames); 251cd9647a1SBrian Somers 25203036ec7SBrian Somers ccp->cfg.deflate.in.winsize = 0; 25303036ec7SBrian Somers ccp->cfg.deflate.out.winsize = 15; 254479508cfSBrian Somers ccp->cfg.fsm.timeout = DEF_FSMRETRY; 255479508cfSBrian Somers ccp->cfg.fsm.maxreq = DEF_FSMTRIES; 256479508cfSBrian Somers ccp->cfg.fsm.maxtrm = DEF_FSMTRIES; 2571342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; 2581342caedSBrian Somers ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; 2591342caedSBrian Somers ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; 260fb11a9c2SBrian Somers #ifndef NODES 2616cf6ee76SBrian Somers ccp->cfg.mppe.keybits = 0; 2626cf6ee76SBrian Somers ccp->cfg.mppe.state = MPPE_ANYSTATE; 2636cf6ee76SBrian Somers ccp->cfg.mppe.required = 0; 264385167a6SBrian Somers ccp->cfg.neg[CCP_NEG_MPPE] = NEG_ENABLED|NEG_ACCEPTED; 265a8d604abSBrian Somers #endif 266cd9647a1SBrian Somers 267503a7782SBrian Somers ccp_Setup(ccp); 268503a7782SBrian Somers } 269503a7782SBrian Somers 270503a7782SBrian Somers void 271503a7782SBrian Somers ccp_Setup(struct ccp *ccp) 272503a7782SBrian Somers { 273503a7782SBrian Somers /* Set ourselves up for a startup */ 274503a7782SBrian Somers ccp->fsm.open_mode = 0; 275503a7782SBrian Somers ccp->his_proto = ccp->my_proto = -1; 276503a7782SBrian Somers ccp->reset_sent = ccp->last_reset = -1; 27703036ec7SBrian Somers ccp->in.algorithm = ccp->out.algorithm = -1; 27803036ec7SBrian Somers ccp->in.state = ccp->out.state = NULL; 279ff360cc9SBrian Somers ccp->in.opt.hdr.id = -1; 28003036ec7SBrian Somers ccp->out.opt = NULL; 281503a7782SBrian Somers ccp->his_reject = ccp->my_reject = 0; 282503a7782SBrian Somers ccp->uncompout = ccp->compout = 0; 283503a7782SBrian Somers ccp->uncompin = ccp->compin = 0; 284af57ed9fSAtsushi Murai } 285af57ed9fSAtsushi Murai 2866cf6ee76SBrian Somers /* 2876cf6ee76SBrian Somers * Is ccp *REQUIRED* ? 2886cf6ee76SBrian Somers * We ask each of the configured ccp protocols if they're required and 2896cf6ee76SBrian Somers * return TRUE if they are. 2906cf6ee76SBrian Somers * 2916cf6ee76SBrian Somers * It's not possible for the peer to reject a required ccp protocol 2926cf6ee76SBrian Somers * without our state machine bringing the supporting lcp layer down. 2936cf6ee76SBrian Somers * 2946cf6ee76SBrian Somers * If ccp is required but not open, the NCP layer should not push 2956cf6ee76SBrian Somers * any data into the link. 2966cf6ee76SBrian Somers */ 2976cf6ee76SBrian Somers int 2986cf6ee76SBrian Somers ccp_Required(struct ccp *ccp) 2996cf6ee76SBrian Somers { 300057f1760SBrian Somers unsigned f; 3016cf6ee76SBrian Somers 3026cf6ee76SBrian Somers for (f = 0; f < NALGORITHMS; f++) 3036cf6ee76SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 3046cf6ee76SBrian Somers (*algorithm[f]->Required)(&ccp->fsm)) 3056cf6ee76SBrian Somers return 1; 3066cf6ee76SBrian Somers 3076cf6ee76SBrian Somers return 0; 3086cf6ee76SBrian Somers } 3096cf6ee76SBrian Somers 3106301d506SBrian Somers /* 3116301d506SBrian Somers * Report whether it's possible to increase a packet's size after 3126301d506SBrian Somers * compression (and by how much). 3136301d506SBrian Somers */ 3146301d506SBrian Somers int 3156301d506SBrian Somers ccp_MTUOverhead(struct ccp *ccp) 3166301d506SBrian Somers { 3177e62c638SBrian Somers if (ccp->fsm.state == ST_OPENED && ccp->out.algorithm >= 0) 3186301d506SBrian Somers return algorithm[ccp->out.algorithm]->o.MTUOverhead; 3196301d506SBrian Somers 3206301d506SBrian Somers return 0; 3216301d506SBrian Somers } 3226301d506SBrian Somers 323af57ed9fSAtsushi Murai static void 324479508cfSBrian Somers CcpInitRestartCounter(struct fsm *fp, int what) 325af57ed9fSAtsushi Murai { 3267308ec68SBrian Somers /* Set fsm timer load */ 327cd9647a1SBrian Somers struct ccp *ccp = fsm2ccp(fp); 328cd9647a1SBrian Somers 329479508cfSBrian Somers fp->FsmTimer.load = ccp->cfg.fsm.timeout * SECTICKS; 330479508cfSBrian Somers switch (what) { 331479508cfSBrian Somers case FSM_REQ_TIMER: 332479508cfSBrian Somers fp->restart = ccp->cfg.fsm.maxreq; 333479508cfSBrian Somers break; 334479508cfSBrian Somers case FSM_TRM_TIMER: 335479508cfSBrian Somers fp->restart = ccp->cfg.fsm.maxtrm; 336479508cfSBrian Somers break; 337479508cfSBrian Somers default: 338479508cfSBrian Somers fp->restart = 1; 339479508cfSBrian Somers break; 340479508cfSBrian Somers } 341af57ed9fSAtsushi Murai } 342af57ed9fSAtsushi Murai 343af57ed9fSAtsushi Murai static void 344944f7098SBrian Somers CcpSendConfigReq(struct fsm *fp) 345af57ed9fSAtsushi Murai { 3467308ec68SBrian Somers /* Send config REQ please */ 347aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 34803036ec7SBrian Somers struct ccp_opt **o; 34930c2f2ffSBrian Somers u_char *cp, buff[100]; 350057f1760SBrian Somers unsigned f; 351057f1760SBrian Somers int alloc; 352af57ed9fSAtsushi Murai 35330c2f2ffSBrian Somers cp = buff; 35403036ec7SBrian Somers o = &ccp->out.opt; 35503036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 35683d1af55SBrian Somers ccp->my_proto = -1; 35703036ec7SBrian Somers ccp->out.algorithm = -1; 3580053cc58SBrian Somers for (f = 0; f < NALGORITHMS; f++) 3591342caedSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 3607f89db65SBrian Somers !REJECTED(ccp, algorithm[f]->id) && 3617f89db65SBrian Somers (*algorithm[f]->Usable)(fp)) { 3620053cc58SBrian Somers 363ba081e43SBrian Somers if (!alloc) 364ba081e43SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 365057f1760SBrian Somers if ((*o)->val.hdr.id == algorithm[f]->id && (*o)->algorithm == (int)f) 366ba081e43SBrian Somers break; 367ba081e43SBrian Somers 368ba081e43SBrian Somers if (alloc || *o == NULL) { 36903036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 370ff360cc9SBrian Somers (*o)->val.hdr.id = algorithm[f]->id; 371ff360cc9SBrian Somers (*o)->val.hdr.len = 2; 37203036ec7SBrian Somers (*o)->next = NULL; 37303036ec7SBrian Somers (*o)->algorithm = f; 3748fb5ef5aSBrian Somers (*algorithm[f]->o.OptInit)(fp->bundle, &(*o)->val, &ccp->cfg); 375af57ed9fSAtsushi Murai } 3761ae349f5Scvs2svn 377ff360cc9SBrian Somers if (cp + (*o)->val.hdr.len > buff + sizeof buff) { 378dd7e2610SBrian Somers log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 37930c2f2ffSBrian Somers break; 38030c2f2ffSBrian Somers } 381ff360cc9SBrian Somers memcpy(cp, &(*o)->val, (*o)->val.hdr.len); 382ff360cc9SBrian Somers cp += (*o)->val.hdr.len; 38303036ec7SBrian Somers 384ff360cc9SBrian Somers ccp->my_proto = (*o)->val.hdr.id; 38503036ec7SBrian Somers ccp->out.algorithm = f; 38603036ec7SBrian Somers 38703036ec7SBrian Somers if (alloc) 38803036ec7SBrian Somers o = &(*o)->next; 3891ae349f5Scvs2svn } 3902267893fSBrian Somers 391411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT); 392af57ed9fSAtsushi Murai } 393af57ed9fSAtsushi Murai 394af57ed9fSAtsushi Murai void 395dd7e2610SBrian Somers ccp_SendResetReq(struct fsm *fp) 396af57ed9fSAtsushi Murai { 3977308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 398aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3992267893fSBrian Somers 40083d1af55SBrian Somers ccp->reset_sent = fp->reqid; 40183d1af55SBrian Somers ccp->last_reset = -1; 402411675baSBrian Somers fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT); 403af57ed9fSAtsushi Murai } 404af57ed9fSAtsushi Murai 405af57ed9fSAtsushi Murai static void 406057f1760SBrian Somers CcpSentTerminateReq(struct fsm *fp __unused) 407af57ed9fSAtsushi Murai { 4087308ec68SBrian Somers /* Term REQ just sent by FSM */ 409af57ed9fSAtsushi Murai } 410af57ed9fSAtsushi Murai 411af57ed9fSAtsushi Murai static void 4122267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 413af57ed9fSAtsushi Murai { 4147308ec68SBrian Somers /* Send Term ACK please */ 415411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); 416af57ed9fSAtsushi Murai } 417af57ed9fSAtsushi Murai 4186cf6ee76SBrian Somers static int 419944f7098SBrian Somers CcpRecvResetReq(struct fsm *fp) 420af57ed9fSAtsushi Murai { 4217308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 422aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 4236cf6ee76SBrian Somers if (ccp->out.state == NULL) 4246cf6ee76SBrian Somers return 1; 4256cf6ee76SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 426af57ed9fSAtsushi Murai } 427af57ed9fSAtsushi Murai 428af57ed9fSAtsushi Murai static void 429944f7098SBrian Somers CcpLayerStart(struct fsm *fp) 430af57ed9fSAtsushi Murai { 4317308ec68SBrian Somers /* We're about to start up ! */ 432479508cfSBrian Somers struct ccp *ccp = fsm2ccp(fp); 433479508cfSBrian Somers 4343a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name); 435479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 436af57ed9fSAtsushi Murai } 437af57ed9fSAtsushi Murai 438af57ed9fSAtsushi Murai static void 439897f9429SBrian Somers CcpLayerDown(struct fsm *fp) 440af57ed9fSAtsushi Murai { 441897f9429SBrian Somers /* About to come down */ 442aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 443ba081e43SBrian Somers struct ccp_opt *next; 444ba081e43SBrian Somers 4453a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name); 44603036ec7SBrian Somers if (ccp->in.state != NULL) { 44703036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 44803036ec7SBrian Somers ccp->in.state = NULL; 4498d9b9867SBrian Somers ccp->in.algorithm = -1; 4507308ec68SBrian Somers } 45103036ec7SBrian Somers if (ccp->out.state != NULL) { 45203036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 45303036ec7SBrian Somers ccp->out.state = NULL; 4548d9b9867SBrian Somers ccp->out.algorithm = -1; 4557308ec68SBrian Somers } 4568d9b9867SBrian Somers ccp->his_reject = ccp->my_reject = 0; 457ba081e43SBrian Somers 458ba081e43SBrian Somers while (ccp->out.opt) { 459ba081e43SBrian Somers next = ccp->out.opt->next; 460ba081e43SBrian Somers free(ccp->out.opt); 461ba081e43SBrian Somers ccp->out.opt = next; 462ba081e43SBrian Somers } 463897f9429SBrian Somers ccp_Setup(ccp); 464af57ed9fSAtsushi Murai } 465af57ed9fSAtsushi Murai 466af57ed9fSAtsushi Murai static void 467897f9429SBrian Somers CcpLayerFinish(struct fsm *fp) 468af57ed9fSAtsushi Murai { 469897f9429SBrian Somers /* We're now down */ 470e1e8b15eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 471e1e8b15eSBrian Somers struct ccp_opt *next; 472e1e8b15eSBrian Somers 4733a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 474e1e8b15eSBrian Somers 475e1e8b15eSBrian Somers /* 476e1e8b15eSBrian Somers * Nuke options that may be left over from sending a REQ but never 477e1e8b15eSBrian Somers * coming up. 478e1e8b15eSBrian Somers */ 479e1e8b15eSBrian Somers while (ccp->out.opt) { 480e1e8b15eSBrian Somers next = ccp->out.opt->next; 481e1e8b15eSBrian Somers free(ccp->out.opt); 482e1e8b15eSBrian Somers ccp->out.opt = next; 483e1e8b15eSBrian Somers } 4846cf6ee76SBrian Somers 4856cf6ee76SBrian Somers if (ccp_Required(ccp)) { 4866cf6ee76SBrian Somers if (fp->link->lcp.fsm.state == ST_OPENED) 4876cf6ee76SBrian Somers log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name); 4886cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 4896cf6ee76SBrian Somers } 490af57ed9fSAtsushi Murai } 491af57ed9fSAtsushi Murai 4923377c28cSBrian Somers /* Called when CCP has reached the OPEN state */ 4936f384573SBrian Somers static int 494944f7098SBrian Somers CcpLayerUp(struct fsm *fp) 495af57ed9fSAtsushi Murai { 4967308ec68SBrian Somers /* We're now up */ 497aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 498e1e8b15eSBrian Somers struct ccp_opt **o; 499057f1760SBrian Somers unsigned f, fail; 5006301d506SBrian Somers 5016301d506SBrian Somers for (f = fail = 0; f < NALGORITHMS; f++) 5026301d506SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 5036301d506SBrian Somers (*algorithm[f]->Required)(&ccp->fsm) && 504057f1760SBrian Somers (ccp->in.algorithm != (int)f || ccp->out.algorithm != (int)f)) { 5056301d506SBrian Somers /* Blow it all away - we haven't negotiated a required algorithm */ 5066301d506SBrian Somers log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n", 5076301d506SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 5086301d506SBrian Somers fail = 1; 5096301d506SBrian Somers } 5106301d506SBrian Somers 5116301d506SBrian Somers if (fail) { 5126301d506SBrian Somers ccp->his_proto = ccp->my_proto = -1; 5136301d506SBrian Somers fsm_Close(fp); 5146301d506SBrian Somers fsm_Close(&fp->link->lcp.fsm); 5156301d506SBrian Somers return 0; 5166301d506SBrian Somers } 517479508cfSBrian Somers 5183a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 519479508cfSBrian Somers 52003036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 521057f1760SBrian Somers ccp->in.algorithm < (int)NALGORITHMS) { 5228fb5ef5aSBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init) 5238fb5ef5aSBrian Somers (fp->bundle, &ccp->in.opt); 52403036ec7SBrian Somers if (ccp->in.state == NULL) { 525dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 526d47dceb8SBrian Somers fp->link->name, protoname(ccp->his_proto)); 52783d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 528dd7e2610SBrian Somers fsm_Close(fp); 529479508cfSBrian Somers return 0; 53079d1bdaeSBrian Somers } 531af57ed9fSAtsushi Murai } 532af57ed9fSAtsushi Murai 533e1e8b15eSBrian Somers o = &ccp->out.opt; 534057f1760SBrian Somers if (ccp->out.algorithm > 0) 535057f1760SBrian Somers for (f = 0; f < (unsigned)ccp->out.algorithm; f++) 536e1e8b15eSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 537e1e8b15eSBrian Somers o = &(*o)->next; 538e1e8b15eSBrian Somers 53903036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 540057f1760SBrian Somers ccp->out.algorithm < (int)NALGORITHMS) { 5418fb5ef5aSBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 5428fb5ef5aSBrian Somers (fp->bundle, &(*o)->val); 54303036ec7SBrian Somers if (ccp->out.state == NULL) { 544dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 545d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto)); 54683d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 547dd7e2610SBrian Somers fsm_Close(fp); 548479508cfSBrian Somers return 0; 549247ab36dSBrian Somers } 550af57ed9fSAtsushi Murai } 551af57ed9fSAtsushi Murai 552479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 553479508cfSBrian Somers 554dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 555d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 55683d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 557479508cfSBrian Somers 5586f384573SBrian Somers return 1; 559af57ed9fSAtsushi Murai } 560af57ed9fSAtsushi Murai 561af57ed9fSAtsushi Murai static void 562ff360cc9SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 56330c2f2ffSBrian Somers struct fsm_decode *dec) 564af57ed9fSAtsushi Murai { 5657308ec68SBrian Somers /* Deal with incoming data */ 566aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 567ff360cc9SBrian Somers int f; 568ff360cc9SBrian Somers const char *disp; 569ff360cc9SBrian Somers struct fsm_opt *opt; 570af57ed9fSAtsushi Murai 57131516407SBrian Somers if (mode_type == MODE_REQ) 57231516407SBrian Somers ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 57331516407SBrian Somers 574057f1760SBrian Somers while (end >= cp + sizeof(opt->hdr)) { 575ff360cc9SBrian Somers if ((opt = fsm_readopt(&cp)) == NULL) 576d47dceb8SBrian Somers break; 577af57ed9fSAtsushi Murai 5780053cc58SBrian Somers for (f = NALGORITHMS-1; f > -1; f--) 579ff360cc9SBrian Somers if (algorithm[f]->id == opt->hdr.id) 5800053cc58SBrian Somers break; 581af57ed9fSAtsushi Murai 582ff360cc9SBrian Somers disp = f == -1 ? "" : (*algorithm[f]->Disp)(opt); 583ff360cc9SBrian Somers if (disp == NULL) 584ff360cc9SBrian Somers disp = ""; 58503036ec7SBrian Somers 586ff360cc9SBrian Somers log_Printf(LogCCP, " %s[%d] %s\n", protoname(opt->hdr.id), 587ff360cc9SBrian Somers opt->hdr.len, disp); 58803036ec7SBrian Somers 5890053cc58SBrian Somers if (f == -1) { 5900053cc58SBrian Somers /* Don't understand that :-( */ 5910053cc58SBrian Somers if (mode_type == MODE_REQ) { 592ff360cc9SBrian Somers ccp->my_reject |= (1 << opt->hdr.id); 593ff360cc9SBrian Somers fsm_rej(dec, opt); 5940053cc58SBrian Somers } 5950053cc58SBrian Somers } else { 59603036ec7SBrian Somers struct ccp_opt *o; 5970053cc58SBrian Somers 5989780ef31SBrian Somers switch (mode_type) { 599af57ed9fSAtsushi Murai case MODE_REQ: 6001342caedSBrian Somers if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 6017f89db65SBrian Somers (*algorithm[f]->Usable)(fp) && 6021342caedSBrian Somers ccp->in.algorithm == -1) { 603ff360cc9SBrian Somers memcpy(&ccp->in.opt, opt, opt->hdr.len); 6048fb5ef5aSBrian Somers switch ((*algorithm[f]->i.Set)(fp->bundle, &ccp->in.opt, &ccp->cfg)) { 6050053cc58SBrian Somers case MODE_REJ: 606ff360cc9SBrian Somers fsm_rej(dec, &ccp->in.opt); 6070053cc58SBrian Somers break; 6080053cc58SBrian Somers case MODE_NAK: 609ff360cc9SBrian Somers fsm_nak(dec, &ccp->in.opt); 6100053cc58SBrian Somers break; 6110053cc58SBrian Somers case MODE_ACK: 612ff360cc9SBrian Somers fsm_ack(dec, &ccp->in.opt); 613ff360cc9SBrian Somers ccp->his_proto = opt->hdr.id; 614057f1760SBrian Somers ccp->in.algorithm = (int)f; /* This one'll do :-) */ 6150053cc58SBrian Somers break; 6160053cc58SBrian Somers } 617af57ed9fSAtsushi Murai } else { 618ff360cc9SBrian Somers fsm_rej(dec, opt); 619af57ed9fSAtsushi Murai } 620af57ed9fSAtsushi Murai break; 621af57ed9fSAtsushi Murai case MODE_NAK: 62203036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 623ff360cc9SBrian Somers if (o->val.hdr.id == opt->hdr.id) 62403036ec7SBrian Somers break; 62503036ec7SBrian Somers if (o == NULL) 6269b996792SBrian Somers log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" 6279b996792SBrian Somers " option\n", fp->link->name); 6280053cc58SBrian Somers else { 629ff360cc9SBrian Somers memcpy(&o->val, opt, opt->hdr.len); 6308fb5ef5aSBrian Somers if ((*algorithm[f]->o.Set)(fp->bundle, &o->val, &ccp->cfg) == 6318fb5ef5aSBrian Somers MODE_ACK) 63283d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 6331ae349f5Scvs2svn else { 634ff360cc9SBrian Somers ccp->his_reject |= (1 << opt->hdr.id); 63583d1af55SBrian Somers ccp->my_proto = -1; 6366cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6376cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Cannot understand peers (required)" 6386cf6ee76SBrian Somers " %s negotiation\n", fp->link->name, 6396cf6ee76SBrian Somers protoname(algorithm[f]->id)); 6406cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6416cf6ee76SBrian Somers } 6421ae349f5Scvs2svn } 6430053cc58SBrian Somers } 6440053cc58SBrian Somers break; 645af57ed9fSAtsushi Murai case MODE_REJ: 646ff360cc9SBrian Somers ccp->his_reject |= (1 << opt->hdr.id); 64783d1af55SBrian Somers ccp->my_proto = -1; 6486cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6496cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n", 6506cf6ee76SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 6516cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6526cf6ee76SBrian Somers } 653af57ed9fSAtsushi Murai break; 654af57ed9fSAtsushi Murai } 655af57ed9fSAtsushi Murai } 656af57ed9fSAtsushi Murai } 6570053cc58SBrian Somers 658e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 659ff360cc9SBrian Somers fsm_opt_normalise(dec); 660ff360cc9SBrian Somers if (dec->rejend != dec->rej || dec->nakend != dec->nak) { 66103036ec7SBrian Somers if (ccp->in.state == NULL) { 66203036ec7SBrian Somers ccp->his_proto = -1; 66303036ec7SBrian Somers ccp->in.algorithm = -1; 664247ab36dSBrian Somers } 6651ae349f5Scvs2svn } 6660053cc58SBrian Somers } 667af57ed9fSAtsushi Murai } 668af57ed9fSAtsushi Murai 6695d9e6103SBrian Somers extern struct mbuf * 6705d9e6103SBrian Somers ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 671af57ed9fSAtsushi Murai { 6727308ec68SBrian Somers /* Got PROTO_CCP from link */ 67326af0ae9SBrian Somers m_settype(bp, MB_CCPIN); 674455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 6755d9e6103SBrian Somers fsm_Input(&l->ccp.fsm, bp); 676af57ed9fSAtsushi Murai else { 677641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 678dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 6795d9e6103SBrian Somers l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 68026af0ae9SBrian Somers m_freem(bp); 681af57ed9fSAtsushi Murai } 6825d9e6103SBrian Somers return NULL; 683af57ed9fSAtsushi Murai } 6840053cc58SBrian Somers 685503a7782SBrian Somers static void 686503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 6870053cc58SBrian Somers { 6887308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 689f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 690f4768038SBrian Somers 691f4768038SBrian Somers if (ccp->reset_sent != -1) { 692f4768038SBrian Somers if (id != ccp->reset_sent) { 693a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 694d47dceb8SBrian Somers " ignored\n", fp->link->name, id, ccp->reset_sent); 69598baf7c8SBrian Somers return; 69698baf7c8SBrian Somers } 69798baf7c8SBrian Somers /* Whaddaya know - a correct reset ack */ 698f4768038SBrian Somers } else if (id == ccp->last_reset) 699dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 700d47dceb8SBrian Somers fp->link->name); 70198baf7c8SBrian Somers else { 702a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 703d47dceb8SBrian Somers fp->link->name, id); 70498baf7c8SBrian Somers return; 70598baf7c8SBrian Somers } 70698baf7c8SBrian Somers 707f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 708f4768038SBrian Somers ccp->reset_sent = -1; 70903036ec7SBrian Somers if (ccp->in.state != NULL) 71003036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 7110053cc58SBrian Somers } 7120053cc58SBrian Somers 7135d9e6103SBrian Somers static struct mbuf * 714057f1760SBrian Somers ccp_LayerPush(struct bundle *b __unused, struct link *l, struct mbuf *bp, 7155d9e6103SBrian Somers int pri, u_short *proto) 7160053cc58SBrian Somers { 7176cf6ee76SBrian Somers if (PROTO_COMPRESSIBLE(*proto)) { 7186cf6ee76SBrian Somers if (l->ccp.fsm.state != ST_OPENED) { 7196cf6ee76SBrian Somers if (ccp_Required(&l->ccp)) { 7206cf6ee76SBrian Somers /* The NCP layer shouldn't have let this happen ! */ 7216cf6ee76SBrian Somers log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and" 7226cf6ee76SBrian Somers " required CCP layer\n", l->name); 7236cf6ee76SBrian Somers m_freem(bp); 7246cf6ee76SBrian Somers bp = NULL; 7256cf6ee76SBrian Somers } 7266cf6ee76SBrian Somers } else if (l->ccp.out.state != NULL) { 727411675baSBrian Somers bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 7285d9e6103SBrian Somers (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 729411675baSBrian Somers switch (*proto) { 730411675baSBrian Somers case PROTO_ICOMPD: 73126af0ae9SBrian Somers m_settype(bp, MB_ICOMPDOUT); 732411675baSBrian Somers break; 733411675baSBrian Somers case PROTO_COMPD: 73426af0ae9SBrian Somers m_settype(bp, MB_COMPDOUT); 735411675baSBrian Somers break; 736411675baSBrian Somers } 737411675baSBrian Somers } 7386cf6ee76SBrian Somers } 7395d9e6103SBrian Somers 7405d9e6103SBrian Somers return bp; 7410053cc58SBrian Somers } 7420053cc58SBrian Somers 7435d9e6103SBrian Somers static struct mbuf * 744057f1760SBrian Somers ccp_LayerPull(struct bundle *b __unused, struct link *l, struct mbuf *bp, 745057f1760SBrian Somers u_short *proto) 7460053cc58SBrian Somers { 747ee6c193fSBrian Somers /* 748ed32233cSBrian Somers * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 749ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 750ee6c193fSBrian Somers */ 7515d9e6103SBrian Somers if (l->ccp.fsm.state == ST_OPENED) { 752ed32233cSBrian Somers if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 7537308ec68SBrian Somers /* Decompress incoming data */ 7545d9e6103SBrian Somers if (l->ccp.reset_sent != -1) 75598baf7c8SBrian Somers /* Send another REQ and put the packet in the bit bucket */ 756411675baSBrian Somers fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 757411675baSBrian Somers MB_CCPOUT); 758411675baSBrian Somers else if (l->ccp.in.state != NULL) { 759411675baSBrian Somers bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 7605d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, proto, bp); 761411675baSBrian Somers switch (*proto) { 762411675baSBrian Somers case PROTO_ICOMPD: 76326af0ae9SBrian Somers m_settype(bp, MB_ICOMPDIN); 764411675baSBrian Somers break; 765411675baSBrian Somers case PROTO_COMPD: 76626af0ae9SBrian Somers m_settype(bp, MB_COMPDIN); 767411675baSBrian Somers break; 768411675baSBrian Somers } 769411675baSBrian Somers return bp; 770411675baSBrian Somers } 77126af0ae9SBrian Somers m_freem(bp); 772ee6c193fSBrian Somers bp = NULL; 7736815097bSBrian Somers } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 774ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 7755d9e6103SBrian Somers (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 7765d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, *proto, bp); 777e0efa796SBrian Somers } 7780053cc58SBrian Somers } 7790053cc58SBrian Somers 780ee6c193fSBrian Somers return bp; 7811ae349f5Scvs2svn } 782ed32233cSBrian Somers 783ed32233cSBrian Somers u_short 784ed32233cSBrian Somers ccp_Proto(struct ccp *ccp) 7850053cc58SBrian Somers { 786ed32233cSBrian Somers return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 787ed32233cSBrian Somers PROTO_COMPD : PROTO_ICOMPD; 7880053cc58SBrian Somers } 7891df0a3b9SBrian Somers 79006337856SBrian Somers int 7911df0a3b9SBrian Somers ccp_SetOpenMode(struct ccp *ccp) 7921df0a3b9SBrian Somers { 7931df0a3b9SBrian Somers int f; 7941df0a3b9SBrian Somers 7951df0a3b9SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 79606337856SBrian Somers if (IsEnabled(ccp->cfg.neg[f])) { 7971df0a3b9SBrian Somers ccp->fsm.open_mode = 0; 79806337856SBrian Somers return 1; 79906337856SBrian Somers } 8001df0a3b9SBrian Somers 80106337856SBrian Somers ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 80206337856SBrian Somers 80306337856SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 80406337856SBrian Somers if (IsAccepted(ccp->cfg.neg[f])) 80506337856SBrian Somers return 1; 80606337856SBrian Somers 80706337856SBrian Somers return 0; /* No CCP at all */ 8081df0a3b9SBrian Somers } 8095d9e6103SBrian Somers 8107f89db65SBrian Somers int 811057f1760SBrian Somers ccp_DefaultUsable(struct fsm *fp __unused) 8127f89db65SBrian Somers { 8137f89db65SBrian Somers return 1; 8147f89db65SBrian Somers } 8157f89db65SBrian Somers 8166cf6ee76SBrian Somers int 817057f1760SBrian Somers ccp_DefaultRequired(struct fsm *fp __unused) 8186cf6ee76SBrian Somers { 8196cf6ee76SBrian Somers return 0; 8206cf6ee76SBrian Somers } 8216cf6ee76SBrian Somers 8225d9e6103SBrian Somers struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 823