1 /*- 2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 4 * Internet Initiative Japan, Inc (IIJ) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <netinet/in.h> 33 #include <netinet/in_systm.h> 34 #include <netinet/ip.h> 35 #include <sys/socket.h> 36 #include <sys/un.h> 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> /* memcpy() on some archs */ 41 #include <termios.h> 42 43 #include "layer.h" 44 #include "defs.h" 45 #include "command.h" 46 #include "mbuf.h" 47 #include "log.h" 48 #include "timer.h" 49 #include "fsm.h" 50 #include "proto.h" 51 #include "pred.h" 52 #include "deflate.h" 53 #include "throughput.h" 54 #include "iplist.h" 55 #include "slcompress.h" 56 #include "lqr.h" 57 #include "hdlc.h" 58 #include "lcp.h" 59 #include "ccp.h" 60 #include "ncpaddr.h" 61 #include "ip.h" 62 #include "ipcp.h" 63 #include "filter.h" 64 #include "descriptor.h" 65 #include "prompt.h" 66 #include "link.h" 67 #include "mp.h" 68 #include "async.h" 69 #include "physical.h" 70 #ifndef NORADIUS 71 #include "radius.h" 72 #endif 73 #ifdef HAVE_DES 74 #include "mppe.h" 75 #endif 76 #include "ipv6cp.h" 77 #include "ncp.h" 78 #include "bundle.h" 79 80 static void CcpSendConfigReq(struct fsm *); 81 static void CcpSentTerminateReq(struct fsm *); 82 static void CcpSendTerminateAck(struct fsm *, u_char); 83 static void CcpDecodeConfig(struct fsm *, u_char *, int, int, 84 struct fsm_decode *); 85 static void CcpLayerStart(struct fsm *); 86 static void CcpLayerFinish(struct fsm *); 87 static int CcpLayerUp(struct fsm *); 88 static void CcpLayerDown(struct fsm *); 89 static void CcpInitRestartCounter(struct fsm *, int); 90 static int CcpRecvResetReq(struct fsm *); 91 static void CcpRecvResetAck(struct fsm *, u_char); 92 93 static struct fsm_callbacks ccp_Callbacks = { 94 CcpLayerUp, 95 CcpLayerDown, 96 CcpLayerStart, 97 CcpLayerFinish, 98 CcpInitRestartCounter, 99 CcpSendConfigReq, 100 CcpSentTerminateReq, 101 CcpSendTerminateAck, 102 CcpDecodeConfig, 103 CcpRecvResetReq, 104 CcpRecvResetAck 105 }; 106 107 static const char * const ccp_TimerNames[] = 108 {"CCP restart", "CCP openmode", "CCP stopped"}; 109 110 static const char * 111 protoname(int proto) 112 { 113 static char const * const cftypes[] = { 114 /* Check out the latest ``Compression Control Protocol'' rfc (1962) */ 115 "OUI", /* 0: OUI */ 116 "PRED1", /* 1: Predictor type 1 */ 117 "PRED2", /* 2: Predictor type 2 */ 118 "PUDDLE", /* 3: Puddle Jumber */ 119 NULL, NULL, NULL, NULL, NULL, NULL, 120 NULL, NULL, NULL, NULL, NULL, NULL, 121 "HWPPC", /* 16: Hewlett-Packard PPC */ 122 "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 123 "MPPE", /* 18: Microsoft PPC (rfc2118) and */ 124 /* Microsoft PPE (draft-ietf-pppext-mppe) */ 125 "GAND", /* 19: Gandalf FZA (rfc1993) */ 126 "V42BIS", /* 20: ARG->DATA.42bis compression */ 127 "BSD", /* 21: BSD LZW Compress */ 128 NULL, 129 "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 130 "MAGNALINK/DEFLATE",/* 24: Magnalink Variable Resource (rfc1975) */ 131 /* 24: Deflate (according to pppd-2.3.*) */ 132 "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 133 "DEFLATE", /* 26: Deflate (rfc1979) */ 134 }; 135 136 if (proto < 0 || proto > sizeof cftypes / sizeof *cftypes || 137 cftypes[proto] == NULL) 138 return HexStr(proto, NULL, 0); 139 140 return cftypes[proto]; 141 } 142 143 /* We support these algorithms, and Req them in the given order */ 144 static const struct ccp_algorithm * const algorithm[] = { 145 &DeflateAlgorithm, 146 &Pred1Algorithm, 147 &PppdDeflateAlgorithm 148 #ifdef HAVE_DES 149 , &MPPEAlgorithm 150 #endif 151 }; 152 153 #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0]) 154 155 int 156 ccp_ReportStatus(struct cmdargs const *arg) 157 { 158 struct ccp_opt **o; 159 struct link *l; 160 struct ccp *ccp; 161 int f; 162 163 l = command_ChooseLink(arg); 164 ccp = &l->ccp; 165 166 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, ccp->fsm.name, 167 State2Nam(ccp->fsm.state)); 168 if (ccp->fsm.state == ST_OPENED) { 169 prompt_Printf(arg->prompt, " My protocol = %s, His protocol = %s\n", 170 protoname(ccp->my_proto), protoname(ccp->his_proto)); 171 prompt_Printf(arg->prompt, " Output: %ld --> %ld, Input: %ld --> %ld\n", 172 ccp->uncompout, ccp->compout, 173 ccp->compin, ccp->uncompin); 174 } 175 176 if (ccp->in.algorithm != -1) 177 prompt_Printf(arg->prompt, "\n Input Options: %s\n", 178 (*algorithm[ccp->in.algorithm]->Disp)(&ccp->in.opt)); 179 180 if (ccp->out.algorithm != -1) { 181 o = &ccp->out.opt; 182 for (f = 0; f < ccp->out.algorithm; f++) 183 if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 184 o = &(*o)->next; 185 prompt_Printf(arg->prompt, " Output Options: %s\n", 186 (*algorithm[ccp->out.algorithm]->Disp)(&(*o)->val)); 187 } 188 189 prompt_Printf(arg->prompt, "\n Defaults: "); 190 prompt_Printf(arg->prompt, "FSM retry = %us, max %u Config" 191 " REQ%s, %u Term REQ%s\n", ccp->cfg.fsm.timeout, 192 ccp->cfg.fsm.maxreq, ccp->cfg.fsm.maxreq == 1 ? "" : "s", 193 ccp->cfg.fsm.maxtrm, ccp->cfg.fsm.maxtrm == 1 ? "" : "s"); 194 prompt_Printf(arg->prompt, " deflate windows: "); 195 prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); 196 prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); 197 #ifdef HAVE_DES 198 prompt_Printf(arg->prompt, " MPPE: "); 199 if (ccp->cfg.mppe.keybits) 200 prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits); 201 else 202 prompt_Printf(arg->prompt, "any bits, "); 203 switch (ccp->cfg.mppe.state) { 204 case MPPE_STATEFUL: 205 prompt_Printf(arg->prompt, "stateful"); 206 break; 207 case MPPE_STATELESS: 208 prompt_Printf(arg->prompt, "stateless"); 209 break; 210 case MPPE_ANYSTATE: 211 prompt_Printf(arg->prompt, "any state"); 212 break; 213 } 214 prompt_Printf(arg->prompt, "%s\n", 215 ccp->cfg.mppe.required ? ", required" : ""); 216 #endif 217 218 prompt_Printf(arg->prompt, "\n DEFLATE: %s\n", 219 command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE])); 220 prompt_Printf(arg->prompt, " PREDICTOR1: %s\n", 221 command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); 222 prompt_Printf(arg->prompt, " DEFLATE24: %s\n", 223 command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); 224 #ifdef HAVE_DES 225 prompt_Printf(arg->prompt, " MPPE: %s\n", 226 command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE])); 227 #endif 228 return 0; 229 } 230 231 void 232 ccp_SetupCallbacks(struct ccp *ccp) 233 { 234 ccp->fsm.fn = &ccp_Callbacks; 235 ccp->fsm.FsmTimer.name = ccp_TimerNames[0]; 236 ccp->fsm.OpenTimer.name = ccp_TimerNames[1]; 237 ccp->fsm.StoppedTimer.name = ccp_TimerNames[2]; 238 } 239 240 void 241 ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, 242 const struct fsm_parent *parent) 243 { 244 /* Initialise ourselves */ 245 246 fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, 1, CCP_MAXCODE, LogCCP, 247 bundle, l, parent, &ccp_Callbacks, ccp_TimerNames); 248 249 ccp->cfg.deflate.in.winsize = 0; 250 ccp->cfg.deflate.out.winsize = 15; 251 ccp->cfg.fsm.timeout = DEF_FSMRETRY; 252 ccp->cfg.fsm.maxreq = DEF_FSMTRIES; 253 ccp->cfg.fsm.maxtrm = DEF_FSMTRIES; 254 ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; 255 ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; 256 ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; 257 #ifdef HAVE_DES 258 ccp->cfg.mppe.keybits = 0; 259 ccp->cfg.mppe.state = MPPE_ANYSTATE; 260 ccp->cfg.mppe.required = 0; 261 ccp->cfg.neg[CCP_NEG_MPPE] = NEG_ENABLED|NEG_ACCEPTED; 262 #endif 263 264 ccp_Setup(ccp); 265 } 266 267 void 268 ccp_Setup(struct ccp *ccp) 269 { 270 /* Set ourselves up for a startup */ 271 ccp->fsm.open_mode = 0; 272 ccp->his_proto = ccp->my_proto = -1; 273 ccp->reset_sent = ccp->last_reset = -1; 274 ccp->in.algorithm = ccp->out.algorithm = -1; 275 ccp->in.state = ccp->out.state = NULL; 276 ccp->in.opt.id = -1; 277 ccp->out.opt = NULL; 278 ccp->his_reject = ccp->my_reject = 0; 279 ccp->uncompout = ccp->compout = 0; 280 ccp->uncompin = ccp->compin = 0; 281 } 282 283 /* 284 * Is ccp *REQUIRED* ? 285 * We ask each of the configured ccp protocols if they're required and 286 * return TRUE if they are. 287 * 288 * It's not possible for the peer to reject a required ccp protocol 289 * without our state machine bringing the supporting lcp layer down. 290 * 291 * If ccp is required but not open, the NCP layer should not push 292 * any data into the link. 293 */ 294 int 295 ccp_Required(struct ccp *ccp) 296 { 297 int f; 298 299 for (f = 0; f < NALGORITHMS; f++) 300 if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 301 (*algorithm[f]->Required)(&ccp->fsm)) 302 return 1; 303 304 return 0; 305 } 306 307 /* 308 * Report whether it's possible to increase a packet's size after 309 * compression (and by how much). 310 */ 311 int 312 ccp_MTUOverhead(struct ccp *ccp) 313 { 314 if (ccp->fsm.state == ST_OPENED && ccp->out.algorithm >= 0) 315 return algorithm[ccp->out.algorithm]->o.MTUOverhead; 316 317 return 0; 318 } 319 320 static void 321 CcpInitRestartCounter(struct fsm *fp, int what) 322 { 323 /* Set fsm timer load */ 324 struct ccp *ccp = fsm2ccp(fp); 325 326 fp->FsmTimer.load = ccp->cfg.fsm.timeout * SECTICKS; 327 switch (what) { 328 case FSM_REQ_TIMER: 329 fp->restart = ccp->cfg.fsm.maxreq; 330 break; 331 case FSM_TRM_TIMER: 332 fp->restart = ccp->cfg.fsm.maxtrm; 333 break; 334 default: 335 fp->restart = 1; 336 break; 337 } 338 } 339 340 static void 341 CcpSendConfigReq(struct fsm *fp) 342 { 343 /* Send config REQ please */ 344 struct ccp *ccp = fsm2ccp(fp); 345 struct ccp_opt **o; 346 u_char *cp, buff[100]; 347 int f, alloc; 348 349 cp = buff; 350 o = &ccp->out.opt; 351 alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; 352 ccp->my_proto = -1; 353 ccp->out.algorithm = -1; 354 for (f = 0; f < NALGORITHMS; f++) 355 if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 356 !REJECTED(ccp, algorithm[f]->id) && 357 (*algorithm[f]->Usable)(fp)) { 358 359 if (!alloc) 360 for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 361 if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 362 break; 363 364 if (alloc || *o == NULL) { 365 *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 366 (*o)->val.id = algorithm[f]->id; 367 (*o)->val.len = 2; 368 (*o)->next = NULL; 369 (*o)->algorithm = f; 370 (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 371 } 372 373 if (cp + (*o)->val.len > buff + sizeof buff) { 374 log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 375 break; 376 } 377 memcpy(cp, &(*o)->val, (*o)->val.len); 378 cp += (*o)->val.len; 379 380 ccp->my_proto = (*o)->val.id; 381 ccp->out.algorithm = f; 382 383 if (alloc) 384 o = &(*o)->next; 385 } 386 387 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT); 388 } 389 390 void 391 ccp_SendResetReq(struct fsm *fp) 392 { 393 /* We can't read our input - ask peer to reset */ 394 struct ccp *ccp = fsm2ccp(fp); 395 396 ccp->reset_sent = fp->reqid; 397 ccp->last_reset = -1; 398 fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT); 399 } 400 401 static void 402 CcpSentTerminateReq(struct fsm *fp) 403 { 404 /* Term REQ just sent by FSM */ 405 } 406 407 static void 408 CcpSendTerminateAck(struct fsm *fp, u_char id) 409 { 410 /* Send Term ACK please */ 411 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); 412 } 413 414 static int 415 CcpRecvResetReq(struct fsm *fp) 416 { 417 /* Got a reset REQ, reset outgoing dictionary */ 418 struct ccp *ccp = fsm2ccp(fp); 419 if (ccp->out.state == NULL) 420 return 1; 421 return (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 422 } 423 424 static void 425 CcpLayerStart(struct fsm *fp) 426 { 427 /* We're about to start up ! */ 428 struct ccp *ccp = fsm2ccp(fp); 429 430 log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name); 431 fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 432 } 433 434 static void 435 CcpLayerDown(struct fsm *fp) 436 { 437 /* About to come down */ 438 struct ccp *ccp = fsm2ccp(fp); 439 struct ccp_opt *next; 440 441 log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name); 442 if (ccp->in.state != NULL) { 443 (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 444 ccp->in.state = NULL; 445 ccp->in.algorithm = -1; 446 } 447 if (ccp->out.state != NULL) { 448 (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 449 ccp->out.state = NULL; 450 ccp->out.algorithm = -1; 451 } 452 ccp->his_reject = ccp->my_reject = 0; 453 454 while (ccp->out.opt) { 455 next = ccp->out.opt->next; 456 free(ccp->out.opt); 457 ccp->out.opt = next; 458 } 459 ccp_Setup(ccp); 460 } 461 462 static void 463 CcpLayerFinish(struct fsm *fp) 464 { 465 /* We're now down */ 466 struct ccp *ccp = fsm2ccp(fp); 467 struct ccp_opt *next; 468 469 log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 470 471 /* 472 * Nuke options that may be left over from sending a REQ but never 473 * coming up. 474 */ 475 while (ccp->out.opt) { 476 next = ccp->out.opt->next; 477 free(ccp->out.opt); 478 ccp->out.opt = next; 479 } 480 481 if (ccp_Required(ccp)) { 482 if (fp->link->lcp.fsm.state == ST_OPENED) 483 log_Printf(LogLCP, "%s: Closing due to CCP completion\n", fp->link->name); 484 fsm_Close(&fp->link->lcp.fsm); 485 } 486 } 487 488 /* Called when CCP has reached the OPEN state */ 489 static int 490 CcpLayerUp(struct fsm *fp) 491 { 492 /* We're now up */ 493 struct ccp *ccp = fsm2ccp(fp); 494 struct ccp_opt **o; 495 int f, fail; 496 497 for (f = fail = 0; f < NALGORITHMS; f++) 498 if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg]) && 499 (*algorithm[f]->Required)(&ccp->fsm) && 500 (ccp->in.algorithm != f || ccp->out.algorithm != f)) { 501 /* Blow it all away - we haven't negotiated a required algorithm */ 502 log_Printf(LogWARN, "%s: Failed to negotiate (required) %s\n", 503 fp->link->name, protoname(algorithm[f]->id)); 504 fail = 1; 505 } 506 507 if (fail) { 508 ccp->his_proto = ccp->my_proto = -1; 509 fsm_Close(fp); 510 fsm_Close(&fp->link->lcp.fsm); 511 return 0; 512 } 513 514 log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 515 516 if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 517 ccp->in.algorithm < NALGORITHMS) { 518 ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 519 if (ccp->in.state == NULL) { 520 log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 521 fp->link->name, protoname(ccp->his_proto)); 522 ccp->his_proto = ccp->my_proto = -1; 523 fsm_Close(fp); 524 return 0; 525 } 526 } 527 528 o = &ccp->out.opt; 529 for (f = 0; f < ccp->out.algorithm; f++) 530 if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 531 o = &(*o)->next; 532 533 if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 534 ccp->out.algorithm < NALGORITHMS) { 535 ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)(&(*o)->val); 536 if (ccp->out.state == NULL) { 537 log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 538 fp->link->name, protoname(ccp->my_proto)); 539 ccp->his_proto = ccp->my_proto = -1; 540 fsm_Close(fp); 541 return 0; 542 } 543 } 544 545 fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 546 547 log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 548 fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 549 protoname(ccp->his_proto), ccp->his_proto); 550 551 return 1; 552 } 553 554 static void 555 CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 556 struct fsm_decode *dec) 557 { 558 /* Deal with incoming data */ 559 struct ccp *ccp = fsm2ccp(fp); 560 int type, length, f; 561 const char *end; 562 563 if (mode_type == MODE_REQ) 564 ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 565 566 while (plen >= sizeof(struct fsmconfig)) { 567 type = *cp; 568 length = cp[1]; 569 570 if (length == 0) { 571 log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name); 572 break; 573 } 574 575 if (length > sizeof(struct lcp_opt)) { 576 length = sizeof(struct lcp_opt); 577 log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n", 578 fp->link->name, length); 579 } 580 581 for (f = NALGORITHMS-1; f > -1; f--) 582 if (algorithm[f]->id == type) 583 break; 584 585 end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 586 if (end == NULL) 587 end = ""; 588 589 log_Printf(LogCCP, " %s[%d] %s\n", protoname(type), length, end); 590 591 if (f == -1) { 592 /* Don't understand that :-( */ 593 if (mode_type == MODE_REQ) { 594 ccp->my_reject |= (1 << type); 595 memcpy(dec->rejend, cp, length); 596 dec->rejend += length; 597 } 598 } else { 599 struct ccp_opt *o; 600 601 switch (mode_type) { 602 case MODE_REQ: 603 if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 604 (*algorithm[f]->Usable)(fp) && 605 ccp->in.algorithm == -1) { 606 memcpy(&ccp->in.opt, cp, length); 607 switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 608 case MODE_REJ: 609 memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 610 dec->rejend += ccp->in.opt.len; 611 break; 612 case MODE_NAK: 613 memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 614 dec->nakend += ccp->in.opt.len; 615 break; 616 case MODE_ACK: 617 memcpy(dec->ackend, cp, length); 618 dec->ackend += length; 619 ccp->his_proto = type; 620 ccp->in.algorithm = f; /* This one'll do :-) */ 621 break; 622 } 623 } else { 624 memcpy(dec->rejend, cp, length); 625 dec->rejend += length; 626 } 627 break; 628 case MODE_NAK: 629 for (o = ccp->out.opt; o != NULL; o = o->next) 630 if (o->val.id == cp[0]) 631 break; 632 if (o == NULL) 633 log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" 634 " option\n", fp->link->name); 635 else { 636 memcpy(&o->val, cp, length); 637 if ((*algorithm[f]->o.Set)(&o->val, &ccp->cfg) == MODE_ACK) 638 ccp->my_proto = algorithm[f]->id; 639 else { 640 ccp->his_reject |= (1 << type); 641 ccp->my_proto = -1; 642 if (algorithm[f]->Required(fp)) { 643 log_Printf(LogWARN, "%s: Cannot understand peers (required)" 644 " %s negotiation\n", fp->link->name, 645 protoname(algorithm[f]->id)); 646 fsm_Close(&fp->link->lcp.fsm); 647 } 648 } 649 } 650 break; 651 case MODE_REJ: 652 ccp->his_reject |= (1 << type); 653 ccp->my_proto = -1; 654 if (algorithm[f]->Required(fp)) { 655 log_Printf(LogWARN, "%s: Peer rejected (required) %s negotiation\n", 656 fp->link->name, protoname(algorithm[f]->id)); 657 fsm_Close(&fp->link->lcp.fsm); 658 } 659 break; 660 } 661 } 662 663 plen -= cp[1]; 664 cp += cp[1]; 665 } 666 667 if (mode_type != MODE_NOP) { 668 if (dec->rejend != dec->rej) { 669 /* rejects are preferred */ 670 dec->ackend = dec->ack; 671 dec->nakend = dec->nak; 672 if (ccp->in.state == NULL) { 673 ccp->his_proto = -1; 674 ccp->in.algorithm = -1; 675 } 676 } else if (dec->nakend != dec->nak) { 677 /* then NAKs */ 678 dec->ackend = dec->ack; 679 if (ccp->in.state == NULL) { 680 ccp->his_proto = -1; 681 ccp->in.algorithm = -1; 682 } 683 } 684 } 685 } 686 687 extern struct mbuf * 688 ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 689 { 690 /* Got PROTO_CCP from link */ 691 m_settype(bp, MB_CCPIN); 692 if (bundle_Phase(bundle) == PHASE_NETWORK) 693 fsm_Input(&l->ccp.fsm, bp); 694 else { 695 if (bundle_Phase(bundle) < PHASE_NETWORK) 696 log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 697 l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 698 m_freem(bp); 699 } 700 return NULL; 701 } 702 703 static void 704 CcpRecvResetAck(struct fsm *fp, u_char id) 705 { 706 /* Got a reset ACK, reset incoming dictionary */ 707 struct ccp *ccp = fsm2ccp(fp); 708 709 if (ccp->reset_sent != -1) { 710 if (id != ccp->reset_sent) { 711 log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 712 " ignored\n", fp->link->name, id, ccp->reset_sent); 713 return; 714 } 715 /* Whaddaya know - a correct reset ack */ 716 } else if (id == ccp->last_reset) 717 log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 718 fp->link->name); 719 else { 720 log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 721 fp->link->name, id); 722 return; 723 } 724 725 ccp->last_reset = ccp->reset_sent; 726 ccp->reset_sent = -1; 727 if (ccp->in.state != NULL) 728 (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 729 } 730 731 static struct mbuf * 732 ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, 733 int pri, u_short *proto) 734 { 735 if (PROTO_COMPRESSIBLE(*proto)) { 736 if (l->ccp.fsm.state != ST_OPENED) { 737 if (ccp_Required(&l->ccp)) { 738 /* The NCP layer shouldn't have let this happen ! */ 739 log_Printf(LogERROR, "%s: Unexpected attempt to use an unopened and" 740 " required CCP layer\n", l->name); 741 m_freem(bp); 742 bp = NULL; 743 } 744 } else if (l->ccp.out.state != NULL) { 745 bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 746 (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 747 switch (*proto) { 748 case PROTO_ICOMPD: 749 m_settype(bp, MB_ICOMPDOUT); 750 break; 751 case PROTO_COMPD: 752 m_settype(bp, MB_COMPDOUT); 753 break; 754 } 755 } 756 } 757 758 return bp; 759 } 760 761 static struct mbuf * 762 ccp_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto) 763 { 764 /* 765 * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 766 * decompression routines so that the dictionary's updated 767 */ 768 if (l->ccp.fsm.state == ST_OPENED) { 769 if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 770 log_Printf(LogDEBUG, "ccp_LayerPull: PROTO_%sCOMPDP -> PROTO_IP\n", 771 *proto == PROTO_ICOMPD ? "I" : ""); 772 /* Decompress incoming data */ 773 if (l->ccp.reset_sent != -1) 774 /* Send another REQ and put the packet in the bit bucket */ 775 fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 776 MB_CCPOUT); 777 else if (l->ccp.in.state != NULL) { 778 bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 779 (l->ccp.in.state, &l->ccp, proto, bp); 780 switch (*proto) { 781 case PROTO_ICOMPD: 782 m_settype(bp, MB_ICOMPDIN); 783 break; 784 case PROTO_COMPD: 785 m_settype(bp, MB_COMPDIN); 786 break; 787 } 788 return bp; 789 } 790 m_freem(bp); 791 bp = NULL; 792 } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 793 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet (dict only)\n"); 794 /* Add incoming Network Layer traffic to our dictionary */ 795 (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 796 (l->ccp.in.state, &l->ccp, *proto, bp); 797 } else 798 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet\n"); 799 } 800 801 return bp; 802 } 803 804 u_short 805 ccp_Proto(struct ccp *ccp) 806 { 807 return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 808 PROTO_COMPD : PROTO_ICOMPD; 809 } 810 811 int 812 ccp_SetOpenMode(struct ccp *ccp) 813 { 814 int f; 815 816 for (f = 0; f < CCP_NEG_TOTAL; f++) 817 if (IsEnabled(ccp->cfg.neg[f])) { 818 ccp->fsm.open_mode = 0; 819 return 1; 820 } 821 822 ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 823 824 for (f = 0; f < CCP_NEG_TOTAL; f++) 825 if (IsAccepted(ccp->cfg.neg[f])) 826 return 1; 827 828 return 0; /* No CCP at all */ 829 } 830 831 int 832 ccp_DefaultUsable(struct fsm *fp) 833 { 834 return 1; 835 } 836 837 int 838 ccp_DefaultRequired(struct fsm *fp) 839 { 840 return 0; 841 } 842 843 struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 844