Annotation of embedaddon/mpd/src/ccp.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * ccp.c
! 4: *
! 5: * Written by Archie Cobbs <archie@freebsd.org>
! 6: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
! 7: * See ``COPYRIGHT.whistle''
! 8: */
! 9:
! 10: #include "defs.h"
! 11: #include "ppp.h"
! 12: #include "ccp.h"
! 13: #include "fsm.h"
! 14: #include "ngfunc.h"
! 15:
! 16: #include <netgraph/ng_message.h>
! 17: #include <netgraph/ng_socket.h>
! 18: #include <netgraph.h>
! 19:
! 20: /*
! 21: * DEFINITIONS
! 22: */
! 23:
! 24: #define CCP_MAXFAILURE 7
! 25:
! 26: #define CCP_KNOWN_CODES ( (1 << CODE_CONFIGREQ) \
! 27: | (1 << CODE_CONFIGACK) \
! 28: | (1 << CODE_CONFIGNAK) \
! 29: | (1 << CODE_CONFIGREJ) \
! 30: | (1 << CODE_TERMREQ) \
! 31: | (1 << CODE_TERMACK) \
! 32: | (1 << CODE_CODEREJ) \
! 33: | (1 << CODE_RESETREQ) \
! 34: | (1 << CODE_RESETACK) )
! 35:
! 36: /* Set menu options */
! 37: enum {
! 38: SET_ACCEPT,
! 39: SET_DENY,
! 40: SET_ENABLE,
! 41: SET_DISABLE,
! 42: SET_YES,
! 43: SET_NO
! 44: };
! 45:
! 46: /*
! 47: * INTERNAL FUNCTIONS
! 48: */
! 49:
! 50: static void CcpConfigure(Fsm fp);
! 51: static void CcpUnConfigure(Fsm fp);
! 52: static u_char *CcpBuildConfigReq(Fsm fp, u_char *cp);
! 53: static void CcpDecodeConfig(Fsm f, FsmOption a, int num, int mode);
! 54: static void CcpLayerUp(Fsm fp);
! 55: static void CcpLayerDown(Fsm fp);
! 56: static void CcpFailure(Fsm f, enum fsmfail reason);
! 57: static void CcpRecvResetReq(Fsm fp, int id, Mbuf bp);
! 58: static void CcpRecvResetAck(Fsm fp, int id, Mbuf bp);
! 59:
! 60: static int CcpCheckEncryption(Bund b);
! 61: static int CcpSetCommand(Context ctx, int ac, char *av[], void *arg);
! 62: static CompType CcpFindComp(int type, int *indexp);
! 63: static const char *CcpTypeName(int type, char *buf, size_t len);
! 64:
! 65: static void CcpNgCtrlEvent(int type, void *cookie);
! 66: static void CcpNgDataEvent(int type, void *cookie);
! 67:
! 68: /*
! 69: * GLOBAL VARIABLES
! 70: */
! 71:
! 72: const struct cmdtab CcpSetCmds[] = {
! 73: { "accept [opt ...]", "Accept option",
! 74: CcpSetCommand, NULL, 2, (void *) SET_ACCEPT },
! 75: { "deny [opt ...]", "Deny option",
! 76: CcpSetCommand, NULL, 2, (void *) SET_DENY },
! 77: { "enable [opt ...]", "Enable option",
! 78: CcpSetCommand, NULL, 2, (void *) SET_ENABLE },
! 79: { "disable [opt ...]", "Disable option",
! 80: CcpSetCommand, NULL, 2, (void *) SET_DISABLE },
! 81: { "yes [opt ...]", "Enable and accept option",
! 82: CcpSetCommand, NULL, 2, (void *) SET_YES },
! 83: { "no [opt ...]", "Disable and deny option",
! 84: CcpSetCommand, NULL, 2, (void *) SET_NO },
! 85: { NULL },
! 86: };
! 87:
! 88: /*
! 89: * INTERNAL VARIABLES
! 90: */
! 91:
! 92: /* These should be listed in order of preference */
! 93: static const CompType gCompTypes[] = {
! 94: #ifdef CCP_MPPC
! 95: &gCompMppcInfo,
! 96: #endif
! 97: #ifdef CCP_DEFLATE
! 98: &gCompDeflateInfo,
! 99: #endif
! 100: #ifdef CCP_PRED1
! 101: &gCompPred1Info,
! 102: #endif
! 103: };
! 104: #define CCP_NUM_PROTOS (sizeof(gCompTypes) / sizeof(*gCompTypes))
! 105:
! 106: /* Corresponding option list */
! 107: static const struct confinfo *gConfList;
! 108:
! 109: /* FSM Initializer */
! 110: static const struct fsmtype gCcpFsmType = {
! 111: "CCP",
! 112: PROTO_CCP,
! 113: CCP_KNOWN_CODES,
! 114: FALSE,
! 115: LG_CCP, LG_CCP2,
! 116: NULL,
! 117: CcpLayerUp,
! 118: CcpLayerDown,
! 119: NULL,
! 120: NULL,
! 121: CcpBuildConfigReq,
! 122: CcpDecodeConfig,
! 123: CcpConfigure,
! 124: CcpUnConfigure,
! 125: NULL,
! 126: NULL,
! 127: NULL,
! 128: NULL,
! 129: CcpFailure,
! 130: CcpRecvResetReq,
! 131: CcpRecvResetAck,
! 132: NULL,
! 133: };
! 134:
! 135: /* Names for different types of compression */
! 136: static const struct ccpname {
! 137: u_char type;
! 138: const char *name;
! 139: } gCcpTypeNames[] = {
! 140: { CCP_TY_OUI, "OUI" },
! 141: { CCP_TY_PRED1, "PRED1" },
! 142: { CCP_TY_PRED2, "PRED2" },
! 143: { CCP_TY_PUDDLE, "PUDDLE" },
! 144: { CCP_TY_HWPPC, "HWPPC" },
! 145: { CCP_TY_STAC, "STAC" },
! 146: { CCP_TY_MPPC, "MPPC" },
! 147: { CCP_TY_GAND, "GAND" },
! 148: { CCP_TY_V42BIS, "V42BIS" },
! 149: { CCP_TY_BSD, "BSD" },
! 150: { CCP_TY_LZS_DCP, "LZS-DCP" },
! 151: { CCP_TY_DEFLATE24, "DEFLATE24" },
! 152: { CCP_TY_DCE, "DCE" },
! 153: { CCP_TY_DEFLATE, "DEFLATE" },
! 154: { CCP_TY_V44, "V.44/LZJH" },
! 155: { 0, NULL },
! 156: };
! 157:
! 158: int gCcpCsock = -1; /* Socket node control socket */
! 159: int gCcpDsock = -1; /* Socket node data socket */
! 160: EventRef gCcpCtrlEvent;
! 161: EventRef gCcpDataEvent;
! 162:
! 163: int
! 164: CcpsInit(void)
! 165: {
! 166: char name[NG_NODESIZ];
! 167:
! 168: /* Create a netgraph socket node */
! 169: snprintf(name, sizeof(name), "mpd%d-cso", gPid);
! 170: if (NgMkSockNode(name, &gCcpCsock, &gCcpDsock) < 0) {
! 171: Perror("CcpsInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
! 172: return(-1);
! 173: }
! 174: (void) fcntl(gCcpCsock, F_SETFD, 1);
! 175: (void) fcntl(gCcpDsock, F_SETFD, 1);
! 176:
! 177: /* Listen for happenings on our node */
! 178: EventRegister(&gCcpCtrlEvent, EVENT_READ,
! 179: gCcpCsock, EVENT_RECURRING, CcpNgCtrlEvent, NULL);
! 180: EventRegister(&gCcpDataEvent, EVENT_READ,
! 181: gCcpDsock, EVENT_RECURRING, CcpNgDataEvent, NULL);
! 182:
! 183: return (0);
! 184: }
! 185:
! 186: void
! 187: CcpsShutdown(void)
! 188: {
! 189: EventUnRegister(&gCcpCtrlEvent);
! 190: close(gCcpCsock);
! 191: gCcpCsock = -1;
! 192: EventUnRegister(&gCcpDataEvent);
! 193: close(gCcpDsock);
! 194: gCcpDsock = -1;
! 195: }
! 196:
! 197: /*
! 198: * CcpInit()
! 199: */
! 200:
! 201: void
! 202: CcpInit(Bund b)
! 203: {
! 204: CcpState ccp = &b->ccp;
! 205:
! 206: /* Init CCP state for this bundle */
! 207: memset(ccp, 0, sizeof(*ccp));
! 208: FsmInit(&ccp->fsm, &gCcpFsmType, b);
! 209: ccp->fsm.conf.maxfailure = CCP_MAXFAILURE;
! 210:
! 211: /* Construct options list if we haven't done so already */
! 212: if (gConfList == NULL) {
! 213: struct confinfo *ci;
! 214: int k;
! 215:
! 216: ci = Malloc(MB_COMP, (CCP_NUM_PROTOS + 1) * sizeof(*ci));
! 217: for (k = 0; k < CCP_NUM_PROTOS; k++) {
! 218: ci[k].option = k;
! 219: ci[k].peered = TRUE;
! 220: ci[k].name = gCompTypes[k]->name;
! 221: }
! 222:
! 223: /* Terminate list */
! 224: ci[k].name = NULL;
! 225: gConfList = (const struct confinfo *) ci;
! 226: }
! 227: }
! 228:
! 229: /*
! 230: * CcpInst()
! 231: */
! 232:
! 233: void
! 234: CcpInst(Bund b, Bund bt)
! 235: {
! 236: CcpState ccp = &b->ccp;
! 237:
! 238: /* Init CCP state for this bundle */
! 239: memcpy(ccp, &bt->ccp, sizeof(*ccp));
! 240: FsmInst(&ccp->fsm, &bt->ccp.fsm, b);
! 241: }
! 242:
! 243: /*
! 244: * CcpConfigure()
! 245: */
! 246:
! 247: static void
! 248: CcpConfigure(Fsm fp)
! 249: {
! 250: Bund b = (Bund)fp->arg;
! 251: CcpState const ccp = &b->ccp;
! 252: int k;
! 253:
! 254: /* Reset state */
! 255: ccp->self_reject = 0;
! 256: ccp->peer_reject = 0;
! 257: ccp->crypt_check = 0;
! 258: ccp->xmit = NULL;
! 259: ccp->recv = NULL;
! 260: for (k = 0; k < CCP_NUM_PROTOS; k++) {
! 261: CompType const ct = gCompTypes[k];
! 262:
! 263: if (ct->Configure) {
! 264: if ((*ct->Configure)(b)) {
! 265: if (Enabled(&ccp->options, k)) {
! 266: Log(LG_CCP, ("[%s] CCP: Protocol %s disabled "
! 267: "as useless for this setup",
! 268: b->name, ct->name));
! 269: }
! 270: CCP_SELF_REJ(ccp, k);
! 271: };
! 272: }
! 273: }
! 274: }
! 275:
! 276: /*
! 277: * CcpUnConfigure()
! 278: */
! 279:
! 280: static void
! 281: CcpUnConfigure(Fsm fp)
! 282: {
! 283: Bund b = (Bund)fp->arg;
! 284: CcpState const ccp = &b->ccp;
! 285: int k;
! 286:
! 287: /* Reset state */
! 288: ccp->self_reject = 0;
! 289: ccp->peer_reject = 0;
! 290: ccp->crypt_check = 0;
! 291: ccp->xmit = NULL;
! 292: ccp->recv = NULL;
! 293: for (k = 0; k < CCP_NUM_PROTOS; k++) {
! 294: CompType const ct = gCompTypes[k];
! 295:
! 296: if (ct->UnConfigure)
! 297: (*ct->UnConfigure)(b);
! 298: }
! 299: }
! 300:
! 301: /*
! 302: * CcpNgCtrlEvent()
! 303: *
! 304: */
! 305:
! 306: void
! 307: CcpNgCtrlEvent(int type, void *cookie)
! 308: {
! 309: Bund b = NULL;
! 310: union {
! 311: u_char buf[2048];
! 312: struct ng_mesg msg;
! 313: } u;
! 314: char raddr[NG_PATHSIZ];
! 315: int i, len;
! 316: ng_ID_t id;
! 317:
! 318: /* Read message */
! 319: if ((len = NgRecvMsg(gCcpCsock, &u.msg, sizeof(u), raddr)) < 0) {
! 320: Perror("CcpNgCtrlEvent: can't read message");
! 321: return;
! 322: }
! 323:
! 324: if (sscanf(raddr, "[%x]:", &id) != 1) {
! 325: Log(LG_ERR, ("CcpNgCtrlEvent: can't decode sender id: '%s'",
! 326: raddr));
! 327: return;
! 328: }
! 329:
! 330: for (i = 0; i < gNumBundles; i++) {
! 331: if (gBundles[i] && !gBundles[i]->dead &&
! 332: gBundles[i]->ccp.decomp_node_id == id) {
! 333: b = gBundles[i];
! 334: break;
! 335: }
! 336: }
! 337: if (!b)
! 338: return;
! 339:
! 340: /* Examine message */
! 341: switch (u.msg.header.typecookie) {
! 342:
! 343: #ifdef USE_NG_MPPC
! 344: case NGM_MPPC_COOKIE:
! 345: #endif
! 346: #ifdef USE_NG_DEFLATE
! 347: case NGM_DEFLATE_COOKIE:
! 348: #endif
! 349: #ifdef USE_NG_PRED1
! 350: case NGM_PRED1_COOKIE:
! 351: #endif
! 352: CcpRecvMsg(b, &u.msg, len);
! 353: return;
! 354:
! 355: default:
! 356: /* Unknown message */
! 357: Log(LG_ERR, ("CcpNgCtrlEvent: rec'd unknown ctrl message, cookie=%d cmd=%d",
! 358: u.msg.header.typecookie, u.msg.header.cmd));
! 359: break;
! 360: }
! 361:
! 362: }
! 363:
! 364: /*
! 365: * CcpNgDataEvent()
! 366: */
! 367:
! 368: static void
! 369: CcpNgDataEvent(int type, void *cookie)
! 370: {
! 371: Bund b;
! 372: struct sockaddr_ng naddr;
! 373: socklen_t nsize;
! 374: Mbuf bp;
! 375: int num = 0;
! 376: char *bundname, *rest;
! 377: int id;
! 378:
! 379: while (1) {
! 380: /* Protect from bundle shutdown and DoS */
! 381: if (num > 100)
! 382: return;
! 383:
! 384: bp = mballoc(4096);
! 385:
! 386: /* Read data */
! 387: nsize = sizeof(naddr);
! 388: if ((bp->cnt = recvfrom(gCcpDsock, MBDATA(bp), MBSPACE(bp),
! 389: MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
! 390: mbfree(bp);
! 391: if (errno == EAGAIN)
! 392: return;
! 393: Log(LG_BUND|LG_ERR, ("CcpNgDataEvent: socket read: %s", strerror(errno)));
! 394: return;
! 395: }
! 396: num++;
! 397:
! 398: /* Debugging */
! 399: LogDumpBp(LG_FRAME, bp,
! 400: "CcpNgDataEvent: rec'd %d bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
! 401:
! 402: bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
! 403: if (bundname[0] != 'c' && bundname[0] != 'd') {
! 404: Log(LG_ERR, ("CCP: Packet from unknown hook \"%s\"",
! 405: bundname));
! 406: mbfree(bp);
! 407: continue;
! 408: }
! 409: bundname++;
! 410: id = strtol(bundname, &rest, 10);
! 411: if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
! 412: Log(LG_ERR, ("CCP: Packet from unexisting bundle \"%s\"",
! 413: bundname));
! 414: mbfree(bp);
! 415: continue;
! 416: }
! 417:
! 418: b = gBundles[id];
! 419:
! 420: /* Packet requiring compression */
! 421: if (bundname[0] == 'c') {
! 422: bp = CcpDataOutput(b, bp);
! 423: } else {
! 424: /* Packet requiring decompression */
! 425: bp = CcpDataInput(b, bp);
! 426: }
! 427: if (bp)
! 428: NgFuncWriteFrame(gCcpDsock, naddr.sg_data, b->name, bp);
! 429: }
! 430: }
! 431:
! 432: /*
! 433: * CcpRecvMsg()
! 434: */
! 435:
! 436: void
! 437: CcpRecvMsg(Bund b, struct ng_mesg *msg, int len)
! 438: {
! 439: CcpState const ccp = &b->ccp;
! 440: Fsm const fp = &ccp->fsm;
! 441:
! 442: switch (msg->header.typecookie) {
! 443: #ifdef USE_NG_MPPC
! 444: case NGM_MPPC_COOKIE:
! 445: switch (msg->header.cmd) {
! 446: case NGM_MPPC_RESETREQ: {
! 447: CcpSendResetReq(b);
! 448: return;
! 449: }
! 450: default:
! 451: break;
! 452: }
! 453: break;
! 454: #endif
! 455: #ifdef USE_NG_DEFLATE
! 456: case NGM_DEFLATE_COOKIE:
! 457: switch (msg->header.cmd) {
! 458: case NGM_DEFLATE_RESETREQ: {
! 459: CcpSendResetReq(b);
! 460: return;
! 461: }
! 462: default:
! 463: break;
! 464: }
! 465: break;
! 466: #endif
! 467: #ifdef USE_NG_PRED1
! 468: case NGM_PRED1_COOKIE:
! 469: switch (msg->header.cmd) {
! 470: case NGM_PRED1_RESETREQ: {
! 471: CcpSendResetReq(b);
! 472: return;
! 473: }
! 474: default:
! 475: break;
! 476: }
! 477: break;
! 478: #endif
! 479: default:
! 480: break;
! 481: }
! 482:
! 483: /* Unknown! */
! 484: Log(LG_ERR, ("[%s] %s: rec'd unknown netgraph message: cookie=%d, cmd=%d",
! 485: Pref(fp), Fsm(fp), msg->header.typecookie, msg->header.cmd));
! 486: }
! 487:
! 488: /*
! 489: * CcpUp()
! 490: */
! 491:
! 492: void
! 493: CcpUp(Bund b)
! 494: {
! 495: FsmUp(&b->ccp.fsm);
! 496: }
! 497:
! 498: /*
! 499: * CcpDown()
! 500: */
! 501:
! 502: void
! 503: CcpDown(Bund b)
! 504: {
! 505: FsmDown(&b->ccp.fsm);
! 506: }
! 507:
! 508: /*
! 509: * CcpOpen()
! 510: */
! 511:
! 512: void
! 513: CcpOpen(Bund b)
! 514: {
! 515: FsmOpen(&b->ccp.fsm);
! 516: }
! 517:
! 518: /*
! 519: * CcpClose()
! 520: */
! 521:
! 522: void
! 523: CcpClose(Bund b)
! 524: {
! 525: FsmClose(&b->ccp.fsm);
! 526: }
! 527:
! 528: /*
! 529: * CcpOpenCmd()
! 530: */
! 531:
! 532: int
! 533: CcpOpenCmd(Context ctx)
! 534: {
! 535: if (ctx->bund->tmpl)
! 536: Error("impossible to open template");
! 537: FsmOpen(&ctx->bund->ccp.fsm);
! 538: return (0);
! 539: }
! 540:
! 541: /*
! 542: * CcpCloseCmd()
! 543: */
! 544:
! 545: int
! 546: CcpCloseCmd(Context ctx)
! 547: {
! 548: if (ctx->bund->tmpl)
! 549: Error("impossible to close template");
! 550: FsmClose(&ctx->bund->ccp.fsm);
! 551: return (0);
! 552: }
! 553:
! 554: /*
! 555: * CcpFailure()
! 556: *
! 557: * If we fail, just shut down and stop trying. However, if encryption
! 558: * was required and MPPE encryption was enabled, then die here as well.
! 559: */
! 560:
! 561: static void
! 562: CcpFailure(Fsm fp, enum fsmfail reason)
! 563: {
! 564: Bund b = (Bund)fp->arg;
! 565: CcpCheckEncryption(b);
! 566: }
! 567:
! 568: /*
! 569: * CcpStat()
! 570: */
! 571:
! 572: int
! 573: CcpStat(Context ctx, int ac, char *av[], void *arg)
! 574: {
! 575: CcpState const ccp = &ctx->bund->ccp;
! 576: char buf[64];
! 577:
! 578: Printf("[%s] %s [%s]\r\n", Pref(&ccp->fsm), Fsm(&ccp->fsm), FsmStateName(ccp->fsm.state));
! 579: Printf("Enabled protocols:\r\n");
! 580: OptStat(ctx, &ccp->options, gConfList);
! 581:
! 582: #ifdef CCP_MPPC
! 583: MppcStat(ctx, ac, av, arg);
! 584: #endif
! 585: Printf("Outgoing compression:\r\n");
! 586: Printf("\tProto\t: %s (%s)\r\n", !ccp->xmit ? "none" : ccp->xmit->name,
! 587: (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(ctx->bund, COMP_DIR_XMIT, buf, sizeof(buf)) : "");
! 588: if (ccp->xmit && ccp->xmit->Stat)
! 589: ccp->xmit->Stat(ctx, COMP_DIR_XMIT);
! 590: Printf("\tResets\t: %d\r\n", ccp->xmit_resets);
! 591:
! 592: Printf("Incoming decompression:\r\n");
! 593: Printf("\tProto\t: %s (%s)\r\n", !ccp->recv ? "none" : ccp->recv->name,
! 594: (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(ctx->bund, COMP_DIR_RECV, buf, sizeof(buf)) : "");
! 595: if (ccp->recv && ccp->recv->Stat)
! 596: ccp->recv->Stat(ctx, COMP_DIR_RECV);
! 597: Printf("\tResets\t: %d\r\n", ccp->recv_resets);
! 598:
! 599: return(0);
! 600: }
! 601:
! 602: /*
! 603: * CcpSendResetReq()
! 604: */
! 605:
! 606: void
! 607: CcpSendResetReq(Bund b)
! 608: {
! 609: CcpState const ccp = &b->ccp;
! 610: CompType const ct = ccp->recv;
! 611: Fsm const fp = &ccp->fsm;
! 612: Mbuf bp = NULL;
! 613:
! 614: if (ct == NULL) {
! 615: Log(LG_ERR, ("[%s] %s: CcpSendResetReq() call from undefined decompressor!",
! 616: Pref(fp), Fsm(fp)));
! 617: return;
! 618: }
! 619:
! 620: ccp->recv_resets++;
! 621: if (ct->SendResetReq)
! 622: bp = (*ct->SendResetReq)(b);
! 623: Log(LG_CCP, ("[%s] %s: SendResetReq #%d link %d (%s)",
! 624: Pref(fp), Fsm(fp), fp->reqid, 0, FsmStateName(fp->state)));
! 625: FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
! 626: }
! 627:
! 628: /*
! 629: * CcpRecvResetReq()
! 630: */
! 631:
! 632: static void
! 633: CcpRecvResetReq(Fsm fp, int id, Mbuf bp)
! 634: {
! 635: Bund b = (Bund)fp->arg;
! 636: CcpState const ccp = &b->ccp;
! 637: CompType const ct = ccp->xmit;
! 638: int noAck = 0;
! 639:
! 640: ccp->xmit_resets++;
! 641: bp = (ct && ct->RecvResetReq) ? (*ct->RecvResetReq)(b, id, bp, &noAck) : NULL;
! 642: if (!noAck) {
! 643: Log(LG_CCP, ("[%s] %s: SendResetAck #%d link %d (%s)",
! 644: Pref(fp), Fsm(fp), id, 0, FsmStateName(fp->state)));
! 645: FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
! 646: }
! 647: }
! 648:
! 649: /*
! 650: * CcpRecvResetAck()
! 651: */
! 652:
! 653: static void
! 654: CcpRecvResetAck(Fsm fp, int id, Mbuf bp)
! 655: {
! 656: Bund b = (Bund)fp->arg;
! 657: CcpState const ccp = &b->ccp;
! 658: CompType const ct = ccp->recv;
! 659:
! 660: if (ct && ct->RecvResetAck)
! 661: (*ct->RecvResetAck)(b, id, bp);
! 662: }
! 663:
! 664: /*
! 665: * CcpInput()
! 666: */
! 667:
! 668: void
! 669: CcpInput(Bund b, Mbuf bp)
! 670: {
! 671: FsmInput(&b->ccp.fsm, bp);
! 672: }
! 673:
! 674: /*
! 675: * CcpDataOutput()
! 676: *
! 677: * Compress a frame. Consumes the original packet.
! 678: */
! 679:
! 680: Mbuf
! 681: CcpDataOutput(Bund b, Mbuf plain)
! 682: {
! 683: CcpState const ccp = &b->ccp;
! 684: Mbuf comp;
! 685:
! 686: LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
! 687:
! 688: /* Compress packet */
! 689:
! 690: if ((!ccp->xmit) || (!ccp->xmit->Compress))
! 691: {
! 692: Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
! 693: mbfree(plain);
! 694: return(NULL);
! 695: }
! 696: comp = (*ccp->xmit->Compress)(b, plain);
! 697: LogDumpBp(LG_FRAME, comp, "[%s] %s: xmit comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
! 698:
! 699: return(comp);
! 700: }
! 701:
! 702: /*
! 703: * CcpDataInput()
! 704: *
! 705: * Decompress incoming packet. If packet got garbled, return NULL.
! 706: * In any case, we consume the packet passed to us.
! 707: */
! 708:
! 709: Mbuf
! 710: CcpDataInput(Bund b, Mbuf comp)
! 711: {
! 712: CcpState const ccp = &b->ccp;
! 713: Mbuf plain;
! 714:
! 715: LogDumpBp(LG_FRAME, comp, "[%s] %s: recv comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
! 716:
! 717: /* Decompress packet */
! 718:
! 719: if ((!ccp->recv) || (!ccp->recv->Decompress))
! 720: {
! 721: Log(LG_ERR, ("[%s] %s: no compression for recv", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
! 722: mbfree(comp);
! 723: return(NULL);
! 724: }
! 725:
! 726: plain = (*ccp->recv->Decompress)(b, comp);
! 727:
! 728: /* Encrypted ok? */
! 729:
! 730: if (plain == NULL)
! 731: {
! 732: Log(LG_CCP, ("[%s] %s: decompression failed", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
! 733: return(NULL);
! 734: }
! 735: LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
! 736:
! 737: return(plain);
! 738: }
! 739:
! 740: /*
! 741: * CcpBuildConfigReq()
! 742: */
! 743:
! 744: static u_char *
! 745: CcpBuildConfigReq(Fsm fp, u_char *cp)
! 746: {
! 747: Bund b = (Bund)fp->arg;
! 748: CcpState const ccp = &b->ccp;
! 749: int type;
! 750: int ok;
! 751:
! 752: /* Put in all options that peer hasn't rejected in preferred order */
! 753: ccp->xmit = NULL;
! 754: for (type = 0; type < CCP_NUM_PROTOS; type++) {
! 755: CompType const ct = gCompTypes[type];
! 756:
! 757: if (Enabled(&ccp->options, type) && !CCP_PEER_REJECTED(ccp, type)) {
! 758: cp = (*ct->BuildConfigReq)(b, cp, &ok);
! 759: if (ok && (!ccp->xmit))
! 760: ccp->xmit = ct;
! 761: }
! 762: }
! 763: return(cp);
! 764: }
! 765:
! 766: /*
! 767: * CcpLayerUp()
! 768: */
! 769:
! 770: static void
! 771: CcpLayerUp(Fsm fp)
! 772: {
! 773: Bund b = (Bund)fp->arg;
! 774: CcpState const ccp = &b->ccp;
! 775: struct ngm_connect cn;
! 776: char buf[64];
! 777:
! 778: /* If nothing was negotiated in either direction, close CCP */
! 779: if ((!ccp->recv || !(*ccp->recv->Negotiated)(b, COMP_DIR_RECV))
! 780: && (!ccp->xmit || !(*ccp->xmit->Negotiated)(b, COMP_DIR_XMIT))) {
! 781: Log(LG_CCP, ("[%s] %s: No compression negotiated", Pref(fp), Fsm(fp)));
! 782: FsmFailure(fp, FAIL_NEGOT_FAILURE);
! 783: return;
! 784: }
! 785:
! 786: /* Check for required encryption */
! 787: if (CcpCheckEncryption(b) < 0) {
! 788: return;
! 789: }
! 790:
! 791: /* Initialize each direction */
! 792: if (ccp->xmit != NULL && ccp->xmit->Init != NULL
! 793: && (*ccp->xmit->Init)(b, COMP_DIR_XMIT) < 0) {
! 794: Log(LG_CCP, ("[%s] %s: compression init failed", Pref(fp), Fsm(fp)));
! 795: FsmFailure(fp, FAIL_NEGOT_FAILURE); /* XXX */
! 796: return;
! 797: }
! 798: if (ccp->recv != NULL && ccp->recv->Init != NULL
! 799: && (*ccp->recv->Init)(b, COMP_DIR_RECV) < 0) {
! 800: Log(LG_CCP, ("[%s] %s: decompression init failed", Pref(fp), Fsm(fp)));
! 801: FsmFailure(fp, FAIL_NEGOT_FAILURE); /* XXX */
! 802: return;
! 803: }
! 804:
! 805: if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
! 806: /* Connect a hook from the ppp node to our socket node */
! 807: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
! 808: snprintf(cn.ourhook, sizeof(cn.ourhook), "c%d", b->id);
! 809: strcpy(cn.peerhook, NG_PPP_HOOK_COMPRESS);
! 810: if (NgSendMsg(gCcpCsock, ".:",
! 811: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 812: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 813: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
! 814: }
! 815: }
! 816:
! 817: if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
! 818: /* Connect a hook from the ppp node to our socket node */
! 819: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
! 820: snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
! 821: strcpy(cn.peerhook, NG_PPP_HOOK_DECOMPRESS);
! 822: if (NgSendMsg(gCcpCsock, ".:",
! 823: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 824: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 825: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
! 826: }
! 827: }
! 828:
! 829: /* Report what we're doing */
! 830: Log(LG_CCP, ("[%s] CCP: Compress using: %s (%s)", b->name, !ccp->xmit ? "none" : ccp->xmit->name,
! 831: (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(b, COMP_DIR_XMIT, buf, sizeof(buf)) : ""));
! 832: Log(LG_CCP, ("[%s] CCP: Decompress using: %s (%s)", b->name, !ccp->recv ? "none" : ccp->recv->name,
! 833: (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(b, COMP_DIR_RECV, buf, sizeof(buf)) : ""));
! 834:
! 835: /* Update PPP node config */
! 836: b->pppConfig.bund.enableCompression = (ccp->xmit != NULL)?ccp->xmit->mode:0;
! 837: b->pppConfig.bund.enableDecompression = (ccp->recv != NULL)?ccp->recv->mode:0;
! 838: NgFuncSetConfig(b);
! 839:
! 840: /* Update interface MTU */
! 841: BundUpdateParams(b);
! 842: }
! 843:
! 844: /*
! 845: * CcpLayerDown()
! 846: */
! 847:
! 848: static void
! 849: CcpLayerDown(Fsm fp)
! 850: {
! 851: Bund b = (Bund)fp->arg;
! 852: CcpState const ccp = &b->ccp;
! 853:
! 854: /* Update PPP node config */
! 855: b->pppConfig.bund.enableCompression = 0;
! 856: b->pppConfig.bund.enableDecompression = 0;
! 857: NgFuncSetConfig(b);
! 858:
! 859: /* Update interface MTU */
! 860: BundUpdateParams(b);
! 861:
! 862: if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
! 863: char hook[NG_HOOKSIZ];
! 864: /* Disconnect hook. */
! 865: snprintf(hook, sizeof(hook), "c%d", b->id);
! 866: NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
! 867: }
! 868:
! 869: if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
! 870: char hook[NG_HOOKSIZ];
! 871: /* Disconnect hook. */
! 872: snprintf(hook, sizeof(hook), "d%d", b->id);
! 873: NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
! 874: }
! 875: if (ccp->recv && ccp->recv->Cleanup)
! 876: (*ccp->recv->Cleanup)(b, COMP_DIR_RECV);
! 877: if (ccp->xmit && ccp->xmit->Cleanup)
! 878: (*ccp->xmit->Cleanup)(b, COMP_DIR_XMIT);
! 879:
! 880: ccp->xmit_resets = 0;
! 881: ccp->recv_resets = 0;
! 882: }
! 883:
! 884: /*
! 885: * CcpDecodeConfig()
! 886: */
! 887:
! 888: static void
! 889: CcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
! 890: {
! 891: Bund b = (Bund)fp->arg;
! 892: CcpState const ccp = &b->ccp;
! 893: u_int ackSizeSave, rejSizeSave;
! 894: int k, rej;
! 895:
! 896: /* Forget our previous choice on new request */
! 897: if (mode == MODE_REQ)
! 898: ccp->recv = NULL;
! 899:
! 900: /* Decode each config option */
! 901: for (k = 0; k < num; k++) {
! 902: FsmOption const opt = &list[k];
! 903: int index;
! 904: CompType ct;
! 905: char buf[32];
! 906:
! 907: Log(LG_CCP, ("[%s] %s", b->name, CcpTypeName(opt->type, buf, sizeof(buf))));
! 908: if ((ct = CcpFindComp(opt->type, &index)) == NULL) {
! 909: if (mode == MODE_REQ) {
! 910: Log(LG_CCP, ("[%s] Not supported", b->name));
! 911: FsmRej(fp, opt);
! 912: }
! 913: continue;
! 914: }
! 915: switch (mode) {
! 916: case MODE_REQ:
! 917: ackSizeSave = gAckSize;
! 918: rejSizeSave = gRejSize;
! 919: rej = (!Acceptable(&ccp->options, index)
! 920: || CCP_SELF_REJECTED(ccp, index)
! 921: || (ccp->recv && ccp->recv != ct));
! 922: if (rej) {
! 923: (*ct->DecodeConfig)(fp, opt, MODE_NOP);
! 924: FsmRej(fp, opt);
! 925: break;
! 926: }
! 927: (*ct->DecodeConfig)(fp, opt, mode);
! 928: if (gRejSize != rejSizeSave) { /* we rejected it */
! 929: CCP_SELF_REJ(ccp, index);
! 930: break;
! 931: }
! 932: if (gAckSize != ackSizeSave) /* we accepted it */
! 933: ccp->recv = ct;
! 934: break;
! 935:
! 936: case MODE_REJ:
! 937: (*ct->DecodeConfig)(fp, opt, mode);
! 938: CCP_PEER_REJ(ccp, index);
! 939: break;
! 940:
! 941: case MODE_NAK:
! 942: case MODE_NOP:
! 943: (*ct->DecodeConfig)(fp, opt, mode);
! 944: break;
! 945: }
! 946: }
! 947: }
! 948:
! 949: /*
! 950: * CcpSubtractBloat()
! 951: *
! 952: * Given that "size" is our MTU, return the maximum length frame
! 953: * we can compress without the result being longer than "size".
! 954: */
! 955:
! 956: int
! 957: CcpSubtractBloat(Bund b, int size)
! 958: {
! 959: CcpState const ccp = &b->ccp;
! 960:
! 961: /* Account for transmit compression overhead */
! 962: if (OPEN_STATE(ccp->fsm.state) && ccp->xmit && ccp->xmit->SubtractBloat)
! 963: size = (*ccp->xmit->SubtractBloat)(b, size);
! 964:
! 965: /* Account for CCP's protocol number overhead */
! 966: if (OPEN_STATE(ccp->fsm.state))
! 967: size -= CCP_OVERHEAD;
! 968:
! 969: /* Done */
! 970: return(size);
! 971: }
! 972:
! 973: /*
! 974: * CcpCheckEncryption()
! 975: *
! 976: * Because MPPE is negotiated as an option to MPPC compression,
! 977: * we have to check for encryption required when CCP comes up.
! 978: */
! 979:
! 980: static int
! 981: CcpCheckEncryption(Bund b)
! 982: {
! 983: #if 0
! 984: CcpState const ccp = &b->ccp;
! 985:
! 986: /* Already checked? */
! 987: if (ccp->crypt_check)
! 988: return(0);
! 989: ccp->crypt_check = 1;
! 990:
! 991: /* Is encryption required? */
! 992: if (Enabled(&ccp->options, gMppePolicy)) {
! 993: if (b->params.msoft.policy != MPPE_POLICY_REQUIRED)
! 994: return(0);
! 995: } else {
! 996: if (!Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD))
! 997: return(0);
! 998: }
! 999:
! 1000: /* Was MPPE encryption enabled? If not, ignore requirement */
! 1001: if (!Enabled(&ccp->options, gMppe40)
! 1002: && !Enabled(&ccp->options, gMppe56)
! 1003: && !Enabled(&ccp->options, gMppe128)
! 1004: && !Enabled(&ccp->options, gMppePolicy))
! 1005: return(0);
! 1006:
! 1007: /* Make sure MPPE was negotiated in both directions */
! 1008: if (!OPEN_STATE(ccp->fsm.state)
! 1009: || !ccp->xmit || ccp->xmit->type != CCP_TY_MPPC
! 1010: || !ccp->recv || ccp->recv->type != CCP_TY_MPPC
! 1011: #ifdef CCP_MPPC
! 1012: || !(ccp->mppc.recv_bits & MPPE_BITS)
! 1013: || !(ccp->mppc.xmit_bits & MPPE_BITS)
! 1014: #endif
! 1015: )
! 1016: goto fail;
! 1017:
! 1018: /* Looks OK */
! 1019: return(0);
! 1020:
! 1021: fail:
! 1022: Log(LG_ERR, ("[%s] %s: encryption required, but MPPE was not"
! 1023: " negotiated in both directions", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
! 1024: FsmFailure(&ccp->fsm, FAIL_CANT_ENCRYPT);
! 1025: FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
! 1026: FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
! 1027: return(-1);
! 1028: #endif
! 1029: return (0);
! 1030: }
! 1031:
! 1032: /*
! 1033: * CcpSetCommand()
! 1034: */
! 1035:
! 1036: static int
! 1037: CcpSetCommand(Context ctx, int ac, char *av[], void *arg)
! 1038: {
! 1039: CcpState const ccp = &ctx->bund->ccp;
! 1040:
! 1041: if (ac == 0)
! 1042: return(-1);
! 1043: switch ((intptr_t)arg) {
! 1044: case SET_ACCEPT:
! 1045: AcceptCommand(ac, av, &ccp->options, gConfList);
! 1046: break;
! 1047:
! 1048: case SET_DENY:
! 1049: DenyCommand(ac, av, &ccp->options, gConfList);
! 1050: break;
! 1051:
! 1052: case SET_ENABLE:
! 1053: EnableCommand(ac, av, &ccp->options, gConfList);
! 1054: break;
! 1055:
! 1056: case SET_DISABLE:
! 1057: DisableCommand(ac, av, &ccp->options, gConfList);
! 1058: break;
! 1059:
! 1060: case SET_YES:
! 1061: YesCommand(ac, av, &ccp->options, gConfList);
! 1062: break;
! 1063:
! 1064: case SET_NO:
! 1065: NoCommand(ac, av, &ccp->options, gConfList);
! 1066: break;
! 1067:
! 1068: default:
! 1069: assert(0);
! 1070: }
! 1071: return(0);
! 1072: }
! 1073:
! 1074: /*
! 1075: * CcpFindComp()
! 1076: */
! 1077:
! 1078: static CompType
! 1079: CcpFindComp(int type, int *indexp)
! 1080: {
! 1081: int k;
! 1082:
! 1083: for (k = 0; k < CCP_NUM_PROTOS; k++) {
! 1084: if (gCompTypes[k]->type == type) {
! 1085: if (indexp)
! 1086: *indexp = k;
! 1087: return(gCompTypes[k]);
! 1088: }
! 1089: }
! 1090: return(NULL);
! 1091: }
! 1092:
! 1093: /*
! 1094: * CcpTypeName()
! 1095: */
! 1096:
! 1097: static const char *
! 1098: CcpTypeName(int type, char *buf, size_t len)
! 1099: {
! 1100: const struct ccpname *p;
! 1101:
! 1102: for (p = gCcpTypeNames; p->name; p++) {
! 1103: if (p->type == type) {
! 1104: strlcpy(buf, p->name, len);
! 1105: return (buf);
! 1106: }
! 1107: }
! 1108: snprintf(buf, sizeof(buf), "UNKNOWN[%d]", type);
! 1109: return(buf);
! 1110: }
! 1111:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>