ccp.c revision 67910
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 67910 2000-10-30 00:15:04Z 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\n", 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] = 0; 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 273 if (!alloc) 274 for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) 275 if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) 276 break; 277 278 if (alloc || *o == NULL) { 279 *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); 280 (*o)->val.id = algorithm[f]->id; 281 (*o)->val.len = 2; 282 (*o)->next = NULL; 283 (*o)->algorithm = f; 284 (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); 285 } 286 287 if (cp + (*o)->val.len > buff + sizeof buff) { 288 log_Printf(LogERROR, "%s: CCP REQ buffer overrun !\n", fp->link->name); 289 break; 290 } 291 memcpy(cp, &(*o)->val, (*o)->val.len); 292 cp += (*o)->val.len; 293 294 ccp->my_proto = (*o)->val.id; 295 ccp->out.algorithm = f; 296 297 if (alloc) 298 o = &(*o)->next; 299 } 300 301 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, cp - buff, MB_CCPOUT); 302} 303 304void 305ccp_SendResetReq(struct fsm *fp) 306{ 307 /* We can't read our input - ask peer to reset */ 308 struct ccp *ccp = fsm2ccp(fp); 309 310 ccp->reset_sent = fp->reqid; 311 ccp->last_reset = -1; 312 fsm_Output(fp, CODE_RESETREQ, fp->reqid, NULL, 0, MB_CCPOUT); 313} 314 315static void 316CcpSentTerminateReq(struct fsm *fp) 317{ 318 /* Term REQ just sent by FSM */ 319} 320 321static void 322CcpSendTerminateAck(struct fsm *fp, u_char id) 323{ 324 /* Send Term ACK please */ 325 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_CCPOUT); 326} 327 328static void 329CcpRecvResetReq(struct fsm *fp) 330{ 331 /* Got a reset REQ, reset outgoing dictionary */ 332 struct ccp *ccp = fsm2ccp(fp); 333 if (ccp->out.state != NULL) 334 (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); 335} 336 337static void 338CcpLayerStart(struct fsm *fp) 339{ 340 /* We're about to start up ! */ 341 struct ccp *ccp = fsm2ccp(fp); 342 343 log_Printf(LogCCP, "%s: LayerStart.\n", fp->link->name); 344 fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 345} 346 347static void 348CcpLayerDown(struct fsm *fp) 349{ 350 /* About to come down */ 351 struct ccp *ccp = fsm2ccp(fp); 352 struct ccp_opt *next; 353 354 log_Printf(LogCCP, "%s: LayerDown.\n", fp->link->name); 355 if (ccp->in.state != NULL) { 356 (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); 357 ccp->in.state = NULL; 358 ccp->in.algorithm = -1; 359 } 360 if (ccp->out.state != NULL) { 361 (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); 362 ccp->out.state = NULL; 363 ccp->out.algorithm = -1; 364 } 365 ccp->his_reject = ccp->my_reject = 0; 366 367 while (ccp->out.opt) { 368 next = ccp->out.opt->next; 369 free(ccp->out.opt); 370 ccp->out.opt = next; 371 } 372 ccp_Setup(ccp); 373} 374 375static void 376CcpLayerFinish(struct fsm *fp) 377{ 378 /* We're now down */ 379 log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 380} 381 382/* Called when CCP has reached the OPEN state */ 383static int 384CcpLayerUp(struct fsm *fp) 385{ 386 /* We're now up */ 387 struct ccp *ccp = fsm2ccp(fp); 388 389 log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 390 391 if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 392 ccp->in.algorithm < NALGORITHMS) { 393 ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 394 if (ccp->in.state == NULL) { 395 log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 396 fp->link->name, protoname(ccp->his_proto)); 397 ccp->his_proto = ccp->my_proto = -1; 398 fsm_Close(fp); 399 return 0; 400 } 401 } 402 403 if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 404 ccp->out.algorithm < NALGORITHMS) { 405 ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) 406 (&ccp->out.opt->val); 407 if (ccp->out.state == NULL) { 408 log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 409 fp->link->name, protoname(ccp->my_proto)); 410 ccp->his_proto = ccp->my_proto = -1; 411 fsm_Close(fp); 412 return 0; 413 } 414 } 415 416 fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 417 418 log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 419 fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 420 protoname(ccp->his_proto), ccp->his_proto); 421 422 return 1; 423} 424 425static void 426CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 427 struct fsm_decode *dec) 428{ 429 /* Deal with incoming data */ 430 struct ccp *ccp = fsm2ccp(fp); 431 int type, length, f; 432 const char *end; 433 434 if (mode_type == MODE_REQ) 435 ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 436 437 while (plen >= sizeof(struct fsmconfig)) { 438 type = *cp; 439 length = cp[1]; 440 441 if (length == 0) { 442 log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name); 443 break; 444 } 445 446 if (length > sizeof(struct lcp_opt)) { 447 length = sizeof(struct lcp_opt); 448 log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n", 449 fp->link->name, length); 450 } 451 452 for (f = NALGORITHMS-1; f > -1; f--) 453 if (algorithm[f]->id == type) 454 break; 455 456 end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 457 if (end == NULL) 458 end = ""; 459 460 log_Printf(LogCCP, " %s[%d] %s\n", protoname(type), length, end); 461 462 if (f == -1) { 463 /* Don't understand that :-( */ 464 if (mode_type == MODE_REQ) { 465 ccp->my_reject |= (1 << type); 466 memcpy(dec->rejend, cp, length); 467 dec->rejend += length; 468 } 469 } else { 470 struct ccp_opt *o; 471 472 switch (mode_type) { 473 case MODE_REQ: 474 if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 475 ccp->in.algorithm == -1) { 476 memcpy(&ccp->in.opt, cp, length); 477 switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 478 case MODE_REJ: 479 memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 480 dec->rejend += ccp->in.opt.len; 481 break; 482 case MODE_NAK: 483 memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 484 dec->nakend += ccp->in.opt.len; 485 break; 486 case MODE_ACK: 487 memcpy(dec->ackend, cp, length); 488 dec->ackend += length; 489 ccp->his_proto = type; 490 ccp->in.algorithm = f; /* This one'll do :-) */ 491 break; 492 } 493 } else { 494 memcpy(dec->rejend, cp, length); 495 dec->rejend += length; 496 } 497 break; 498 case MODE_NAK: 499 for (o = ccp->out.opt; o != NULL; o = o->next) 500 if (o->val.id == cp[0]) 501 break; 502 if (o == NULL) 503 log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent option\n", 504 fp->link->name); 505 else { 506 memcpy(&o->val, cp, length); 507 if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 508 ccp->my_proto = algorithm[f]->id; 509 else { 510 ccp->his_reject |= (1 << type); 511 ccp->my_proto = -1; 512 } 513 } 514 break; 515 case MODE_REJ: 516 ccp->his_reject |= (1 << type); 517 ccp->my_proto = -1; 518 break; 519 } 520 } 521 522 plen -= cp[1]; 523 cp += cp[1]; 524 } 525 526 if (mode_type != MODE_NOP) { 527 if (dec->rejend != dec->rej) { 528 /* rejects are preferred */ 529 dec->ackend = dec->ack; 530 dec->nakend = dec->nak; 531 if (ccp->in.state == NULL) { 532 ccp->his_proto = -1; 533 ccp->in.algorithm = -1; 534 } 535 } else if (dec->nakend != dec->nak) { 536 /* then NAKs */ 537 dec->ackend = dec->ack; 538 if (ccp->in.state == NULL) { 539 ccp->his_proto = -1; 540 ccp->in.algorithm = -1; 541 } 542 } 543 } 544} 545 546extern struct mbuf * 547ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 548{ 549 /* Got PROTO_CCP from link */ 550 m_settype(bp, MB_CCPIN); 551 if (bundle_Phase(bundle) == PHASE_NETWORK) 552 fsm_Input(&l->ccp.fsm, bp); 553 else { 554 if (bundle_Phase(bundle) < PHASE_NETWORK) 555 log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 556 l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 557 m_freem(bp); 558 } 559 return NULL; 560} 561 562static void 563CcpRecvResetAck(struct fsm *fp, u_char id) 564{ 565 /* Got a reset ACK, reset incoming dictionary */ 566 struct ccp *ccp = fsm2ccp(fp); 567 568 if (ccp->reset_sent != -1) { 569 if (id != ccp->reset_sent) { 570 log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 571 " ignored\n", fp->link->name, id, ccp->reset_sent); 572 return; 573 } 574 /* Whaddaya know - a correct reset ack */ 575 } else if (id == ccp->last_reset) 576 log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 577 fp->link->name); 578 else { 579 log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 580 fp->link->name, id); 581 return; 582 } 583 584 ccp->last_reset = ccp->reset_sent; 585 ccp->reset_sent = -1; 586 if (ccp->in.state != NULL) 587 (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 588} 589 590static struct mbuf * 591ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, 592 int pri, u_short *proto) 593{ 594 if (PROTO_COMPRESSIBLE(*proto) && l->ccp.fsm.state == ST_OPENED && 595 l->ccp.out.state != NULL) { 596 bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 597 (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 598 switch (*proto) { 599 case PROTO_ICOMPD: 600 m_settype(bp, MB_ICOMPDOUT); 601 break; 602 case PROTO_COMPD: 603 m_settype(bp, MB_COMPDOUT); 604 break; 605 } 606 } 607 608 return bp; 609} 610 611static struct mbuf * 612ccp_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto) 613{ 614 /* 615 * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 616 * decompression routines so that the dictionary's updated 617 */ 618 if (l->ccp.fsm.state == ST_OPENED) { 619 if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 620 log_Printf(LogDEBUG, "ccp_LayerPull: PROTO_%sCOMPDP -> PROTO_IP\n", 621 *proto == PROTO_ICOMPD ? "I" : ""); 622 /* Decompress incoming data */ 623 if (l->ccp.reset_sent != -1) 624 /* Send another REQ and put the packet in the bit bucket */ 625 fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 626 MB_CCPOUT); 627 else if (l->ccp.in.state != NULL) { 628 bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 629 (l->ccp.in.state, &l->ccp, proto, bp); 630 switch (*proto) { 631 case PROTO_ICOMPD: 632 m_settype(bp, MB_ICOMPDIN); 633 break; 634 case PROTO_COMPD: 635 m_settype(bp, MB_COMPDIN); 636 break; 637 } 638 return bp; 639 } 640 m_freem(bp); 641 bp = NULL; 642 } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 643 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet (dict only)\n"); 644 /* Add incoming Network Layer traffic to our dictionary */ 645 (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 646 (l->ccp.in.state, &l->ccp, *proto, bp); 647 } else 648 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet\n"); 649 } 650 651 return bp; 652} 653 654u_short 655ccp_Proto(struct ccp *ccp) 656{ 657 return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 658 PROTO_COMPD : PROTO_ICOMPD; 659} 660 661int 662ccp_SetOpenMode(struct ccp *ccp) 663{ 664 int f; 665 666 for (f = 0; f < CCP_NEG_TOTAL; f++) 667 if (IsEnabled(ccp->cfg.neg[f])) { 668 ccp->fsm.open_mode = 0; 669 return 1; 670 } 671 672 ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 673 674 for (f = 0; f < CCP_NEG_TOTAL; f++) 675 if (IsAccepted(ccp->cfg.neg[f])) 676 return 1; 677 678 return 0; /* No CCP at all */ 679} 680 681struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 682