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 "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 69 static void CcpSendConfigReq(struct fsm *); 70 static void CcpSentTerminateReq(struct fsm *); 71 static void CcpSendTerminateAck(struct fsm *, u_char); 72 static void CcpDecodeConfig(struct fsm *, u_char *, int, int, 73 struct fsm_decode *); 74 static void CcpLayerStart(struct fsm *); 75 static void CcpLayerFinish(struct fsm *); 76 static int CcpLayerUp(struct fsm *); 77 static void CcpLayerDown(struct fsm *); 78 static void CcpInitRestartCounter(struct fsm *, int); 79 static void CcpRecvResetReq(struct fsm *); 80 static void CcpRecvResetAck(struct fsm *, u_char); 81 82 static 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 96 static const char * const ccp_TimerNames[] = 97 {"CCP restart", "CCP openmode", "CCP stopped"}; 98 99 static const char * 100 protoname(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 */ 133 static 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 144 int 145 ccp_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 185 void 186 ccp_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 194 void 195 ccp_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 219 void 220 ccp_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 235 static void 236 CcpInitRestartCounter(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 255 static void 256 CcpSendConfigReq(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 304 void 305 ccp_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 315 static void 316 CcpSentTerminateReq(struct fsm *fp) 317 { 318 /* Term REQ just sent by FSM */ 319 } 320 321 static void 322 CcpSendTerminateAck(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 328 static void 329 CcpRecvResetReq(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 337 static void 338 CcpLayerStart(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 347 static void 348 CcpLayerDown(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 375 static void 376 CcpLayerFinish(struct fsm *fp) 377 { 378 /* We're now down */ 379 struct ccp *ccp = fsm2ccp(fp); 380 struct ccp_opt *next; 381 382 log_Printf(LogCCP, "%s: LayerFinish.\n", fp->link->name); 383 384 /* 385 * Nuke options that may be left over from sending a REQ but never 386 * coming up. 387 */ 388 while (ccp->out.opt) { 389 next = ccp->out.opt->next; 390 free(ccp->out.opt); 391 ccp->out.opt = next; 392 } 393 } 394 395 /* Called when CCP has reached the OPEN state */ 396 static int 397 CcpLayerUp(struct fsm *fp) 398 { 399 /* We're now up */ 400 struct ccp *ccp = fsm2ccp(fp); 401 struct ccp_opt **o; 402 int f; 403 404 log_Printf(LogCCP, "%s: LayerUp.\n", fp->link->name); 405 406 if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && 407 ccp->in.algorithm < NALGORITHMS) { 408 ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); 409 if (ccp->in.state == NULL) { 410 log_Printf(LogERROR, "%s: %s (in) initialisation failure\n", 411 fp->link->name, protoname(ccp->his_proto)); 412 ccp->his_proto = ccp->my_proto = -1; 413 fsm_Close(fp); 414 return 0; 415 } 416 } 417 418 o = &ccp->out.opt; 419 for (f = 0; f < ccp->out.algorithm; f++) 420 if (IsEnabled(ccp->cfg.neg[algorithm[f]->Neg])) 421 o = &(*o)->next; 422 423 if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && 424 ccp->out.algorithm < NALGORITHMS) { 425 ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init)(&(*o)->val); 426 if (ccp->out.state == NULL) { 427 log_Printf(LogERROR, "%s: %s (out) initialisation failure\n", 428 fp->link->name, protoname(ccp->my_proto)); 429 ccp->his_proto = ccp->my_proto = -1; 430 fsm_Close(fp); 431 return 0; 432 } 433 } 434 435 fp->more.reqs = fp->more.naks = fp->more.rejs = ccp->cfg.fsm.maxreq * 3; 436 437 log_Printf(LogCCP, "%s: Out = %s[%d], In = %s[%d]\n", 438 fp->link->name, protoname(ccp->my_proto), ccp->my_proto, 439 protoname(ccp->his_proto), ccp->his_proto); 440 441 return 1; 442 } 443 444 static void 445 CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 446 struct fsm_decode *dec) 447 { 448 /* Deal with incoming data */ 449 struct ccp *ccp = fsm2ccp(fp); 450 int type, length, f; 451 const char *end; 452 453 if (mode_type == MODE_REQ) 454 ccp->in.algorithm = -1; /* In case we've received two REQs in a row */ 455 456 while (plen >= sizeof(struct fsmconfig)) { 457 type = *cp; 458 length = cp[1]; 459 460 if (length == 0) { 461 log_Printf(LogCCP, "%s: CCP size zero\n", fp->link->name); 462 break; 463 } 464 465 if (length > sizeof(struct lcp_opt)) { 466 length = sizeof(struct lcp_opt); 467 log_Printf(LogCCP, "%s: Warning: Truncating length to %d\n", 468 fp->link->name, length); 469 } 470 471 for (f = NALGORITHMS-1; f > -1; f--) 472 if (algorithm[f]->id == type) 473 break; 474 475 end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); 476 if (end == NULL) 477 end = ""; 478 479 log_Printf(LogCCP, " %s[%d] %s\n", protoname(type), length, end); 480 481 if (f == -1) { 482 /* Don't understand that :-( */ 483 if (mode_type == MODE_REQ) { 484 ccp->my_reject |= (1 << type); 485 memcpy(dec->rejend, cp, length); 486 dec->rejend += length; 487 } 488 } else { 489 struct ccp_opt *o; 490 491 switch (mode_type) { 492 case MODE_REQ: 493 if (IsAccepted(ccp->cfg.neg[algorithm[f]->Neg]) && 494 ccp->in.algorithm == -1) { 495 memcpy(&ccp->in.opt, cp, length); 496 switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { 497 case MODE_REJ: 498 memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); 499 dec->rejend += ccp->in.opt.len; 500 break; 501 case MODE_NAK: 502 memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); 503 dec->nakend += ccp->in.opt.len; 504 break; 505 case MODE_ACK: 506 memcpy(dec->ackend, cp, length); 507 dec->ackend += length; 508 ccp->his_proto = type; 509 ccp->in.algorithm = f; /* This one'll do :-) */ 510 break; 511 } 512 } else { 513 memcpy(dec->rejend, cp, length); 514 dec->rejend += length; 515 } 516 break; 517 case MODE_NAK: 518 for (o = ccp->out.opt; o != NULL; o = o->next) 519 if (o->val.id == cp[0]) 520 break; 521 if (o == NULL) 522 log_Printf(LogCCP, "%s: Warning: Ignoring peer NAK of unsent" 523 " option\n", fp->link->name); 524 else { 525 memcpy(&o->val, cp, length); 526 if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) 527 ccp->my_proto = algorithm[f]->id; 528 else { 529 ccp->his_reject |= (1 << type); 530 ccp->my_proto = -1; 531 } 532 } 533 break; 534 case MODE_REJ: 535 ccp->his_reject |= (1 << type); 536 ccp->my_proto = -1; 537 break; 538 } 539 } 540 541 plen -= cp[1]; 542 cp += cp[1]; 543 } 544 545 if (mode_type != MODE_NOP) { 546 if (dec->rejend != dec->rej) { 547 /* rejects are preferred */ 548 dec->ackend = dec->ack; 549 dec->nakend = dec->nak; 550 if (ccp->in.state == NULL) { 551 ccp->his_proto = -1; 552 ccp->in.algorithm = -1; 553 } 554 } else if (dec->nakend != dec->nak) { 555 /* then NAKs */ 556 dec->ackend = dec->ack; 557 if (ccp->in.state == NULL) { 558 ccp->his_proto = -1; 559 ccp->in.algorithm = -1; 560 } 561 } 562 } 563 } 564 565 extern struct mbuf * 566 ccp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 567 { 568 /* Got PROTO_CCP from link */ 569 m_settype(bp, MB_CCPIN); 570 if (bundle_Phase(bundle) == PHASE_NETWORK) 571 fsm_Input(&l->ccp.fsm, bp); 572 else { 573 if (bundle_Phase(bundle) < PHASE_NETWORK) 574 log_Printf(LogCCP, "%s: Error: Unexpected CCP in phase %s (ignored)\n", 575 l->ccp.fsm.link->name, bundle_PhaseName(bundle)); 576 m_freem(bp); 577 } 578 return NULL; 579 } 580 581 static void 582 CcpRecvResetAck(struct fsm *fp, u_char id) 583 { 584 /* Got a reset ACK, reset incoming dictionary */ 585 struct ccp *ccp = fsm2ccp(fp); 586 587 if (ccp->reset_sent != -1) { 588 if (id != ccp->reset_sent) { 589 log_Printf(LogCCP, "%s: Incorrect ResetAck (id %d, not %d)" 590 " ignored\n", fp->link->name, id, ccp->reset_sent); 591 return; 592 } 593 /* Whaddaya know - a correct reset ack */ 594 } else if (id == ccp->last_reset) 595 log_Printf(LogCCP, "%s: Duplicate ResetAck (resetting again)\n", 596 fp->link->name); 597 else { 598 log_Printf(LogCCP, "%s: Unexpected ResetAck (id %d) ignored\n", 599 fp->link->name, id); 600 return; 601 } 602 603 ccp->last_reset = ccp->reset_sent; 604 ccp->reset_sent = -1; 605 if (ccp->in.state != NULL) 606 (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); 607 } 608 609 static struct mbuf * 610 ccp_LayerPush(struct bundle *b, struct link *l, struct mbuf *bp, 611 int pri, u_short *proto) 612 { 613 if (PROTO_COMPRESSIBLE(*proto) && l->ccp.fsm.state == ST_OPENED && 614 l->ccp.out.state != NULL) { 615 bp = (*algorithm[l->ccp.out.algorithm]->o.Write) 616 (l->ccp.out.state, &l->ccp, l, pri, proto, bp); 617 switch (*proto) { 618 case PROTO_ICOMPD: 619 m_settype(bp, MB_ICOMPDOUT); 620 break; 621 case PROTO_COMPD: 622 m_settype(bp, MB_COMPDOUT); 623 break; 624 } 625 } 626 627 return bp; 628 } 629 630 static struct mbuf * 631 ccp_LayerPull(struct bundle *b, struct link *l, struct mbuf *bp, u_short *proto) 632 { 633 /* 634 * If proto isn't PROTO_[I]COMPD, we still want to pass it to the 635 * decompression routines so that the dictionary's updated 636 */ 637 if (l->ccp.fsm.state == ST_OPENED) { 638 if (*proto == PROTO_COMPD || *proto == PROTO_ICOMPD) { 639 log_Printf(LogDEBUG, "ccp_LayerPull: PROTO_%sCOMPDP -> PROTO_IP\n", 640 *proto == PROTO_ICOMPD ? "I" : ""); 641 /* Decompress incoming data */ 642 if (l->ccp.reset_sent != -1) 643 /* Send another REQ and put the packet in the bit bucket */ 644 fsm_Output(&l->ccp.fsm, CODE_RESETREQ, l->ccp.reset_sent, NULL, 0, 645 MB_CCPOUT); 646 else if (l->ccp.in.state != NULL) { 647 bp = (*algorithm[l->ccp.in.algorithm]->i.Read) 648 (l->ccp.in.state, &l->ccp, proto, bp); 649 switch (*proto) { 650 case PROTO_ICOMPD: 651 m_settype(bp, MB_ICOMPDIN); 652 break; 653 case PROTO_COMPD: 654 m_settype(bp, MB_COMPDIN); 655 break; 656 } 657 return bp; 658 } 659 m_freem(bp); 660 bp = NULL; 661 } else if (PROTO_COMPRESSIBLE(*proto) && l->ccp.in.state != NULL) { 662 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet (dict only)\n"); 663 /* Add incoming Network Layer traffic to our dictionary */ 664 (*algorithm[l->ccp.in.algorithm]->i.DictSetup) 665 (l->ccp.in.state, &l->ccp, *proto, bp); 666 } else 667 log_Printf(LogDEBUG, "ccp_LayerPull: Ignore packet\n"); 668 } 669 670 return bp; 671 } 672 673 u_short 674 ccp_Proto(struct ccp *ccp) 675 { 676 return !link2physical(ccp->fsm.link) || !ccp->fsm.bundle->ncp.mp.active ? 677 PROTO_COMPD : PROTO_ICOMPD; 678 } 679 680 int 681 ccp_SetOpenMode(struct ccp *ccp) 682 { 683 int f; 684 685 for (f = 0; f < CCP_NEG_TOTAL; f++) 686 if (IsEnabled(ccp->cfg.neg[f])) { 687 ccp->fsm.open_mode = 0; 688 return 1; 689 } 690 691 ccp->fsm.open_mode = OPEN_PASSIVE; /* Go straight to ST_STOPPED ? */ 692 693 for (f = 0; f < CCP_NEG_TOTAL; f++) 694 if (IsAccepted(ccp->cfg.neg[f])) 695 return 1; 696 697 return 0; /* No CCP at all */ 698 } 699 700 struct layer ccplayer = { LAYER_CCP, "ccp", ccp_LayerPush, ccp_LayerPull }; 701