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