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>