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

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

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