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