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 3875240ed1SBrian Somers #include <stdio.h> 3903036ec7SBrian Somers #include <stdlib.h> 40eb6e5e05SBrian Somers #include <string.h> /* memcpy() on some archs */ 4185b542cfSBrian Somers #include <termios.h> 4275240ed1SBrian Somers 435d9e6103SBrian Somers #include "layer.h" 44c9e11a11SBrian Somers #include "defs.h" 45b6e82f33SBrian Somers #include "command.h" 4675240ed1SBrian Somers #include "mbuf.h" 4775240ed1SBrian Somers #include "log.h" 4875240ed1SBrian Somers #include "timer.h" 49af57ed9fSAtsushi Murai #include "fsm.h" 505d9e6103SBrian Somers #include "proto.h" 51ed6a16c1SPoul-Henning Kamp #include "pred.h" 520053cc58SBrian Somers #include "deflate.h" 535828db6dSBrian Somers #include "throughput.h" 545828db6dSBrian Somers #include "iplist.h" 55eaa4df37SBrian Somers #include "slcompress.h" 565a72b6edSBrian Somers #include "lqr.h" 575a72b6edSBrian Somers #include "hdlc.h" 581038894eSBrian Somers #include "lcp.h" 591038894eSBrian Somers #include "ccp.h" 6030949fd4SBrian Somers #include "ncpaddr.h" 6130949fd4SBrian Somers #include "ip.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); 8330c2f2ffSBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, 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 136d6d3eeabSBrian Somers if (proto < 0 || 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; 27903036ec7SBrian Somers ccp->in.opt.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 { 3006cf6ee76SBrian Somers int 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]; 35003036ec7SBrian Somers int f, alloc; 351af57ed9fSAtsushi Murai 35230c2f2ffSBrian Somers cp = buff; 35303036ec7SBrian Somers o = &ccp->out.opt; 35403036ec7SBrian Somers alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 35583d1af55SBrian Somers ccp->my_proto = -1; 35603036ec7SBrian Somers ccp->out.algorithm = -1; 3570053cc58SBrian Somers for (f = 0; f < NALGORITHMS; f++) 3581342caedSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 3597f89db65SBrian Somers !REJECTED(ccp, algorithm[f]->id) && 3607f89db65SBrian Somers (*algorithm[f]->Usable)(fp)) { 3610053cc58SBrian Somers 362ba081e43SBrian Somers if (!alloc) 363ba081e43SBrian Somers for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 364ba081e43SBrian Somers if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 365ba081e43SBrian Somers break; 366ba081e43SBrian Somers 367ba081e43SBrian Somers if (alloc || *o == NULL) { 36803036ec7SBrian Somers *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 36903036ec7SBrian Somers (*o)->val.id = algorithm[f]->id; 37003036ec7SBrian Somers (*o)->val.len = 2; 37103036ec7SBrian Somers (*o)->next = NULL; 37203036ec7SBrian Somers (*o)->algorithm = f; 37303036ec7SBrian Somers (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 374af57ed9fSAtsushi Murai } 3751ae349f5Scvs2svn 37603036ec7SBrian Somers if (cp + (*o)->val.len > buff + sizeof buff) { 377dd7e2610SBrian Somers log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 37830c2f2ffSBrian Somers break; 37930c2f2ffSBrian Somers } 3802267893fSBrian Somers memcpy(cp, &(*o)->val, (*o)->val.len); 3812267893fSBrian Somers cp += (*o)->val.len; 38203036ec7SBrian Somers 38303036ec7SBrian Somers ccp->my_proto = (*o)->val.id; 38403036ec7SBrian Somers ccp->out.algorithm = f; 38503036ec7SBrian Somers 38603036ec7SBrian Somers if (alloc) 38703036ec7SBrian Somers o = &(*o)->next; 3881ae349f5Scvs2svn } 3892267893fSBrian Somers 390411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT); 391af57ed9fSAtsushi Murai } 392af57ed9fSAtsushi Murai 393af57ed9fSAtsushi Murai void 394dd7e2610SBrian Somers ccp_SendResetReq(struct fsm *fp) 395af57ed9fSAtsushi Murai { 3967308ec68SBrian Somers /* We can't read our input - ask peer to reset */ 397aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 3982267893fSBrian Somers 39983d1af55SBrian Somers ccp->reset_sent = fp->reqid; 40083d1af55SBrian Somers ccp->last_reset = -1; 401411675baSBrian Somers fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT); 402af57ed9fSAtsushi Murai } 403af57ed9fSAtsushi Murai 404af57ed9fSAtsushi Murai static void 4052267893fSBrian Somers CcpSentTerminateReq(struct fsm *fp) 406af57ed9fSAtsushi Murai { 4077308ec68SBrian Somers /* Term REQ just sent by FSM */ 408af57ed9fSAtsushi Murai } 409af57ed9fSAtsushi Murai 410af57ed9fSAtsushi Murai static void 4112267893fSBrian Somers CcpSendTerminateAck(struct fsm *fp, u_char id) 412af57ed9fSAtsushi Murai { 4137308ec68SBrian Somers /* Send Term ACK please */ 414411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); 415af57ed9fSAtsushi Murai } 416af57ed9fSAtsushi Murai 4176cf6ee76SBrian Somers static int 418944f7098SBrian Somers CcpRecvResetReq(struct fsm *fp) 419af57ed9fSAtsushi Murai { 4207308ec68SBrian Somers /* Got a reset REQ, reset outgoing dictionary */ 421aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 4226cf6ee76SBrian Somers if (ccp->out.state == NULL) 4236cf6ee76SBrian Somers return 1; 4246cf6ee76SBrian Somers return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 425af57ed9fSAtsushi Murai } 426af57ed9fSAtsushi Murai 427af57ed9fSAtsushi Murai static void 428944f7098SBrian Somers CcpLayerStart(struct fsm *fp) 429af57ed9fSAtsushi Murai { 4307308ec68SBrian Somers /* We're about to start up ! */ 431479508cfSBrian Somers struct ccp *ccp = fsm2ccp(fp); 432479508cfSBrian Somers 4333a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name); 434479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 435af57ed9fSAtsushi Murai } 436af57ed9fSAtsushi Murai 437af57ed9fSAtsushi Murai static void 438897f9429SBrian Somers CcpLayerDown(struct fsm *fp) 439af57ed9fSAtsushi Murai { 440897f9429SBrian Somers /* About to come down */ 441aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 442ba081e43SBrian Somers struct ccp_opt *next; 443ba081e43SBrian Somers 4443a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name); 44503036ec7SBrian Somers if (ccp->in.state != NULL) { 44603036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 44703036ec7SBrian Somers ccp->in.state = NULL; 4488d9b9867SBrian Somers ccp->in.algorithm = -1; 4497308ec68SBrian Somers } 45003036ec7SBrian Somers if (ccp->out.state != NULL) { 45103036ec7SBrian Somers (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 45203036ec7SBrian Somers ccp->out.state = NULL; 4538d9b9867SBrian Somers ccp->out.algorithm = -1; 4547308ec68SBrian Somers } 4558d9b9867SBrian Somers ccp->his_reject = ccp->my_reject = 0; 456ba081e43SBrian Somers 457ba081e43SBrian Somers while (ccp->out.opt) { 458ba081e43SBrian Somers next = ccp->out.opt->next; 459ba081e43SBrian Somers free(ccp->out.opt); 460ba081e43SBrian Somers ccp->out.opt = next; 461ba081e43SBrian Somers } 462897f9429SBrian Somers ccp_Setup(ccp); 463af57ed9fSAtsushi Murai } 464af57ed9fSAtsushi Murai 465af57ed9fSAtsushi Murai static void 466897f9429SBrian Somers CcpLayerFinish(struct fsm *fp) 467af57ed9fSAtsushi Murai { 468897f9429SBrian Somers /* We're now down */ 469e1e8b15eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 470e1e8b15eSBrian Somers struct ccp_opt *next; 471e1e8b15eSBrian Somers 4723a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 473e1e8b15eSBrian Somers 474e1e8b15eSBrian Somers /* 475e1e8b15eSBrian Somers * Nuke options that may be left over from sending a REQ but never 476e1e8b15eSBrian Somers * coming up. 477e1e8b15eSBrian Somers */ 478e1e8b15eSBrian Somers while (ccp->out.opt) { 479e1e8b15eSBrian Somers next = ccp->out.opt->next; 480e1e8b15eSBrian Somers free(ccp->out.opt); 481e1e8b15eSBrian Somers ccp->out.opt = next; 482e1e8b15eSBrian Somers } 4836cf6ee76SBrian Somers 4846cf6ee76SBrian Somers if (ccp_Required(ccp)) { 4856cf6ee76SBrian Somers if (fp->link->lcp.fsm.state == ST_OPENED) 4866cf6ee76SBrian Somers log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name); 4876cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 4886cf6ee76SBrian Somers } 489af57ed9fSAtsushi Murai } 490af57ed9fSAtsushi Murai 4913377c28cSBrian Somers /* Called when CCP has reached the OPEN state */ 4926f384573SBrian Somers static int 493944f7098SBrian Somers CcpLayerUp(struct fsm *fp) 494af57ed9fSAtsushi Murai { 4957308ec68SBrian Somers /* We're now up */ 496aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 497e1e8b15eSBrian Somers struct ccp_opt **o; 4986301d506SBrian Somers int f, fail; 4996301d506SBrian Somers 5006301d506SBrian Somers for (f = fail = 0; f < NALGORITHMS; f++) 5016301d506SBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 5026301d506SBrian Somers (*algorithm[f]->Required)(&ccp->fsm) && 5036301d506SBrian Somers (ccp->in.algorithm != f || ccp->out.algorithm != f)) { 5046301d506SBrian Somers /* Blow it all away - we haven't negotiated a required algorithm */ 5056301d506SBrian Somers log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n", 5066301d506SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 5076301d506SBrian Somers fail = 1; 5086301d506SBrian Somers } 5096301d506SBrian Somers 5106301d506SBrian Somers if (fail) { 5116301d506SBrian Somers ccp->his_proto = ccp->my_proto = -1; 5126301d506SBrian Somers fsm_Close(fp); 5136301d506SBrian Somers fsm_Close(&fp->link->lcp.fsm); 5146301d506SBrian Somers return 0; 5156301d506SBrian Somers } 516479508cfSBrian Somers 5173a2e4f62SBrian Somers log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 518479508cfSBrian Somers 51903036ec7SBrian Somers if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 52003036ec7SBrian Somers ccp->in.algorithm < NALGORITHMS) { 52103036ec7SBrian Somers ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 52203036ec7SBrian Somers if (ccp->in.state == NULL) { 523dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 524d47dceb8SBrian Somers fp->link->name, protoname(ccp->his_proto)); 52583d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 526dd7e2610SBrian Somers fsm_Close(fp); 527479508cfSBrian Somers return 0; 52879d1bdaeSBrian Somers } 529af57ed9fSAtsushi Murai } 530af57ed9fSAtsushi Murai 531e1e8b15eSBrian Somers o = &ccp->out.opt; 532e1e8b15eSBrian Somers for (f = 0; f < ccp->out.algorithm; f++) 533e1e8b15eSBrian Somers if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 534e1e8b15eSBrian Somers o = &(*o)->next; 535e1e8b15eSBrian Somers 53603036ec7SBrian Somers if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 53703036ec7SBrian Somers ccp->out.algorithm < NALGORITHMS) { 538e1e8b15eSBrian Somers ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)(&(*o)->val); 53903036ec7SBrian Somers if (ccp->out.state == NULL) { 540dd7e2610SBrian Somers log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 541d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto)); 54283d1af55SBrian Somers ccp->his_proto = ccp->my_proto = -1; 543dd7e2610SBrian Somers fsm_Close(fp); 544479508cfSBrian Somers return 0; 545247ab36dSBrian Somers } 546af57ed9fSAtsushi Murai } 547af57ed9fSAtsushi Murai 548479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 549479508cfSBrian Somers 550dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 551d47dceb8SBrian Somers fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 55283d1af55SBrian Somers protoname(ccp->his_proto), ccp->his_proto); 553479508cfSBrian Somers 5546f384573SBrian Somers return 1; 555af57ed9fSAtsushi Murai } 556af57ed9fSAtsushi Murai 557af57ed9fSAtsushi Murai static void 55830c2f2ffSBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 55930c2f2ffSBrian Somers struct fsm_decode *dec) 560af57ed9fSAtsushi Murai { 5617308ec68SBrian Somers /* Deal with incoming data */ 562aad81d1eSBrian Somers struct ccp *ccp = fsm2ccp(fp); 56331516407SBrian Somers int type, length, f; 56403036ec7SBrian Somers const char *end; 565af57ed9fSAtsushi Murai 56631516407SBrian Somers if (mode_type == MODE_REQ) 56731516407SBrian Somers ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 56831516407SBrian Somers 569af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 570af57ed9fSAtsushi Murai type = *cp; 571af57ed9fSAtsushi Murai length = cp[1]; 57203036ec7SBrian Somers 573d47dceb8SBrian Somers if (length == 0) { 574dd7e2610SBrian Somers log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name); 575d47dceb8SBrian Somers break; 576d47dceb8SBrian Somers } 577d47dceb8SBrian Somers 57803036ec7SBrian Somers if (length > sizeof(struct lcp_opt)) { 57903036ec7SBrian Somers length = sizeof(struct lcp_opt); 580dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n", 581d47dceb8SBrian Somers fp->link->name, length); 58203036ec7SBrian Somers } 583af57ed9fSAtsushi Murai 5840053cc58SBrian Somers for (f = NALGORITHMS-1; f > -1; f--) 5850053cc58SBrian Somers if (algorithm[f]->id == type) 5860053cc58SBrian Somers break; 587af57ed9fSAtsushi Murai 58803036ec7SBrian Somers end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 58903036ec7SBrian Somers if (end == NULL) 59003036ec7SBrian Somers end = ""; 59103036ec7SBrian Somers 592d6d3eeabSBrian Somers log_Printf(LogCCP, " %s[%d] %s\n", protoname(type), length, end); 59303036ec7SBrian Somers 5940053cc58SBrian Somers if (f == -1) { 5950053cc58SBrian Somers /* Don't understand that :-( */ 5960053cc58SBrian Somers if (mode_type == MODE_REQ) { 59783d1af55SBrian Somers ccp->my_reject |= (1 << type); 59830c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 59930c2f2ffSBrian Somers dec->rejend += length; 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) { 60903036ec7SBrian Somers memcpy(&ccp->in.opt, cp, length); 61003036ec7SBrian Somers switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 6110053cc58SBrian Somers case MODE_REJ: 61203036ec7SBrian Somers memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 61303036ec7SBrian Somers dec->rejend += ccp->in.opt.len; 6140053cc58SBrian Somers break; 6150053cc58SBrian Somers case MODE_NAK: 61603036ec7SBrian Somers memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 61703036ec7SBrian Somers dec->nakend += ccp->in.opt.len; 6180053cc58SBrian Somers break; 6190053cc58SBrian Somers case MODE_ACK: 62030c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 62130c2f2ffSBrian Somers dec->ackend += length; 62283d1af55SBrian Somers ccp->his_proto = type; 62303036ec7SBrian Somers ccp->in.algorithm = f; /* This one'll do :-) */ 6240053cc58SBrian Somers break; 6250053cc58SBrian Somers } 626af57ed9fSAtsushi Murai } else { 62730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 62830c2f2ffSBrian Somers dec->rejend += length; 629af57ed9fSAtsushi Murai } 630af57ed9fSAtsushi Murai break; 631af57ed9fSAtsushi Murai case MODE_NAK: 63203036ec7SBrian Somers for (o = ccp->out.opt; o != NULL; o = o->next) 63303036ec7SBrian Somers if (o->val.id == cp[0]) 63403036ec7SBrian Somers break; 63503036ec7SBrian Somers if (o == NULL) 6369b996792SBrian Somers log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" 6379b996792SBrian Somers " option\n", fp->link->name); 6380053cc58SBrian Somers else { 63903036ec7SBrian Somers memcpy(&o->val, cp, length); 6406cf6ee76SBrian Somers if ((*algorithm[f]->o.Set)(&o->val, &ccp->cfg) == MODE_ACK) 64183d1af55SBrian Somers ccp->my_proto = algorithm[f]->id; 6421ae349f5Scvs2svn else { 64383d1af55SBrian Somers ccp->his_reject |= (1 << type); 64483d1af55SBrian Somers ccp->my_proto = -1; 6456cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6466cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Cannot understand peers (required)" 6476cf6ee76SBrian Somers " %s negotiation\n", fp->link->name, 6486cf6ee76SBrian Somers protoname(algorithm[f]->id)); 6496cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6506cf6ee76SBrian Somers } 6511ae349f5Scvs2svn } 6520053cc58SBrian Somers } 6530053cc58SBrian Somers break; 654af57ed9fSAtsushi Murai case MODE_REJ: 65583d1af55SBrian Somers ccp->his_reject |= (1 << type); 65683d1af55SBrian Somers ccp->my_proto = -1; 6576cf6ee76SBrian Somers if (algorithm[f]->Required(fp)) { 6586cf6ee76SBrian Somers log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n", 6596cf6ee76SBrian Somers fp->link->name, protoname(algorithm[f]->id)); 6606cf6ee76SBrian Somers fsm_Close(&fp->link->lcp.fsm); 6616cf6ee76SBrian Somers } 662af57ed9fSAtsushi Murai break; 663af57ed9fSAtsushi Murai } 664af57ed9fSAtsushi Murai } 6650053cc58SBrian Somers 66603036ec7SBrian Somers plen -= cp[1]; 66703036ec7SBrian Somers cp += cp[1]; 668af57ed9fSAtsushi Murai } 6690053cc58SBrian Somers 670e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 6711342caedSBrian Somers if (dec->rejend != dec->rej) { 67203036ec7SBrian Somers /* rejects are preferred */ 67303036ec7SBrian Somers dec->ackend = dec->ack; 67403036ec7SBrian Somers dec->nakend = dec->nak; 67503036ec7SBrian Somers if (ccp->in.state == NULL) { 67683d1af55SBrian Somers ccp->his_proto = -1; 67703036ec7SBrian Somers ccp->in.algorithm = -1; 67803036ec7SBrian Somers } 6791342caedSBrian Somers } else if (dec->nakend != dec->nak) { 68003036ec7SBrian Somers /* then NAKs */ 68103036ec7SBrian Somers dec->ackend = dec->ack; 68203036ec7SBrian Somers if (ccp->in.state == NULL) { 68303036ec7SBrian Somers ccp->his_proto = -1; 68403036ec7SBrian Somers ccp->in.algorithm = -1; 685247ab36dSBrian Somers } 6861ae349f5Scvs2svn } 6870053cc58SBrian Somers } 688af57ed9fSAtsushi Murai } 689af57ed9fSAtsushi Murai 6905d9e6103SBrian Somers extern struct mbuf * 6915d9e6103SBrian Somers ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 692af57ed9fSAtsushi Murai { 6937308ec68SBrian Somers /* Got PROTO_CCP from link */ 69426af0ae9SBrian Somers m_settype(bp, MB_CCPIN); 695455aabc3SBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 6965d9e6103SBrian Somers fsm_Input(&l->ccp.fsm, bp); 697af57ed9fSAtsushi Murai else { 698641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 699dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 7005d9e6103SBrian Somers l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 70126af0ae9SBrian Somers m_freem(bp); 702af57ed9fSAtsushi Murai } 7035d9e6103SBrian Somers return NULL; 704af57ed9fSAtsushi Murai } 7050053cc58SBrian Somers 706503a7782SBrian Somers static void 707503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id) 7080053cc58SBrian Somers { 7097308ec68SBrian Somers /* Got a reset ACK, reset incoming dictionary */ 710f4768038SBrian Somers struct ccp *ccp = fsm2ccp(fp); 711f4768038SBrian Somers 712f4768038SBrian Somers if (ccp->reset_sent != -1) { 713f4768038SBrian Somers if (id != ccp->reset_sent) { 714a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 715d47dceb8SBrian Somers " ignored\n", fp->link->name, id, ccp->reset_sent); 71698baf7c8SBrian Somers return; 71798baf7c8SBrian Somers } 71898baf7c8SBrian Somers /* Whaddaya know - a correct reset ack */ 719f4768038SBrian Somers } else if (id == ccp->last_reset) 720dd7e2610SBrian Somers log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 721d47dceb8SBrian Somers fp->link->name); 72298baf7c8SBrian Somers else { 723a36ca3ccSBrian Somers log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 724d47dceb8SBrian Somers fp->link->name, id); 72598baf7c8SBrian Somers return; 72698baf7c8SBrian Somers } 72798baf7c8SBrian Somers 728f4768038SBrian Somers ccp->last_reset = ccp->reset_sent; 729f4768038SBrian Somers ccp->reset_sent = -1; 73003036ec7SBrian Somers if (ccp->in.state != NULL) 73103036ec7SBrian Somers (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 7320053cc58SBrian Somers } 7330053cc58SBrian Somers 7345d9e6103SBrian Somers static struct mbuf * 7355d9e6103SBrian Somers ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, 7365d9e6103SBrian Somers int pri, u_short *proto) 7370053cc58SBrian Somers { 7386cf6ee76SBrian Somers if (PROTO_COMPRESSIBLE(*proto)) { 7396cf6ee76SBrian Somers if (l->ccp.fsm.state != ST_OPENED) { 7406cf6ee76SBrian Somers if (ccp_Required(&l->ccp)) { 7416cf6ee76SBrian Somers /* The NCP layer shouldn't have let this happen ! */ 7426cf6ee76SBrian Somers log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and" 7436cf6ee76SBrian Somers " required CCP layer\n", l->name); 7446cf6ee76SBrian Somers m_freem(bp); 7456cf6ee76SBrian Somers bp = NULL; 7466cf6ee76SBrian Somers } 7476cf6ee76SBrian Somers } else if (l->ccp.out.state != NULL) { 748411675baSBrian Somers bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 7495d9e6103SBrian Somers (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 750411675baSBrian Somers switch (*proto) { 751411675baSBrian Somers case PROTO_ICOMPD: 75226af0ae9SBrian Somers m_settype(bp, MB_ICOMPDOUT); 753411675baSBrian Somers break; 754411675baSBrian Somers case PROTO_COMPD: 75526af0ae9SBrian Somers m_settype(bp, MB_COMPDOUT); 756411675baSBrian Somers break; 757411675baSBrian Somers } 758411675baSBrian Somers } 7596cf6ee76SBrian Somers } 7605d9e6103SBrian Somers 7615d9e6103SBrian Somers return bp; 7620053cc58SBrian Somers } 7630053cc58SBrian Somers 7645d9e6103SBrian Somers static struct mbuf * 7655d9e6103SBrian Somers ccp_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto) 7660053cc58SBrian Somers { 767ee6c193fSBrian Somers /* 768ed32233cSBrian Somers * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 769ee6c193fSBrian Somers * decompression routines so that the dictionary's updated 770ee6c193fSBrian Somers */ 7715d9e6103SBrian Somers if (l->ccp.fsm.state == ST_OPENED) { 772ed32233cSBrian Somers if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 7736815097bSBrian Somers log_Printf(LogDEBUG, "ccp_LayerPull: PROTO_%sCOMPDP -> PROTO_IP\n", 7746815097bSBrian Somers *proto == PROTO_ICOMPD ? "I" : ""); 7757308ec68SBrian Somers /* Decompress incoming data */ 7765d9e6103SBrian Somers if (l->ccp.reset_sent != -1) 77798baf7c8SBrian Somers /* Send another REQ and put the packet in the bit bucket */ 778411675baSBrian Somers fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 779411675baSBrian Somers MB_CCPOUT); 780411675baSBrian Somers else if (l->ccp.in.state != NULL) { 781411675baSBrian Somers bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 7825d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, proto, bp); 783411675baSBrian Somers switch (*proto) { 784411675baSBrian Somers case PROTO_ICOMPD: 78526af0ae9SBrian Somers m_settype(bp, MB_ICOMPDIN); 786411675baSBrian Somers break; 787411675baSBrian Somers case PROTO_COMPD: 78826af0ae9SBrian Somers m_settype(bp, MB_COMPDIN); 789411675baSBrian Somers break; 790411675baSBrian Somers } 791411675baSBrian Somers return bp; 792411675baSBrian Somers } 79326af0ae9SBrian Somers m_freem(bp); 794ee6c193fSBrian Somers bp = NULL; 7956815097bSBrian Somers } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 7966815097bSBrian Somers log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet (dict only)\n"); 797ee6c193fSBrian Somers /* Add incoming Network Layer traffic to our dictionary */ 7985d9e6103SBrian Somers (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 7995d9e6103SBrian Somers (l->ccp.in.state, &l->ccp, *proto, bp); 8006815097bSBrian Somers } else 8016815097bSBrian Somers log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet\n"); 8020053cc58SBrian Somers } 8030053cc58SBrian Somers 804ee6c193fSBrian Somers return bp; 8051ae349f5Scvs2svn } 806ed32233cSBrian Somers 807ed32233cSBrian Somers u_short 808ed32233cSBrian Somers ccp_Proto(struct ccp *ccp) 8090053cc58SBrian Somers { 810ed32233cSBrian Somers return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 811ed32233cSBrian Somers PROTO_COMPD : PROTO_ICOMPD; 8120053cc58SBrian Somers } 8131df0a3b9SBrian Somers 81406337856SBrian Somers int 8151df0a3b9SBrian Somers ccp_SetOpenMode(struct ccp *ccp) 8161df0a3b9SBrian Somers { 8171df0a3b9SBrian Somers int f; 8181df0a3b9SBrian Somers 8191df0a3b9SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 82006337856SBrian Somers if (IsEnabled(ccp->cfg.neg[f])) { 8211df0a3b9SBrian Somers ccp->fsm.open_mode = 0; 82206337856SBrian Somers return 1; 82306337856SBrian Somers } 8241df0a3b9SBrian Somers 82506337856SBrian Somers ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 82606337856SBrian Somers 82706337856SBrian Somers for (f = 0; f < CCP_NEG_TOTAL; f++) 82806337856SBrian Somers if (IsAccepted(ccp->cfg.neg[f])) 82906337856SBrian Somers return 1; 83006337856SBrian Somers 83106337856SBrian Somers return 0; /* No CCP at all */ 8321df0a3b9SBrian Somers } 8335d9e6103SBrian Somers 8347f89db65SBrian Somers int 8356cf6ee76SBrian Somers ccp_DefaultUsable(struct fsm *fp) 8367f89db65SBrian Somers { 8377f89db65SBrian Somers return 1; 8387f89db65SBrian Somers } 8397f89db65SBrian Somers 8406cf6ee76SBrian Somers int 8416cf6ee76SBrian Somers ccp_DefaultRequired(struct fsm *fp) 8426cf6ee76SBrian Somers { 8436cf6ee76SBrian Somers return 0; 8446cf6ee76SBrian Somers } 8456cf6ee76SBrian Somers 8465d9e6103SBrian Somers struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 847