Annotation of embedaddon/mpd/src/ecp.c, revision 1.1.1.2

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;
1.1.1.2 ! misho     305:     char                *bundname, *rest, *b1;
1.1       misho     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,
1.1.1.2 ! misho     329:            "EcpNgDataEvent: rec'd %zu bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
1.1       misho     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:        }
1.1.1.2 ! misho     338:        /* Keep old value */
        !           339:        b1 = bundname;
1.1       misho     340:        bundname++;
                    341:        id = strtol(bundname, &rest, 10);
                    342:        if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
                    343:            Log(LG_ERR, ("ECP: Packet from unexisting bundle \"%s\"",
                    344:                bundname));
                    345:            mbfree(bp);
                    346:            continue;
                    347:        }
                    348:                
                    349:        b = gBundles[id];
                    350: 
                    351:        /* Packet requiring compression */
1.1.1.2 ! misho     352:        if (b1[0] == 'e') {
1.1       misho     353:            bp = EcpDataOutput(b, bp);
                    354:        } else {
                    355:            /* Packet requiring decompression */
                    356:            bp = EcpDataInput(b, bp);
                    357:        }
                    358:        if (bp)
                    359:            NgFuncWriteFrame(gEcpDsock, naddr.sg_data, b->name, bp);
                    360:     }
                    361: }
                    362: 
                    363: 
                    364: /*
                    365:  * EcpDataOutput()
                    366:  *
                    367:  * Encrypt a frame. Consumes the original packet.
                    368:  */
                    369: 
                    370: Mbuf
                    371: EcpDataOutput(Bund b, Mbuf plain)
                    372: {
                    373:   EcpState     const ecp = &b->ecp;
                    374:   Mbuf         cypher;
                    375: 
                    376:   LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
                    377: 
                    378: /* Encrypt packet */
                    379: 
                    380:   if ((!ecp->xmit) || (!ecp->xmit->Encrypt))
                    381:   {
                    382:     Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
                    383:     mbfree(plain);
                    384:     return(NULL);
                    385:   }
                    386:   cypher = (*ecp->xmit->Encrypt)(b, plain);
                    387:   LogDumpBp(LG_FRAME, cypher, "[%s] %s: xmit cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
                    388: 
                    389: /* Return result, with new protocol number */
                    390: 
                    391:   return(cypher);
                    392: }
                    393: 
                    394: /*
                    395:  * EcpDataInput()
                    396:  *
                    397:  * Decrypt incoming packet. If packet got garbled, return NULL.
                    398:  * In any case, we consume the packet passed to us.
                    399:  */
                    400: 
                    401: Mbuf
                    402: EcpDataInput(Bund b, Mbuf cypher)
                    403: {
                    404:   EcpState     const ecp = &b->ecp;
                    405:   Mbuf         plain;
                    406: 
                    407:   LogDumpBp(LG_FRAME, cypher, "[%s] %s: recv cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
                    408: 
                    409: /* Decrypt packet */
                    410: 
                    411:   if ((!ecp->recv) || (!ecp->recv->Decrypt))
                    412:   {
                    413:     Log(LG_ERR, ("[%s] %s: no encryption for recv", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
                    414:     mbfree(cypher);
                    415:     return(NULL);
                    416:   }
                    417: 
                    418:   plain = (*ecp->recv->Decrypt)(b, cypher);
                    419: 
                    420: /* Decrypted ok? */
                    421: 
                    422:   if (plain == NULL)
                    423:   {
                    424:     Log(LG_ECP, ("[%s] %s: decryption failed", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
                    425:     return(NULL);
                    426:   }
                    427: 
                    428:   LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
                    429: /* Done */
                    430: 
                    431:   return(plain);
                    432: }
                    433: 
                    434: /*
                    435:  * EcpUp()
                    436:  */
                    437: 
                    438: void
                    439: EcpUp(Bund b)
                    440: {
                    441:   FsmUp(&b->ecp.fsm);
                    442: }
                    443: 
                    444: /*
                    445:  * EcpDown()
                    446:  */
                    447: 
                    448: void
                    449: EcpDown(Bund b)
                    450: {
                    451:   FsmDown(&b->ecp.fsm);
                    452: }
                    453: 
                    454: /*
                    455:  * EcpOpen()
                    456:  */
                    457: 
                    458: void
                    459: EcpOpen(Bund b)
                    460: {
                    461:   FsmOpen(&b->ecp.fsm);
                    462: }
                    463: 
                    464: /*
                    465:  * EcpClose()
                    466:  */
                    467: 
                    468: void
                    469: EcpClose(Bund b)
                    470: {
                    471:   FsmClose(&b->ecp.fsm);
                    472: }
                    473: 
                    474: /*
                    475:  * EcpOpenCmd()
                    476:  */
                    477: 
                    478: int
                    479: EcpOpenCmd(Context ctx)
                    480: {
                    481:     if (ctx->bund->tmpl)
                    482:        Error("impossible to open template");
                    483:     FsmOpen(&ctx->bund->ecp.fsm);
                    484:     return (0);
                    485: }
                    486: 
                    487: /*
                    488:  * EcpCloseCmd()
                    489:  */
                    490: 
                    491: int
                    492: EcpCloseCmd(Context ctx)
                    493: {
                    494:     if (ctx->bund->tmpl)
                    495:        Error("impossible to close template");
                    496:     FsmClose(&ctx->bund->ecp.fsm);
                    497:     return (0);
                    498: }
                    499: 
                    500: /*
                    501:  * EcpFailure()
                    502:  *
                    503:  * This is fatal to the entire link if encryption is required.
                    504:  */
                    505: 
                    506: static void
                    507: EcpFailure(Fsm fp, enum fsmfail reason)
                    508: {
                    509:     Bund       b = (Bund)fp->arg;
                    510:     if (Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD)) {
                    511:        FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
                    512:        FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
                    513:     }
                    514: }
                    515: 
                    516: /*
                    517:  * EcpStat()
                    518:  */
                    519: 
                    520: int
                    521: EcpStat(Context ctx, int ac, char *av[], void *arg)
                    522: {
                    523:   EcpState     const ecp = &ctx->bund->ecp;
                    524: 
                    525:   Printf("[%s] %s [%s]\r\n", Pref(&ecp->fsm), Fsm(&ecp->fsm), FsmStateName(ecp->fsm.state));
                    526:   Printf("Enabled protocols:\r\n");
                    527:   OptStat(ctx, &ecp->options, gConfList);
                    528:   Printf("Outgoing encryption:\r\n");
                    529:   Printf("\tProto\t: %s\r\n", ecp->xmit ? ecp->xmit->name : "none");
                    530:   if (ecp->xmit && ecp->xmit->Stat)
                    531:     ecp->xmit->Stat(ctx, ECP_DIR_XMIT);
                    532:   Printf("\tResets\t: %d\r\n", ecp->xmit_resets);
                    533:   Printf("Incoming decryption:\r\n");
                    534:   Printf("\tProto\t: %s\r\n", ecp->recv ? ecp->recv->name : "none");
                    535:   if (ecp->recv && ecp->recv->Stat)
                    536:     ecp->recv->Stat(ctx, ECP_DIR_RECV);
                    537:   Printf("\tResets\t: %d\r\n", ecp->recv_resets);
                    538:   return(0);
                    539: }
                    540: 
                    541: /*
                    542:  * EcpSendResetReq()
                    543:  */
                    544: 
                    545: void
                    546: EcpSendResetReq(Fsm fp)
                    547: {
                    548:     Bund       b = (Bund)fp->arg;
                    549:   EcpState     const ecp = &b->ecp;
                    550:   EncType      const et = ecp->recv;
                    551:   Mbuf         bp = NULL;
                    552: 
                    553:   assert(et);
                    554:   ecp->recv_resets++;
                    555:   if (et->SendResetReq)
                    556:     bp = (*et->SendResetReq)(b);
                    557:   Log(LG_ECP, ("[%s] %s: SendResetReq", Pref(fp), Fsm(fp)));
                    558:   FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
                    559: }
                    560: 
                    561: /*
                    562:  * EcpRecvResetReq()
                    563:  */
                    564: 
                    565: void
                    566: EcpRecvResetReq(Fsm fp, int id, Mbuf bp)
                    567: {
                    568:     Bund       b = (Bund)fp->arg;
                    569:   EcpState     const ecp = &b->ecp;
                    570:   EncType      const et = ecp->xmit;
                    571: 
                    572:   ecp->xmit_resets++;
                    573:   bp = (et && et->RecvResetReq) ? (*et->RecvResetReq)(b, id, bp) : NULL;
                    574:   Log(fp->log, ("[%s] %s: SendResetAck", Pref(fp), Fsm(fp)));
                    575:   FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
                    576: }
                    577: 
                    578: /*
                    579:  * EcpRecvResetAck()
                    580:  */
                    581: 
                    582: static void
                    583: EcpRecvResetAck(Fsm fp, int id, Mbuf bp)
                    584: {
                    585:     Bund       b = (Bund)fp->arg;
                    586:   EcpState     const ecp = &b->ecp;
                    587:   EncType      const et = ecp->recv;
                    588: 
                    589:   if (et && et->RecvResetAck)
                    590:     (*et->RecvResetAck)(b, id, bp);
                    591: }
                    592: 
                    593: /*
                    594:  * EcpInput()
                    595:  */
                    596: 
                    597: void
                    598: EcpInput(Bund b, Mbuf bp)
                    599: {
                    600:   FsmInput(&b->ecp.fsm, bp);
                    601: }
                    602: 
                    603: /*
                    604:  * EcpBuildConfigReq()
                    605:  */
                    606: 
                    607: static u_char *
                    608: EcpBuildConfigReq(Fsm fp, u_char *cp)
                    609: {
                    610:     Bund       b = (Bund)fp->arg;
                    611:   EcpState     const ecp = &b->ecp;
                    612:   int          type;
                    613: 
                    614: /* Put in all options that peer hasn't rejected */
                    615: 
                    616:   for (ecp->xmit = NULL, type = 0; type < ECP_NUM_PROTOS; type++)
                    617:   {
                    618:     EncType    const et = gEncTypes[type];
                    619: 
                    620:     if (Enabled(&ecp->options, type) && !ECP_PEER_REJECTED(ecp, type))
                    621:     {
                    622:       cp = (*et->BuildConfigReq)(b, cp);
                    623:       if (!ecp->xmit)
                    624:        ecp->xmit = et;
                    625:     }
                    626:   }
                    627:   return(cp);
                    628: }
                    629: 
                    630: /*
                    631:  * EcpLayerUp()
                    632:  *
                    633:  * Called when ECP has reached the OPENED state
                    634:  */
                    635: 
                    636: static void
                    637: EcpLayerUp(Fsm fp)
                    638: {
                    639:     Bund       b = (Bund)fp->arg;
                    640:   EcpState     const ecp = &b->ecp;
                    641:   struct ngm_connect    cn;
                    642: 
                    643:   /* Initialize */
                    644:   if (ecp->xmit && ecp->xmit->Init)
                    645:     (*ecp->xmit->Init)(b, ECP_DIR_XMIT);
                    646:   if (ecp->recv && ecp->recv->Init)
                    647:     (*ecp->recv->Init)(b, ECP_DIR_RECV);
                    648: 
                    649:   if (ecp->recv && ecp->recv->Decrypt) 
                    650:   {
                    651:     /* Connect a hook from the bpf node to our socket node */
                    652:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
                    653:     snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
                    654:     strcpy(cn.peerhook, NG_PPP_HOOK_DECRYPT);
                    655:     if (NgSendMsg(gEcpCsock, ".:",
                    656:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    657:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    658:           b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    659:     }
                    660:   }
                    661:   if (ecp->xmit && ecp->xmit->Encrypt)
                    662:   {
                    663:     /* Connect a hook from the bpf node to our socket node */
                    664:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
                    665:     snprintf(cn.ourhook, sizeof(cn.ourhook), "e%d", b->id);
                    666:     strcpy(cn.peerhook, NG_PPP_HOOK_ENCRYPT);
                    667:     if (NgSendMsg(gEcpCsock, ".:",
                    668:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    669:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    670:           b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    671:     }
                    672:   }
                    673: 
                    674:   Log(LG_ECP, ("[%s] ECP: Encrypt using: %s", b->name, !ecp->xmit ? "none" : ecp->xmit->name));
                    675:   Log(LG_ECP, ("[%s] ECP: Decrypt using: %s", b->name, !ecp->recv ? "none" : ecp->recv->name));
                    676: 
                    677:   /* Update PPP node config */
                    678:   b->pppConfig.bund.enableEncryption = (ecp->xmit != NULL);
                    679:   b->pppConfig.bund.enableDecryption = (ecp->recv != NULL);
                    680:   NgFuncSetConfig(b);
                    681: 
                    682:   /* Update interface MTU */
                    683:   BundUpdateParams(b);
                    684: }
                    685: 
                    686: /*
                    687:  * EcpLayerDown()
                    688:  *
                    689:  * Called when ECP leaves the OPENED state
                    690:  */
                    691: 
                    692: static void
                    693: EcpLayerDown(Fsm fp)
                    694: {
                    695:     Bund       b = (Bund)fp->arg;
                    696:   EcpState     const ecp = &b->ecp;
                    697: 
                    698:   /* Update PPP node config */
                    699:   b->pppConfig.bund.enableEncryption = 0;
                    700:   b->pppConfig.bund.enableDecryption = 0;
                    701:   NgFuncSetConfig(b);
                    702: 
                    703:   /* Update interface MTU */
                    704:   BundUpdateParams(b);
                    705: 
                    706:   if (ecp->xmit != NULL && ecp->xmit->Encrypt != NULL) {
                    707:     char       hook[NG_HOOKSIZ];
                    708:     /* Disconnect hook. */
                    709:     snprintf(hook, sizeof(hook), "e%d", b->id);
                    710:     NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
                    711:   }
                    712:   
                    713:   if (ecp->recv != NULL && ecp->recv->Decrypt != NULL) {
                    714:     char       hook[NG_HOOKSIZ];
                    715:     /* Disconnect hook. */
                    716:     snprintf(hook, sizeof(hook), "d%d", b->id);
                    717:     NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
                    718:   }
                    719: 
                    720:   if (ecp->xmit && ecp->xmit->Cleanup)
                    721:     (ecp->xmit->Cleanup)(b, ECP_DIR_XMIT);
                    722:   if (ecp->recv && ecp->recv->Cleanup)
                    723:     (ecp->recv->Cleanup)(b, ECP_DIR_RECV);
                    724:     
                    725:   ecp->xmit_resets = 0;
                    726:   ecp->recv_resets = 0;
                    727: }
                    728: 
                    729: /*
                    730:  * EcpDecodeConfig()
                    731:  */
                    732: 
                    733: static void
                    734: EcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
                    735: {
                    736:     Bund       b = (Bund)fp->arg;
                    737:   EcpState     const ecp = &b->ecp;
                    738:   u_int                ackSizeSave, rejSizeSave;
                    739:   int          k, rej;
                    740: 
                    741:   /* Forget our previous choice on new request */
                    742:   if (mode == MODE_REQ)
                    743:     ecp->recv = NULL;
                    744: 
                    745: /* Decode each config option */
                    746: 
                    747:   for (k = 0; k < num; k++)
                    748:   {
                    749:     FsmOption  const opt = &list[k];
                    750:     int                index;
                    751:     EncType    et;
                    752: 
                    753:     Log(LG_ECP, ("[%s] %s", b->name, EcpTypeName(opt->type)));
                    754:     if ((et = EcpFindType(opt->type, &index)) == NULL)
                    755:     {
                    756:       if (mode == MODE_REQ)
                    757:       {
                    758:        Log(LG_ECP, ("[%s]   Not supported", b->name));
                    759:        FsmRej(fp, opt);
                    760:       }
                    761:       continue;
                    762:     }
                    763:     switch (mode)
                    764:     {
                    765:       case MODE_REQ:
                    766:        ackSizeSave = gAckSize;
                    767:        rejSizeSave = gRejSize;
                    768:        rej = (!Acceptable(&ecp->options, index)
                    769:          || ECP_SELF_REJECTED(ecp, index)
                    770:          || (ecp->recv && ecp->recv != et));
                    771:        if (rej)
                    772:        {
                    773:          (*et->DecodeConfig)(fp, opt, MODE_NOP);
                    774:          FsmRej(fp, opt);
                    775:          break;
                    776:        }
                    777:        (*et->DecodeConfig)(fp, opt, mode);
                    778:        if (gRejSize != rejSizeSave)            /* we rejected it */
                    779:        {
                    780:          ECP_SELF_REJ(ecp, index);
                    781:          break;
                    782:        }
                    783:        if (gAckSize != ackSizeSave)            /* we accepted it */
                    784:          ecp->recv = et;
                    785:        break;
                    786: 
                    787:       case MODE_NAK:
                    788:        (*et->DecodeConfig)(fp, opt, mode);
                    789:        break;
                    790: 
                    791:       case MODE_REJ:
                    792:        (*et->DecodeConfig)(fp, opt, mode);
                    793:        ECP_PEER_REJ(ecp, index);
                    794:        break;
                    795: 
                    796:       case MODE_NOP:
                    797:        (*et->DecodeConfig)(fp, opt, mode);
                    798:        break;
                    799:     }
                    800:   }
                    801: }
                    802: 
                    803: /*
                    804:  * EcpSubtractBloat()
                    805:  *
                    806:  * Given that "size" is our MTU, return the maximum length frame
                    807:  * we can encrypt without the result being longer than "size".
                    808:  */
                    809: 
                    810: int
                    811: EcpSubtractBloat(Bund b, int size)
                    812: {
                    813:   EcpState     const ecp = &b->ecp;
                    814: 
                    815:   /* Check transmit encryption */
                    816:   if (OPEN_STATE(ecp->fsm.state) && ecp->xmit && ecp->xmit->SubtractBloat)
                    817:     size = (*ecp->xmit->SubtractBloat)(b, size);
                    818: 
                    819:   /* Account for ECP's protocol number overhead */
                    820:   if (OPEN_STATE(ecp->fsm.state))
                    821:     size -= ECP_OVERHEAD;
                    822: 
                    823:   /* Done */
                    824:   return(size);
                    825: }
                    826: 
                    827: /*
                    828:  * EcpSetCommand()
                    829:  */
                    830: 
                    831: static int
                    832: EcpSetCommand(Context ctx, int ac, char *av[], void *arg)
                    833: {
                    834:   EcpState     const ecp = &ctx->bund->ecp;
                    835: 
                    836:   if (ac == 0)
                    837:     return(-1);
                    838:   switch ((intptr_t)arg)
                    839:   {
                    840:     case SET_KEY:
                    841:       if (ac != 1)
                    842:        return(-1);
                    843:       strlcpy(ecp->key, av[0], sizeof(ecp->key));
                    844:       break;
                    845: 
                    846:     case SET_ACCEPT:
                    847:       AcceptCommand(ac, av, &ecp->options, gConfList);
                    848:       break;
                    849: 
                    850:     case SET_DENY:
                    851:       DenyCommand(ac, av, &ecp->options, gConfList);
                    852:       break;
                    853: 
                    854:     case SET_ENABLE:
                    855:       EnableCommand(ac, av, &ecp->options, gConfList);
                    856:       break;
                    857: 
                    858:     case SET_DISABLE:
                    859:       DisableCommand(ac, av, &ecp->options, gConfList);
                    860:       break;
                    861: 
                    862:     case SET_YES:
                    863:       YesCommand(ac, av, &ecp->options, gConfList);
                    864:       break;
                    865: 
                    866:     case SET_NO:
                    867:       NoCommand(ac, av, &ecp->options, gConfList);
                    868:       break;
                    869: 
                    870:     default:
                    871:       assert(0);
                    872:   }
                    873:   return(0);
                    874: }
                    875: 
                    876: /*
                    877:  * EcpFindType()
                    878:  */
                    879: 
                    880: static EncType
                    881: EcpFindType(int type, int *indexp)
                    882: {
                    883:   int  k;
                    884: 
                    885:   for (k = 0; k < ECP_NUM_PROTOS; k++)
                    886:     if (gEncTypes[k]->type == type)
                    887:     {
                    888:       if (indexp)
                    889:        *indexp = k;
                    890:       return(gEncTypes[k]);
                    891:     }
                    892:   return(NULL);
                    893: }
                    894: 
                    895: /*
                    896:  * EcpTypeName()
                    897:  */
                    898: 
                    899: static const char *
                    900: EcpTypeName(int type)
                    901: {
                    902:   const struct ecpname *p;
                    903: 
                    904:   for (p = gEcpTypeNames; p->name; p++)
                    905:     if (p->type == type)
                    906:       return(p->name);
                    907:   return("UNKNOWN");
                    908: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>