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 * $Id: ccp.c,v 1.49 1999/05/12 09:48:43 brian Exp $ 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> 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 *ccp_TimerNames[] = 94 {"CCP restart", "CCP openmode", "CCP stopped"}; 95 96 static char const *cftypes[] = { 97 /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */ 98 "OUI", /* 0: OUI */ 99 "PRED1", /* 1: Predictor type 1 */ 100 "PRED2", /* 2: Predictor type 2 */ 101 "PUDDLE", /* 3: Puddle Jumber */ 102 "???", "???", "???", "???", "???", "???", 103 "???", "???", "???", "???", "???", "???", 104 "HWPPC", /* 16: Hewlett-Packard PPC */ 105 "STAC", /* 17: Stac Electronics LZS (rfc1974) */ 106 "MPPC", /* 18: Microsoft PPC (rfc2118) */ 107 "GAND", /* 19: Gandalf FZA (rfc1993) */ 108 "V42BIS", /* 20: ARG->DATA.42bis compression */ 109 "BSD", /* 21: BSD LZW Compress */ 110 "???", 111 "LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */ 112 "MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */ 113 /* 24: Deflate (according to pppd-2.3.*) */ 114 "DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */ 115 "DEFLATE", /* 26: Deflate (rfc1979) */ 116 }; 117 118 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 119 120 static const char * 121 protoname(int proto) 122 { 123 if (proto < 0 || proto > NCFTYPES) 124 return "none"; 125 return cftypes[proto]; 126 } 127 128 /* We support these algorithms, and Req them in the given order */ 129 static const struct ccp_algorithm *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 if (type < NCFTYPES) 445 log_Printf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end); 446 else 447 log_Printf(LogCCP, " ???[%d] %s\n", length, end); 448 449 if (f == -1) { 450 /* Don't understand that :-( */ 451 if (mode_type == MODE_REQ) { 452 ccp->my_reject |= (1 << type); 453 memcpy(dec->rejend, cp, length); 454 dec->rejend += length; 455 } 456 } else { 457 struct ccp_opt *o; 458 459 switch (mode_type) { 460 case MODE_REQ: 461 if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 462 ccp->in.algorithm == -1) { 463 memcpy(&ccp->in.opt, cp, length); 464 switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 465 case MODE_REJ: 466 memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 467 dec->rejend += ccp->in.opt.len; 468 break; 469 case MODE_NAK: 470 memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 471 dec->nakend += ccp->in.opt.len; 472 break; 473 case MODE_ACK: 474 memcpy(dec->ackend, cp, length); 475 dec->ackend += length; 476 ccp->his_proto = type; 477 ccp->in.algorithm = f; /* This one'll do :-) */ 478 break; 479 } 480 } else { 481 memcpy(dec->rejend, cp, length); 482 dec->rejend += length; 483 } 484 break; 485 case MODE_NAK: 486 for (o = ccp->out.opt; o != NULL; o = o->next) 487 if (o->val.id == cp[0]) 488 break; 489 if (o == NULL) 490 log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent option\n", 491 fp->link->name); 492 else { 493 memcpy(&o->val, cp, length); 494 if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 495 ccp->my_proto = algorithm[f]->id; 496 else { 497 ccp->his_reject |= (1 << type); 498 ccp->my_proto = -1; 499 } 500 } 501 break; 502 case MODE_REJ: 503 ccp->his_reject |= (1 << type); 504 ccp->my_proto = -1; 505 break; 506 } 507 } 508 509 plen -= cp[1]; 510 cp += cp[1]; 511 } 512 513 if (mode_type != MODE_NOP) { 514 if (dec->rejend != dec->rej) { 515 /* rejects are preferred */ 516 dec->ackend = dec->ack; 517 dec->nakend = dec->nak; 518 if (ccp->in.state == NULL) { 519 ccp->his_proto = -1; 520 ccp->in.algorithm = -1; 521 } 522 } else if (dec->nakend != dec->nak) { 523 /* then NAKs */ 524 dec->ackend = dec->ack; 525 if (ccp->in.state == NULL) { 526 ccp->his_proto = -1; 527 ccp->in.algorithm = -1; 528 } 529 } 530 } 531 } 532 533 extern struct mbuf * 534 ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 535 { 536 /* Got PROTO_CCP from link */ 537 mbuf_SetType(bp, MB_CCPIN); 538 if (bundle_Phase(bundle) == PHASE_NETWORK) 539 fsm_Input(&l->ccp.fsm, bp); 540 else { 541 if (bundle_Phase(bundle) < PHASE_NETWORK) 542 log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 543 l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 544 mbuf_Free(bp); 545 } 546 return NULL; 547 } 548 549 static void 550 CcpRecvResetAck(struct fsm *fp, u_char id) 551 { 552 /* Got a reset ACK, reset incoming dictionary */ 553 struct ccp *ccp = fsm2ccp(fp); 554 555 if (ccp->reset_sent != -1) { 556 if (id != ccp->reset_sent) { 557 log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 558 " ignored\n", fp->link->name, id, ccp->reset_sent); 559 return; 560 } 561 /* Whaddaya know - a correct reset ack */ 562 } else if (id == ccp->last_reset) 563 log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 564 fp->link->name); 565 else { 566 log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 567 fp->link->name, id); 568 return; 569 } 570 571 ccp->last_reset = ccp->reset_sent; 572 ccp->reset_sent = -1; 573 if (ccp->in.state != NULL) 574 (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 575 } 576 577 static struct mbuf * 578 ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, 579 int pri, u_short *proto) 580 { 581 if (PROTO_COMPRESSIBLE(*proto) && l->ccp.fsm.state == ST_OPENED && 582 l->ccp.out.state != NULL) { 583 bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 584 (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 585 switch (*proto) { 586 case PROTO_ICOMPD: 587 mbuf_SetType(bp, MB_ICOMPDOUT); 588 break; 589 case PROTO_COMPD: 590 mbuf_SetType(bp, MB_COMPDOUT); 591 break; 592 } 593 } 594 595 return bp; 596 } 597 598 static struct mbuf * 599 ccp_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto) 600 { 601 /* 602 * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 603 * decompression routines so that the dictionary's updated 604 */ 605 if (l->ccp.fsm.state == ST_OPENED) { 606 if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 607 log_Printf(LogDEBUG, "ccp_LayerPull: PROTO_%sCOMPDP -> PROTO_IP\n", 608 *proto == PROTO_ICOMPD ? "I" : ""); 609 /* Decompress incoming data */ 610 if (l->ccp.reset_sent != -1) 611 /* Send another REQ and put the packet in the bit bucket */ 612 fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 613 MB_CCPOUT); 614 else if (l->ccp.in.state != NULL) { 615 bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 616 (l->ccp.in.state, &l->ccp, proto, bp); 617 switch (*proto) { 618 case PROTO_ICOMPD: 619 mbuf_SetType(bp, MB_ICOMPDIN); 620 break; 621 case PROTO_COMPD: 622 mbuf_SetType(bp, MB_COMPDIN); 623 break; 624 } 625 return bp; 626 } 627 mbuf_Free(bp); 628 bp = NULL; 629 } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 630 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet (dict only)\n"); 631 /* Add incoming Network Layer traffic to our dictionary */ 632 (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 633 (l->ccp.in.state, &l->ccp, *proto, bp); 634 } else 635 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet\n"); 636 } 637 638 return bp; 639 } 640 641 u_short 642 ccp_Proto(struct ccp *ccp) 643 { 644 return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 645 PROTO_COMPD : PROTO_ICOMPD; 646 } 647 648 int 649 ccp_SetOpenMode(struct ccp *ccp) 650 { 651 int f; 652 653 for (f = 0; f < CCP_NEG_TOTAL; f++) 654 if (IsEnabled(ccp->cfg.neg[f])) { 655 ccp->fsm.open_mode = 0; 656 return 1; 657 } 658 659 ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 660 661 for (f = 0; f < CCP_NEG_TOTAL; f++) 662 if (IsAccepted(ccp->cfg.neg[f])) 663 return 1; 664 665 return 0; /* No CCP at all */ 666 } 667 668 struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 669