Annotation of embedaddon/mpd/src/ecp.c, revision 1.1.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>