Annotation of embedaddon/mpd/src/ecp.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * ecp.c
! 4: *
! 5: * Written by Archie Cobbs <archie@freebsd.org>
! 6: * Copyright (c) 1998-1999 Whistle Communications, Inc. All rights reserved.
! 7: * See ``COPYRIGHT.whistle''
! 8: */
! 9:
! 10: #include "ppp.h"
! 11: #include "bund.h"
! 12: #include "ecp.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 ECP_MAXFAILURE 7
! 25:
! 26: #define ECP_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: #define ECP_OVERHEAD 2
! 37:
! 38: #define ECP_PEER_REJECTED(p,x) ((p)->peer_reject & (1<<(x)))
! 39: #define ECP_SELF_REJECTED(p,x) ((p)->self_reject & (1<<(x)))
! 40:
! 41: #define ECP_PEER_REJ(p,x) do{(p)->peer_reject |= (1<<(x));}while(0)
! 42: #define ECP_SELF_REJ(p,x) do{(p)->self_reject |= (1<<(x));}while(0)
! 43:
! 44: /* Set menu options */
! 45:
! 46: enum
! 47: {
! 48: SET_KEY,
! 49: SET_ACCEPT,
! 50: SET_DENY,
! 51: SET_ENABLE,
! 52: SET_DISABLE,
! 53: SET_YES,
! 54: SET_NO
! 55: };
! 56:
! 57: /*
! 58: * INTERNAL FUNCTIONS
! 59: */
! 60:
! 61: static void EcpConfigure(Fsm fp);
! 62: static void EcpUnConfigure(Fsm fp);
! 63: static u_char *EcpBuildConfigReq(Fsm fp, u_char *cp);
! 64: static void EcpDecodeConfig(Fsm fp, FsmOption a, int num, int mode);
! 65: static void EcpLayerUp(Fsm fp);
! 66: static void EcpLayerDown(Fsm fp);
! 67: static void EcpFailure(Fsm f, enum fsmfail reason);
! 68: static void EcpRecvResetReq(Fsm fp, int id, Mbuf bp);
! 69: static void EcpRecvResetAck(Fsm fp, int id, Mbuf bp);
! 70:
! 71: static int EcpSetCommand(Context ctx, int ac, char *av[], void *arg);
! 72: static EncType EcpFindType(int type, int *indexp);
! 73: static const char *EcpTypeName(int type);
! 74:
! 75: static void EcpNgDataEvent(int type, void *cookie);
! 76:
! 77: /*
! 78: * GLOBAL VARIABLES
! 79: */
! 80:
! 81: const struct cmdtab EcpSetCmds[] =
! 82: {
! 83: { "key {string}", "Set encryption key",
! 84: EcpSetCommand, NULL, 2, (void *) SET_KEY },
! 85: { "accept [opt ...]", "Accept option",
! 86: EcpSetCommand, NULL, 2, (void *) SET_ACCEPT },
! 87: { "deny [opt ...]", "Deny option",
! 88: EcpSetCommand, NULL, 2, (void *) SET_DENY },
! 89: { "enable [opt ...]", "Enable option",
! 90: EcpSetCommand, NULL, 2, (void *) SET_ENABLE },
! 91: { "disable [opt ...]", "Disable option",
! 92: EcpSetCommand, NULL, 2, (void *) SET_DISABLE },
! 93: { "yes [opt ...]", "Enable and accept option",
! 94: EcpSetCommand, NULL, 2, (void *) SET_YES },
! 95: { "no [opt ...]", "Disable and deny option",
! 96: EcpSetCommand, NULL, 2, (void *) SET_NO },
! 97: { NULL },
! 98: };
! 99:
! 100: /*
! 101: * INTERNAL VARIABLES
! 102: */
! 103:
! 104: /* These should be listed in order of preference */
! 105:
! 106: static const EncType gEncTypes[] =
! 107: {
! 108: #ifdef ECP_DES
! 109: &gDeseBisEncType,
! 110: &gDeseEncType,
! 111: #endif
! 112: };
! 113: #define ECP_NUM_PROTOS (sizeof(gEncTypes) / sizeof(*gEncTypes))
! 114:
! 115: /* Corresponding option list */
! 116:
! 117: static const struct confinfo *gConfList;
! 118:
! 119: /* Initializer for struct fsm fields */
! 120:
! 121: static const struct fsmtype gEcpFsmType =
! 122: {
! 123: "ECP",
! 124: PROTO_ECP,
! 125: ECP_KNOWN_CODES,
! 126: FALSE,
! 127: LG_ECP, LG_ECP2,
! 128: NULL,
! 129: EcpLayerUp,
! 130: EcpLayerDown,
! 131: NULL,
! 132: NULL,
! 133: EcpBuildConfigReq,
! 134: EcpDecodeConfig,
! 135: EcpConfigure,
! 136: EcpUnConfigure,
! 137: NULL,
! 138: NULL,
! 139: NULL,
! 140: NULL,
! 141: EcpFailure,
! 142: EcpRecvResetReq,
! 143: EcpRecvResetAck,
! 144: };
! 145:
! 146: /* Names for different types of encryption */
! 147:
! 148: static const struct ecpname
! 149: {
! 150: u_char type;
! 151: const char *name;
! 152: }
! 153: gEcpTypeNames[] =
! 154: {
! 155: { ECP_TY_OUI, "OUI" },
! 156: { ECP_TY_DESE, "DESE" },
! 157: { ECP_TY_3DESE, "3DESE" },
! 158: { ECP_TY_DESE_bis, "DESE-bis" },
! 159: { 0, NULL },
! 160: };
! 161:
! 162: int gEcpCsock = -1; /* Socket node control socket */
! 163: int gEcpDsock = -1; /* Socket node data socket */
! 164: EventRef gEcpDataEvent;
! 165:
! 166: int
! 167: EcpsInit(void)
! 168: {
! 169: char name[NG_NODESIZ];
! 170:
! 171: /* Create a netgraph socket node */
! 172: snprintf(name, sizeof(name), "mpd%d-eso", gPid);
! 173: if (NgMkSockNode(name, &gEcpCsock, &gEcpDsock) < 0) {
! 174: Perror("EcpsInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
! 175: return(-1);
! 176: }
! 177: (void) fcntl(gEcpCsock, F_SETFD, 1);
! 178: (void) fcntl(gEcpDsock, F_SETFD, 1);
! 179:
! 180: /* Listen for happenings on our node */
! 181: EventRegister(&gEcpDataEvent, EVENT_READ,
! 182: gEcpDsock, EVENT_RECURRING, EcpNgDataEvent, NULL);
! 183:
! 184: return (0);
! 185: }
! 186:
! 187: void
! 188: EcpsShutdown(void)
! 189: {
! 190: close(gEcpCsock);
! 191: gEcpCsock = -1;
! 192: EventUnRegister(&gEcpDataEvent);
! 193: close(gEcpDsock);
! 194: gEcpDsock = -1;
! 195: }
! 196:
! 197: /*
! 198: * EcpInit()
! 199: */
! 200:
! 201: void
! 202: EcpInit(Bund b)
! 203: {
! 204: EcpState ecp = &b->ecp;
! 205:
! 206: /* Init ECP state for this bundle */
! 207:
! 208: memset(ecp, 0, sizeof(*ecp));
! 209: FsmInit(&ecp->fsm, &gEcpFsmType, b);
! 210: ecp->fsm.conf.maxfailure = ECP_MAXFAILURE;
! 211:
! 212: /* Construct options list if we haven't done so already */
! 213:
! 214: if (gConfList == NULL)
! 215: {
! 216: struct confinfo *ci;
! 217: int k;
! 218:
! 219: ci = Malloc(MB_CRYPT, (ECP_NUM_PROTOS + 1) * sizeof(*ci));
! 220: for (k = 0; k < ECP_NUM_PROTOS; k++)
! 221: {
! 222: ci[k].option = k;
! 223: ci[k].peered = TRUE;
! 224: ci[k].name = gEncTypes[k]->name;
! 225: }
! 226: ci[k].name = NULL;
! 227: gConfList = (const struct confinfo *) ci;
! 228: }
! 229: }
! 230:
! 231: /*
! 232: * EcpInst()
! 233: */
! 234:
! 235: void
! 236: EcpInst(Bund b, Bund bt)
! 237: {
! 238: EcpState ecp = &b->ecp;
! 239:
! 240: /* Init ECP state for this bundle */
! 241: memcpy(ecp, &bt->ecp, sizeof(*ecp));
! 242: FsmInst(&ecp->fsm, &bt->ecp.fsm, b);
! 243: }
! 244:
! 245: /*
! 246: * EcpConfigure()
! 247: */
! 248:
! 249: static void
! 250: EcpConfigure(Fsm fp)
! 251: {
! 252: Bund b = (Bund)fp->arg;
! 253: EcpState const ecp = &b->ecp;
! 254: int k;
! 255:
! 256: for (k = 0; k < ECP_NUM_PROTOS; k++)
! 257: {
! 258: EncType const et = gEncTypes[k];
! 259:
! 260: if (et->Configure)
! 261: (*et->Configure)(b);
! 262: }
! 263: ecp->xmit = NULL;
! 264: ecp->recv = NULL;
! 265: ecp->self_reject = 0;
! 266: ecp->peer_reject = 0;
! 267: }
! 268:
! 269: /*
! 270: * EcpUnConfigure()
! 271: */
! 272:
! 273: static void
! 274: EcpUnConfigure(Fsm fp)
! 275: {
! 276: Bund b = (Bund)fp->arg;
! 277: EcpState const ecp = &b->ecp;
! 278: int k;
! 279:
! 280: for (k = 0; k < ECP_NUM_PROTOS; k++)
! 281: {
! 282: EncType const et = gEncTypes[k];
! 283:
! 284: if (et->UnConfigure)
! 285: (*et->UnConfigure)(b);
! 286: }
! 287: ecp->xmit = NULL;
! 288: ecp->recv = NULL;
! 289: ecp->self_reject = 0;
! 290: ecp->peer_reject = 0;
! 291: }
! 292:
! 293: /*
! 294: * EcpNgDataEvent()
! 295: */
! 296:
! 297: static void
! 298: EcpNgDataEvent(int type, void *cookie)
! 299: {
! 300: Bund b;
! 301: struct sockaddr_ng naddr;
! 302: socklen_t nsize;
! 303: Mbuf bp;
! 304: int num = 0;
! 305: char *bundname, *rest;
! 306: int id;
! 307:
! 308: while (1) {
! 309: /* Protect from bundle shutdown and DoS */
! 310: if (num > 100)
! 311: return;
! 312:
! 313: bp = mballoc(4096);
! 314:
! 315: /* Read data */
! 316: nsize = sizeof(naddr);
! 317: if ((bp->cnt = recvfrom(gEcpDsock, MBDATA(bp), MBSPACE(bp),
! 318: MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
! 319: mbfree(bp);
! 320: if (errno == EAGAIN)
! 321: return;
! 322: Log(LG_BUND|LG_ERR, ("EcpNgDataEvent: socket read: %s", strerror(errno)));
! 323: return;
! 324: }
! 325: num++;
! 326:
! 327: /* Debugging */
! 328: LogDumpBp(LG_FRAME, bp,
! 329: "EcpNgDataEvent: rec'd %d bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
! 330:
! 331: bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
! 332: if (bundname[0] != 'e' && bundname[0] != 'd') {
! 333: Log(LG_ERR, ("ECP: Packet from unknown hook \"%s\"",
! 334: bundname));
! 335: mbfree(bp);
! 336: continue;
! 337: }
! 338: bundname++;
! 339: id = strtol(bundname, &rest, 10);
! 340: if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
! 341: Log(LG_ERR, ("ECP: Packet from unexisting bundle \"%s\"",
! 342: bundname));
! 343: mbfree(bp);
! 344: continue;
! 345: }
! 346:
! 347: b = gBundles[id];
! 348:
! 349: /* Packet requiring compression */
! 350: if (bundname[0] == 'e') {
! 351: bp = EcpDataOutput(b, bp);
! 352: } else {
! 353: /* Packet requiring decompression */
! 354: bp = EcpDataInput(b, bp);
! 355: }
! 356: if (bp)
! 357: NgFuncWriteFrame(gEcpDsock, naddr.sg_data, b->name, bp);
! 358: }
! 359: }
! 360:
! 361:
! 362: /*
! 363: * EcpDataOutput()
! 364: *
! 365: * Encrypt a frame. Consumes the original packet.
! 366: */
! 367:
! 368: Mbuf
! 369: EcpDataOutput(Bund b, Mbuf plain)
! 370: {
! 371: EcpState const ecp = &b->ecp;
! 372: Mbuf cypher;
! 373:
! 374: LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
! 375:
! 376: /* Encrypt packet */
! 377:
! 378: if ((!ecp->xmit) || (!ecp->xmit->Encrypt))
! 379: {
! 380: Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
! 381: mbfree(plain);
! 382: return(NULL);
! 383: }
! 384: cypher = (*ecp->xmit->Encrypt)(b, plain);
! 385: LogDumpBp(LG_FRAME, cypher, "[%s] %s: xmit cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
! 386:
! 387: /* Return result, with new protocol number */
! 388:
! 389: return(cypher);
! 390: }
! 391:
! 392: /*
! 393: * EcpDataInput()
! 394: *
! 395: * Decrypt incoming packet. If packet got garbled, return NULL.
! 396: * In any case, we consume the packet passed to us.
! 397: */
! 398:
! 399: Mbuf
! 400: EcpDataInput(Bund b, Mbuf cypher)
! 401: {
! 402: EcpState const ecp = &b->ecp;
! 403: Mbuf plain;
! 404:
! 405: LogDumpBp(LG_FRAME, cypher, "[%s] %s: recv cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
! 406:
! 407: /* Decrypt packet */
! 408:
! 409: if ((!ecp->recv) || (!ecp->recv->Decrypt))
! 410: {
! 411: Log(LG_ERR, ("[%s] %s: no encryption for recv", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
! 412: mbfree(cypher);
! 413: return(NULL);
! 414: }
! 415:
! 416: plain = (*ecp->recv->Decrypt)(b, cypher);
! 417:
! 418: /* Decrypted ok? */
! 419:
! 420: if (plain == NULL)
! 421: {
! 422: Log(LG_ECP, ("[%s] %s: decryption failed", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
! 423: return(NULL);
! 424: }
! 425:
! 426: LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
! 427: /* Done */
! 428:
! 429: return(plain);
! 430: }
! 431:
! 432: /*
! 433: * EcpUp()
! 434: */
! 435:
! 436: void
! 437: EcpUp(Bund b)
! 438: {
! 439: FsmUp(&b->ecp.fsm);
! 440: }
! 441:
! 442: /*
! 443: * EcpDown()
! 444: */
! 445:
! 446: void
! 447: EcpDown(Bund b)
! 448: {
! 449: FsmDown(&b->ecp.fsm);
! 450: }
! 451:
! 452: /*
! 453: * EcpOpen()
! 454: */
! 455:
! 456: void
! 457: EcpOpen(Bund b)
! 458: {
! 459: FsmOpen(&b->ecp.fsm);
! 460: }
! 461:
! 462: /*
! 463: * EcpClose()
! 464: */
! 465:
! 466: void
! 467: EcpClose(Bund b)
! 468: {
! 469: FsmClose(&b->ecp.fsm);
! 470: }
! 471:
! 472: /*
! 473: * EcpOpenCmd()
! 474: */
! 475:
! 476: int
! 477: EcpOpenCmd(Context ctx)
! 478: {
! 479: if (ctx->bund->tmpl)
! 480: Error("impossible to open template");
! 481: FsmOpen(&ctx->bund->ecp.fsm);
! 482: return (0);
! 483: }
! 484:
! 485: /*
! 486: * EcpCloseCmd()
! 487: */
! 488:
! 489: int
! 490: EcpCloseCmd(Context ctx)
! 491: {
! 492: if (ctx->bund->tmpl)
! 493: Error("impossible to close template");
! 494: FsmClose(&ctx->bund->ecp.fsm);
! 495: return (0);
! 496: }
! 497:
! 498: /*
! 499: * EcpFailure()
! 500: *
! 501: * This is fatal to the entire link if encryption is required.
! 502: */
! 503:
! 504: static void
! 505: EcpFailure(Fsm fp, enum fsmfail reason)
! 506: {
! 507: Bund b = (Bund)fp->arg;
! 508: if (Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD)) {
! 509: FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
! 510: FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
! 511: }
! 512: }
! 513:
! 514: /*
! 515: * EcpStat()
! 516: */
! 517:
! 518: int
! 519: EcpStat(Context ctx, int ac, char *av[], void *arg)
! 520: {
! 521: EcpState const ecp = &ctx->bund->ecp;
! 522:
! 523: Printf("[%s] %s [%s]\r\n", Pref(&ecp->fsm), Fsm(&ecp->fsm), FsmStateName(ecp->fsm.state));
! 524: Printf("Enabled protocols:\r\n");
! 525: OptStat(ctx, &ecp->options, gConfList);
! 526: Printf("Outgoing encryption:\r\n");
! 527: Printf("\tProto\t: %s\r\n", ecp->xmit ? ecp->xmit->name : "none");
! 528: if (ecp->xmit && ecp->xmit->Stat)
! 529: ecp->xmit->Stat(ctx, ECP_DIR_XMIT);
! 530: Printf("\tResets\t: %d\r\n", ecp->xmit_resets);
! 531: Printf("Incoming decryption:\r\n");
! 532: Printf("\tProto\t: %s\r\n", ecp->recv ? ecp->recv->name : "none");
! 533: if (ecp->recv && ecp->recv->Stat)
! 534: ecp->recv->Stat(ctx, ECP_DIR_RECV);
! 535: Printf("\tResets\t: %d\r\n", ecp->recv_resets);
! 536: return(0);
! 537: }
! 538:
! 539: /*
! 540: * EcpSendResetReq()
! 541: */
! 542:
! 543: void
! 544: EcpSendResetReq(Fsm fp)
! 545: {
! 546: Bund b = (Bund)fp->arg;
! 547: EcpState const ecp = &b->ecp;
! 548: EncType const et = ecp->recv;
! 549: Mbuf bp = NULL;
! 550:
! 551: assert(et);
! 552: ecp->recv_resets++;
! 553: if (et->SendResetReq)
! 554: bp = (*et->SendResetReq)(b);
! 555: Log(LG_ECP, ("[%s] %s: SendResetReq", Pref(fp), Fsm(fp)));
! 556: FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
! 557: }
! 558:
! 559: /*
! 560: * EcpRecvResetReq()
! 561: */
! 562:
! 563: void
! 564: EcpRecvResetReq(Fsm fp, int id, Mbuf bp)
! 565: {
! 566: Bund b = (Bund)fp->arg;
! 567: EcpState const ecp = &b->ecp;
! 568: EncType const et = ecp->xmit;
! 569:
! 570: ecp->xmit_resets++;
! 571: bp = (et && et->RecvResetReq) ? (*et->RecvResetReq)(b, id, bp) : NULL;
! 572: Log(fp->log, ("[%s] %s: SendResetAck", Pref(fp), Fsm(fp)));
! 573: FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
! 574: }
! 575:
! 576: /*
! 577: * EcpRecvResetAck()
! 578: */
! 579:
! 580: static void
! 581: EcpRecvResetAck(Fsm fp, int id, Mbuf bp)
! 582: {
! 583: Bund b = (Bund)fp->arg;
! 584: EcpState const ecp = &b->ecp;
! 585: EncType const et = ecp->recv;
! 586:
! 587: if (et && et->RecvResetAck)
! 588: (*et->RecvResetAck)(b, id, bp);
! 589: }
! 590:
! 591: /*
! 592: * EcpInput()
! 593: */
! 594:
! 595: void
! 596: EcpInput(Bund b, Mbuf bp)
! 597: {
! 598: FsmInput(&b->ecp.fsm, bp);
! 599: }
! 600:
! 601: /*
! 602: * EcpBuildConfigReq()
! 603: */
! 604:
! 605: static u_char *
! 606: EcpBuildConfigReq(Fsm fp, u_char *cp)
! 607: {
! 608: Bund b = (Bund)fp->arg;
! 609: EcpState const ecp = &b->ecp;
! 610: int type;
! 611:
! 612: /* Put in all options that peer hasn't rejected */
! 613:
! 614: for (ecp->xmit = NULL, type = 0; type < ECP_NUM_PROTOS; type++)
! 615: {
! 616: EncType const et = gEncTypes[type];
! 617:
! 618: if (Enabled(&ecp->options, type) && !ECP_PEER_REJECTED(ecp, type))
! 619: {
! 620: cp = (*et->BuildConfigReq)(b, cp);
! 621: if (!ecp->xmit)
! 622: ecp->xmit = et;
! 623: }
! 624: }
! 625: return(cp);
! 626: }
! 627:
! 628: /*
! 629: * EcpLayerUp()
! 630: *
! 631: * Called when ECP has reached the OPENED state
! 632: */
! 633:
! 634: static void
! 635: EcpLayerUp(Fsm fp)
! 636: {
! 637: Bund b = (Bund)fp->arg;
! 638: EcpState const ecp = &b->ecp;
! 639: struct ngm_connect cn;
! 640:
! 641: /* Initialize */
! 642: if (ecp->xmit && ecp->xmit->Init)
! 643: (*ecp->xmit->Init)(b, ECP_DIR_XMIT);
! 644: if (ecp->recv && ecp->recv->Init)
! 645: (*ecp->recv->Init)(b, ECP_DIR_RECV);
! 646:
! 647: if (ecp->recv && ecp->recv->Decrypt)
! 648: {
! 649: /* Connect a hook from the bpf node to our socket node */
! 650: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
! 651: snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
! 652: strcpy(cn.peerhook, NG_PPP_HOOK_DECRYPT);
! 653: if (NgSendMsg(gEcpCsock, ".:",
! 654: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 655: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 656: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
! 657: }
! 658: }
! 659: if (ecp->xmit && ecp->xmit->Encrypt)
! 660: {
! 661: /* Connect a hook from the bpf node to our socket node */
! 662: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
! 663: snprintf(cn.ourhook, sizeof(cn.ourhook), "e%d", b->id);
! 664: strcpy(cn.peerhook, NG_PPP_HOOK_ENCRYPT);
! 665: if (NgSendMsg(gEcpCsock, ".:",
! 666: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 667: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 668: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
! 669: }
! 670: }
! 671:
! 672: Log(LG_ECP, ("[%s] ECP: Encrypt using: %s", b->name, !ecp->xmit ? "none" : ecp->xmit->name));
! 673: Log(LG_ECP, ("[%s] ECP: Decrypt using: %s", b->name, !ecp->recv ? "none" : ecp->recv->name));
! 674:
! 675: /* Update PPP node config */
! 676: b->pppConfig.bund.enableEncryption = (ecp->xmit != NULL);
! 677: b->pppConfig.bund.enableDecryption = (ecp->recv != NULL);
! 678: NgFuncSetConfig(b);
! 679:
! 680: /* Update interface MTU */
! 681: BundUpdateParams(b);
! 682: }
! 683:
! 684: /*
! 685: * EcpLayerDown()
! 686: *
! 687: * Called when ECP leaves the OPENED state
! 688: */
! 689:
! 690: static void
! 691: EcpLayerDown(Fsm fp)
! 692: {
! 693: Bund b = (Bund)fp->arg;
! 694: EcpState const ecp = &b->ecp;
! 695:
! 696: /* Update PPP node config */
! 697: b->pppConfig.bund.enableEncryption = 0;
! 698: b->pppConfig.bund.enableDecryption = 0;
! 699: NgFuncSetConfig(b);
! 700:
! 701: /* Update interface MTU */
! 702: BundUpdateParams(b);
! 703:
! 704: if (ecp->xmit != NULL && ecp->xmit->Encrypt != NULL) {
! 705: char hook[NG_HOOKSIZ];
! 706: /* Disconnect hook. */
! 707: snprintf(hook, sizeof(hook), "e%d", b->id);
! 708: NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
! 709: }
! 710:
! 711: if (ecp->recv != NULL && ecp->recv->Decrypt != NULL) {
! 712: char hook[NG_HOOKSIZ];
! 713: /* Disconnect hook. */
! 714: snprintf(hook, sizeof(hook), "d%d", b->id);
! 715: NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
! 716: }
! 717:
! 718: if (ecp->xmit && ecp->xmit->Cleanup)
! 719: (ecp->xmit->Cleanup)(b, ECP_DIR_XMIT);
! 720: if (ecp->recv && ecp->recv->Cleanup)
! 721: (ecp->recv->Cleanup)(b, ECP_DIR_RECV);
! 722:
! 723: ecp->xmit_resets = 0;
! 724: ecp->recv_resets = 0;
! 725: }
! 726:
! 727: /*
! 728: * EcpDecodeConfig()
! 729: */
! 730:
! 731: static void
! 732: EcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
! 733: {
! 734: Bund b = (Bund)fp->arg;
! 735: EcpState const ecp = &b->ecp;
! 736: u_int ackSizeSave, rejSizeSave;
! 737: int k, rej;
! 738:
! 739: /* Forget our previous choice on new request */
! 740: if (mode == MODE_REQ)
! 741: ecp->recv = NULL;
! 742:
! 743: /* Decode each config option */
! 744:
! 745: for (k = 0; k < num; k++)
! 746: {
! 747: FsmOption const opt = &list[k];
! 748: int index;
! 749: EncType et;
! 750:
! 751: Log(LG_ECP, ("[%s] %s", b->name, EcpTypeName(opt->type)));
! 752: if ((et = EcpFindType(opt->type, &index)) == NULL)
! 753: {
! 754: if (mode == MODE_REQ)
! 755: {
! 756: Log(LG_ECP, ("[%s] Not supported", b->name));
! 757: FsmRej(fp, opt);
! 758: }
! 759: continue;
! 760: }
! 761: switch (mode)
! 762: {
! 763: case MODE_REQ:
! 764: ackSizeSave = gAckSize;
! 765: rejSizeSave = gRejSize;
! 766: rej = (!Acceptable(&ecp->options, index)
! 767: || ECP_SELF_REJECTED(ecp, index)
! 768: || (ecp->recv && ecp->recv != et));
! 769: if (rej)
! 770: {
! 771: (*et->DecodeConfig)(fp, opt, MODE_NOP);
! 772: FsmRej(fp, opt);
! 773: break;
! 774: }
! 775: (*et->DecodeConfig)(fp, opt, mode);
! 776: if (gRejSize != rejSizeSave) /* we rejected it */
! 777: {
! 778: ECP_SELF_REJ(ecp, index);
! 779: break;
! 780: }
! 781: if (gAckSize != ackSizeSave) /* we accepted it */
! 782: ecp->recv = et;
! 783: break;
! 784:
! 785: case MODE_NAK:
! 786: (*et->DecodeConfig)(fp, opt, mode);
! 787: break;
! 788:
! 789: case MODE_REJ:
! 790: (*et->DecodeConfig)(fp, opt, mode);
! 791: ECP_PEER_REJ(ecp, index);
! 792: break;
! 793:
! 794: case MODE_NOP:
! 795: (*et->DecodeConfig)(fp, opt, mode);
! 796: break;
! 797: }
! 798: }
! 799: }
! 800:
! 801: /*
! 802: * EcpSubtractBloat()
! 803: *
! 804: * Given that "size" is our MTU, return the maximum length frame
! 805: * we can encrypt without the result being longer than "size".
! 806: */
! 807:
! 808: int
! 809: EcpSubtractBloat(Bund b, int size)
! 810: {
! 811: EcpState const ecp = &b->ecp;
! 812:
! 813: /* Check transmit encryption */
! 814: if (OPEN_STATE(ecp->fsm.state) && ecp->xmit && ecp->xmit->SubtractBloat)
! 815: size = (*ecp->xmit->SubtractBloat)(b, size);
! 816:
! 817: /* Account for ECP's protocol number overhead */
! 818: if (OPEN_STATE(ecp->fsm.state))
! 819: size -= ECP_OVERHEAD;
! 820:
! 821: /* Done */
! 822: return(size);
! 823: }
! 824:
! 825: /*
! 826: * EcpSetCommand()
! 827: */
! 828:
! 829: static int
! 830: EcpSetCommand(Context ctx, int ac, char *av[], void *arg)
! 831: {
! 832: EcpState const ecp = &ctx->bund->ecp;
! 833:
! 834: if (ac == 0)
! 835: return(-1);
! 836: switch ((intptr_t)arg)
! 837: {
! 838: case SET_KEY:
! 839: if (ac != 1)
! 840: return(-1);
! 841: strlcpy(ecp->key, av[0], sizeof(ecp->key));
! 842: break;
! 843:
! 844: case SET_ACCEPT:
! 845: AcceptCommand(ac, av, &ecp->options, gConfList);
! 846: break;
! 847:
! 848: case SET_DENY:
! 849: DenyCommand(ac, av, &ecp->options, gConfList);
! 850: break;
! 851:
! 852: case SET_ENABLE:
! 853: EnableCommand(ac, av, &ecp->options, gConfList);
! 854: break;
! 855:
! 856: case SET_DISABLE:
! 857: DisableCommand(ac, av, &ecp->options, gConfList);
! 858: break;
! 859:
! 860: case SET_YES:
! 861: YesCommand(ac, av, &ecp->options, gConfList);
! 862: break;
! 863:
! 864: case SET_NO:
! 865: NoCommand(ac, av, &ecp->options, gConfList);
! 866: break;
! 867:
! 868: default:
! 869: assert(0);
! 870: }
! 871: return(0);
! 872: }
! 873:
! 874: /*
! 875: * EcpFindType()
! 876: */
! 877:
! 878: static EncType
! 879: EcpFindType(int type, int *indexp)
! 880: {
! 881: int k;
! 882:
! 883: for (k = 0; k < ECP_NUM_PROTOS; k++)
! 884: if (gEncTypes[k]->type == type)
! 885: {
! 886: if (indexp)
! 887: *indexp = k;
! 888: return(gEncTypes[k]);
! 889: }
! 890: return(NULL);
! 891: }
! 892:
! 893: /*
! 894: * EcpTypeName()
! 895: */
! 896:
! 897: static const char *
! 898: EcpTypeName(int type)
! 899: {
! 900: const struct ecpname *p;
! 901:
! 902: for (p = gEcpTypeNames; p->name; p++)
! 903: if (p->type == type)
! 904: return(p->name);
! 905: return("UNKNOWN");
! 906: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>