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

1.1       misho       1: 
                      2: /*
                      3:  * ccp.c
                      4:  *
                      5:  * Written by Archie Cobbs <archie@freebsd.org>
                      6:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
                      7:  * See ``COPYRIGHT.whistle''
                      8:  */
                      9: 
                     10: #include "defs.h"
                     11: #include "ppp.h"
                     12: #include "ccp.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 CCP_MAXFAILURE       7
                     25: 
                     26:   #define CCP_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:   /* Set menu options */
                     37:   enum {
                     38:     SET_ACCEPT,
                     39:     SET_DENY,
                     40:     SET_ENABLE,
                     41:     SET_DISABLE,
                     42:     SET_YES,
                     43:     SET_NO
                     44:   };
                     45: 
                     46: /*
                     47:  * INTERNAL FUNCTIONS
                     48:  */
                     49: 
                     50:   static void          CcpConfigure(Fsm fp);
                     51:   static void          CcpUnConfigure(Fsm fp);
                     52:   static u_char                *CcpBuildConfigReq(Fsm fp, u_char *cp);
                     53:   static void          CcpDecodeConfig(Fsm f, FsmOption a, int num, int mode);
                     54:   static void          CcpLayerUp(Fsm fp);
                     55:   static void          CcpLayerDown(Fsm fp);
                     56:   static void          CcpFailure(Fsm f, enum fsmfail reason);
                     57:   static void          CcpRecvResetReq(Fsm fp, int id, Mbuf bp);
                     58:   static void          CcpRecvResetAck(Fsm fp, int id, Mbuf bp);
                     59: 
                     60:   static int           CcpCheckEncryption(Bund b);
1.1.1.3 ! misho      61:   static int           CcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1       misho      62:   static CompType      CcpFindComp(int type, int *indexp);
                     63:   static const char    *CcpTypeName(int type, char *buf, size_t len);
                     64: 
                     65:   static void          CcpNgCtrlEvent(int type, void *cookie);
                     66:   static void          CcpNgDataEvent(int type, void *cookie);
                     67: 
                     68: /*
                     69:  * GLOBAL VARIABLES
                     70:  */
                     71: 
                     72:   const struct cmdtab CcpSetCmds[] = {
                     73:     { "accept [opt ...]",              "Accept option",
                     74:        CcpSetCommand, NULL, 2, (void *) SET_ACCEPT },
                     75:     { "deny [opt ...]",                        "Deny option",
                     76:        CcpSetCommand, NULL, 2, (void *) SET_DENY },
                     77:     { "enable [opt ...]",              "Enable option",
                     78:        CcpSetCommand, NULL, 2, (void *) SET_ENABLE },
                     79:     { "disable [opt ...]",             "Disable option",
                     80:        CcpSetCommand, NULL, 2, (void *) SET_DISABLE },
                     81:     { "yes [opt ...]",                 "Enable and accept option",
                     82:        CcpSetCommand, NULL, 2, (void *) SET_YES },
                     83:     { "no [opt ...]",                  "Disable and deny option",
                     84:        CcpSetCommand, NULL, 2, (void *) SET_NO },
1.1.1.3 ! misho      85:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho      86:   };
                     87: 
                     88: /*
                     89:  * INTERNAL VARIABLES
                     90:  */
                     91: 
                     92:   /* These should be listed in order of preference */
                     93:   static const CompType                gCompTypes[] = {
                     94: #ifdef CCP_MPPC
                     95:     &gCompMppcInfo,
                     96: #endif
                     97: #ifdef CCP_DEFLATE
                     98:     &gCompDeflateInfo,
                     99: #endif
                    100: #ifdef CCP_PRED1
                    101:     &gCompPred1Info,
                    102: #endif
                    103:   };
                    104:   #define CCP_NUM_PROTOS       (sizeof(gCompTypes) / sizeof(*gCompTypes))
                    105: 
                    106:   /* Corresponding option list */
                    107:   static const struct confinfo *gConfList;
                    108: 
                    109:   /* FSM Initializer */
                    110:   static const struct fsmtype gCcpFsmType = {
                    111:     "CCP",
                    112:     PROTO_CCP,
                    113:     CCP_KNOWN_CODES,
                    114:     FALSE,
                    115:     LG_CCP, LG_CCP2,
                    116:     NULL,
                    117:     CcpLayerUp,
                    118:     CcpLayerDown,
                    119:     NULL,
                    120:     NULL,
                    121:     CcpBuildConfigReq,
                    122:     CcpDecodeConfig,
                    123:     CcpConfigure,
                    124:     CcpUnConfigure,
                    125:     NULL,
                    126:     NULL,
                    127:     NULL,
                    128:     NULL,
                    129:     CcpFailure,
                    130:     CcpRecvResetReq,
                    131:     CcpRecvResetAck,
1.1.1.3 ! misho     132:     NULL, NULL, NULL, NULL
1.1       misho     133:   };
                    134: 
                    135:   /* Names for different types of compression */
                    136:   static const struct ccpname {
                    137:     u_char     type;
                    138:     const char *name;
                    139:   } gCcpTypeNames[] = {
                    140:     { CCP_TY_OUI,              "OUI" },
                    141:     { CCP_TY_PRED1,            "PRED1" },
                    142:     { CCP_TY_PRED2,            "PRED2" },
                    143:     { CCP_TY_PUDDLE,           "PUDDLE" },
                    144:     { CCP_TY_HWPPC,            "HWPPC" },
                    145:     { CCP_TY_STAC,             "STAC" },
                    146:     { CCP_TY_MPPC,             "MPPC" },
                    147:     { CCP_TY_GAND,             "GAND" },
                    148:     { CCP_TY_V42BIS,           "V42BIS" },
                    149:     { CCP_TY_BSD,              "BSD" },
                    150:     { CCP_TY_LZS_DCP,          "LZS-DCP" },
1.1.1.3 ! misho     151:     { CCP_TY_MVRCA,            "MVRCA" },
1.1       misho     152:     { CCP_TY_DCE,              "DCE" },
                    153:     { CCP_TY_DEFLATE,          "DEFLATE" },
                    154:     { CCP_TY_V44,              "V.44/LZJH" },
                    155:     { 0,                       NULL },
                    156:   };
                    157: 
1.1.1.3 ! misho     158: int            gCcpCsock = -1;         /* Socket node control socket */
        !           159: int            gCcpDsock = -1;         /* Socket node data socket */
        !           160: static EventRef        gCcpCtrlEvent;
        !           161: static EventRef        gCcpDataEvent;
1.1       misho     162: 
                    163: int
                    164: CcpsInit(void)
                    165: {
                    166:     char       name[NG_NODESIZ];
                    167: 
                    168:     /* Create a netgraph socket node */
                    169:     snprintf(name, sizeof(name), "mpd%d-cso", gPid);
                    170:     if (NgMkSockNode(name, &gCcpCsock, &gCcpDsock) < 0) {
                    171:        Perror("CcpsInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
                    172:        return(-1);
                    173:     }
                    174:     (void) fcntl(gCcpCsock, F_SETFD, 1);
                    175:     (void) fcntl(gCcpDsock, F_SETFD, 1);
                    176: 
                    177:     /* Listen for happenings on our node */
                    178:     EventRegister(&gCcpCtrlEvent, EVENT_READ,
                    179:        gCcpCsock, EVENT_RECURRING, CcpNgCtrlEvent, NULL);
                    180:     EventRegister(&gCcpDataEvent, EVENT_READ,
                    181:        gCcpDsock, EVENT_RECURRING, CcpNgDataEvent, NULL);
                    182:        
                    183:     return (0);
                    184: }
                    185: 
                    186: void
                    187: CcpsShutdown(void)
                    188: {
                    189:     EventUnRegister(&gCcpCtrlEvent);
                    190:     close(gCcpCsock);
                    191:     gCcpCsock = -1;
                    192:     EventUnRegister(&gCcpDataEvent);
                    193:     close(gCcpDsock);
                    194:     gCcpDsock = -1;
                    195: }
                    196: 
                    197: /*
                    198:  * CcpInit()
                    199:  */
                    200: 
                    201: void
                    202: CcpInit(Bund b)
                    203: {
                    204:   CcpState     ccp = &b->ccp;
                    205: 
                    206:   /* Init CCP state for this bundle */
                    207:   memset(ccp, 0, sizeof(*ccp));
                    208:   FsmInit(&ccp->fsm, &gCcpFsmType, b);
                    209:   ccp->fsm.conf.maxfailure = CCP_MAXFAILURE;
                    210: 
                    211:   /* Construct options list if we haven't done so already */
                    212:   if (gConfList == NULL) {
                    213:     struct confinfo    *ci;
1.1.1.3 ! misho     214:     unsigned           k;
1.1       misho     215: 
                    216:     ci = Malloc(MB_COMP, (CCP_NUM_PROTOS + 1) * sizeof(*ci));
                    217:     for (k = 0; k < CCP_NUM_PROTOS; k++) {
                    218:       ci[k].option = k;
                    219:       ci[k].peered = TRUE;
                    220:       ci[k].name = gCompTypes[k]->name;
                    221:     }
                    222: 
                    223:     /* Terminate list */
                    224:     ci[k].name = NULL;
                    225:     gConfList = (const struct confinfo *) ci;
                    226:   }
                    227: }
                    228: 
                    229: /*
                    230:  * CcpInst()
                    231:  */
                    232: 
                    233: void
                    234: CcpInst(Bund b, Bund bt)
                    235: {
                    236:   CcpState     ccp = &b->ccp;
                    237: 
                    238:   /* Init CCP state for this bundle */
                    239:   memcpy(ccp, &bt->ccp, sizeof(*ccp));
                    240:   FsmInst(&ccp->fsm, &bt->ccp.fsm, b);
                    241: }
                    242: 
                    243: /*
                    244:  * CcpConfigure()
                    245:  */
                    246: 
                    247: static void
                    248: CcpConfigure(Fsm fp)
                    249: {
                    250:     Bund       b = (Bund)fp->arg;
                    251:     CcpState   const ccp = &b->ccp;
1.1.1.3 ! misho     252:     unsigned   k;
1.1       misho     253: 
                    254:     /* Reset state */
                    255:     ccp->self_reject = 0;
                    256:     ccp->peer_reject = 0;
                    257:     ccp->crypt_check = 0;
                    258:     ccp->xmit = NULL;
                    259:     ccp->recv = NULL;
                    260:     for (k = 0; k < CCP_NUM_PROTOS; k++) {
                    261:        CompType        const ct = gCompTypes[k];
                    262: 
                    263:        if (ct->Configure) {
                    264:            if ((*ct->Configure)(b)) {
                    265:                if (Enabled(&ccp->options, k)) {
                    266:                    Log(LG_CCP, ("[%s] CCP: Protocol %s disabled "
                    267:                        "as useless for this setup",
                    268:                        b->name, ct->name));
                    269:                }
                    270:                CCP_SELF_REJ(ccp, k);
                    271:            };
                    272:        }
                    273:     }
                    274: }
                    275: 
                    276: /*
                    277:  * CcpUnConfigure()
                    278:  */
                    279: 
                    280: static void
                    281: CcpUnConfigure(Fsm fp)
                    282: {
                    283:     Bund       b = (Bund)fp->arg;
                    284:   CcpState     const ccp = &b->ccp;
1.1.1.3 ! misho     285:   unsigned     k;
1.1       misho     286: 
                    287:   /* Reset state */
                    288:   ccp->self_reject = 0;
                    289:   ccp->peer_reject = 0;
                    290:   ccp->crypt_check = 0;
                    291:   ccp->xmit = NULL;
                    292:   ccp->recv = NULL;
                    293:   for (k = 0; k < CCP_NUM_PROTOS; k++) {
                    294:     CompType   const ct = gCompTypes[k];
                    295: 
                    296:     if (ct->UnConfigure)
                    297:       (*ct->UnConfigure)(b);
                    298:   }
                    299: }
                    300: 
                    301: /*
                    302:  * CcpNgCtrlEvent()
                    303:  *
                    304:  */
                    305: 
                    306: void
                    307: CcpNgCtrlEvent(int type, void *cookie)
                    308: {
                    309:     Bund               b = NULL;
                    310:     union {
                    311:         u_char         buf[2048];
                    312:         struct ng_mesg msg;
                    313:     }                  u;
                    314:     char               raddr[NG_PATHSIZ];
                    315:     int                        i, len;
                    316:     ng_ID_t            id;
                    317: 
1.1.1.3 ! misho     318:     (void)cookie;
        !           319:     (void)type;
        !           320: 
1.1       misho     321:     /* Read message */
                    322:     if ((len = NgRecvMsg(gCcpCsock, &u.msg, sizeof(u), raddr)) < 0) {
                    323:        Perror("CcpNgCtrlEvent: can't read message");
                    324:        return;
                    325:     }
                    326:     
                    327:     if (sscanf(raddr, "[%x]:", &id) != 1) {
                    328:        Log(LG_ERR, ("CcpNgCtrlEvent: can't decode sender id: '%s'",
                    329:            raddr));
                    330:        return;
                    331:     }
                    332:     
                    333:     for (i = 0; i < gNumBundles; i++) {
                    334:        if (gBundles[i] && !gBundles[i]->dead &&
                    335:                gBundles[i]->ccp.decomp_node_id == id) {
                    336:            b = gBundles[i];
                    337:            break;
                    338:        }
                    339:     }
                    340:     if (!b)
                    341:        return;
                    342: 
                    343:     /* Examine message */
                    344:     switch (u.msg.header.typecookie) {
                    345: 
                    346: #ifdef USE_NG_MPPC
                    347:        case NGM_MPPC_COOKIE:
                    348: #endif
                    349: #ifdef USE_NG_DEFLATE
                    350:        case NGM_DEFLATE_COOKIE:
                    351: #endif
                    352: #ifdef USE_NG_PRED1
                    353:        case NGM_PRED1_COOKIE:
                    354: #endif
                    355:            CcpRecvMsg(b, &u.msg, len);
                    356:         return;
                    357: 
                    358:        default:
                    359:            /* Unknown message */
                    360:            Log(LG_ERR, ("CcpNgCtrlEvent: rec'd unknown ctrl message, cookie=%d cmd=%d",
                    361:                u.msg.header.typecookie, u.msg.header.cmd));
                    362:            break;
                    363:     }
                    364: 
                    365: }
                    366: 
                    367: /*
                    368:  * CcpNgDataEvent()
                    369:  */
                    370: 
                    371: static void
                    372: CcpNgDataEvent(int type, void *cookie)
                    373: {
                    374:     Bund               b;
                    375:     struct sockaddr_ng naddr;
                    376:     socklen_t          nsize;
                    377:     Mbuf               bp;
                    378:     int                        num = 0;
                    379:     char                *bundname, *rest;
                    380:     int                 id;
                    381:                
1.1.1.3 ! misho     382:     (void)cookie;
        !           383:     (void)type;
        !           384: 
1.1       misho     385:     while (1) {
                    386:        /* Protect from bundle shutdown and DoS */
                    387:        if (num > 100)
                    388:            return;
                    389:     
                    390:        bp = mballoc(4096);
                    391: 
                    392:        /* Read data */
                    393:        nsize = sizeof(naddr);
                    394:        if ((bp->cnt = recvfrom(gCcpDsock, MBDATA(bp), MBSPACE(bp),
                    395:                MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
                    396:            mbfree(bp);
                    397:            if (errno == EAGAIN)
                    398:                return;
                    399:            Log(LG_BUND|LG_ERR, ("CcpNgDataEvent: socket read: %s", strerror(errno)));
                    400:            return;
                    401:        }
                    402:        num++;
                    403:     
                    404:        /* Debugging */
                    405:        LogDumpBp(LG_FRAME, bp,
1.1.1.2   misho     406:            "CcpNgDataEvent: rec'd %zu bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
1.1       misho     407: 
                    408:        bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
                    409:        if (bundname[0] != 'c' && bundname[0] != 'd') {
                    410:            Log(LG_ERR, ("CCP: Packet from unknown hook \"%s\"",
                    411:                bundname));
                    412:            mbfree(bp);
                    413:            continue;
                    414:        }
                    415:        bundname++;
                    416:        id = strtol(bundname, &rest, 10);
                    417:        if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
                    418:            Log(LG_ERR, ("CCP: Packet from unexisting bundle \"%s\"",
                    419:                bundname));
                    420:            mbfree(bp);
                    421:            continue;
                    422:        }
                    423:                
                    424:        b = gBundles[id];
                    425: 
                    426:        /* Packet requiring compression */
                    427:        if (bundname[0] == 'c') {
                    428:            bp = CcpDataOutput(b, bp);
                    429:        } else {
                    430:            /* Packet requiring decompression */
                    431:            bp = CcpDataInput(b, bp);
                    432:        }
                    433:        if (bp)
                    434:            NgFuncWriteFrame(gCcpDsock, naddr.sg_data, b->name, bp);
                    435:     }
                    436: }
                    437: 
                    438: /*
                    439:  * CcpRecvMsg()
                    440:  */
                    441: 
                    442: void
                    443: CcpRecvMsg(Bund b, struct ng_mesg *msg, int len)
                    444: {
                    445:   CcpState     const ccp = &b->ccp;
                    446:   Fsm          const fp = &ccp->fsm;
                    447: 
1.1.1.3 ! misho     448:   (void)len;
        !           449: 
1.1       misho     450:   switch (msg->header.typecookie) {
                    451: #ifdef USE_NG_MPPC
                    452:     case NGM_MPPC_COOKIE:
                    453:       switch (msg->header.cmd) {
                    454:        case NGM_MPPC_RESETREQ: {
                    455:            CcpSendResetReq(b);
                    456:            return;
                    457:          }
                    458:        default:
                    459:          break;
                    460:       }
                    461:       break;
                    462: #endif
                    463: #ifdef USE_NG_DEFLATE
                    464:     case NGM_DEFLATE_COOKIE:
                    465:       switch (msg->header.cmd) {
                    466:        case NGM_DEFLATE_RESETREQ: {
                    467:            CcpSendResetReq(b);
                    468:            return;
                    469:          }
                    470:        default:
                    471:          break;
                    472:       }
                    473:       break;
                    474: #endif
                    475: #ifdef USE_NG_PRED1
                    476:     case NGM_PRED1_COOKIE:
                    477:       switch (msg->header.cmd) {
                    478:        case NGM_PRED1_RESETREQ: {
                    479:            CcpSendResetReq(b);
                    480:            return;
                    481:          }
                    482:        default:
                    483:          break;
                    484:       }
                    485:       break;
                    486: #endif
                    487:     default:
                    488:       break;
                    489:   }
                    490: 
                    491:   /* Unknown! */
                    492:   Log(LG_ERR, ("[%s] %s: rec'd unknown netgraph message: cookie=%d, cmd=%d",
                    493:     Pref(fp), Fsm(fp), msg->header.typecookie, msg->header.cmd));
                    494: }
                    495: 
                    496: /*
                    497:  * CcpUp()
                    498:  */
                    499: 
                    500: void
                    501: CcpUp(Bund b)
                    502: {
                    503:   FsmUp(&b->ccp.fsm);
                    504: }
                    505: 
                    506: /*
                    507:  * CcpDown()
                    508:  */
                    509: 
                    510: void
                    511: CcpDown(Bund b)
                    512: {
                    513:   FsmDown(&b->ccp.fsm);
                    514: }
                    515: 
                    516: /*
                    517:  * CcpOpen()
                    518:  */
                    519: 
                    520: void
                    521: CcpOpen(Bund b)
                    522: {
                    523:   FsmOpen(&b->ccp.fsm);
                    524: }
                    525: 
                    526: /*
                    527:  * CcpClose()
                    528:  */
                    529: 
                    530: void
                    531: CcpClose(Bund b)
                    532: {
                    533:   FsmClose(&b->ccp.fsm);
                    534: }
                    535: 
                    536: /*
                    537:  * CcpOpenCmd()
                    538:  */
                    539: 
                    540: int
                    541: CcpOpenCmd(Context ctx)
                    542: {
                    543:     if (ctx->bund->tmpl)
                    544:        Error("impossible to open template");
                    545:     FsmOpen(&ctx->bund->ccp.fsm);
                    546:     return (0);
                    547: }
                    548: 
                    549: /*
                    550:  * CcpCloseCmd()
                    551:  */
                    552: 
                    553: int
                    554: CcpCloseCmd(Context ctx)
                    555: {
                    556:     if (ctx->bund->tmpl)
                    557:        Error("impossible to close template");
                    558:     FsmClose(&ctx->bund->ccp.fsm);
                    559:     return (0);
                    560: }
                    561: 
                    562: /*
                    563:  * CcpFailure()
                    564:  *
                    565:  * If we fail, just shut down and stop trying. However, if encryption
                    566:  * was required and MPPE encryption was enabled, then die here as well.
                    567:  */
                    568: 
                    569: static void
                    570: CcpFailure(Fsm fp, enum fsmfail reason)
                    571: {
                    572:     Bund       b = (Bund)fp->arg;
1.1.1.3 ! misho     573: 
        !           574:     (void)reason;
1.1       misho     575:     CcpCheckEncryption(b);
                    576: }
                    577: 
                    578: /*
                    579:  * CcpStat()
                    580:  */
                    581: 
                    582: int
1.1.1.3 ! misho     583: CcpStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     584: {
                    585:   CcpState     const ccp = &ctx->bund->ccp;
                    586:   char         buf[64];
                    587: 
                    588:   Printf("[%s] %s [%s]\r\n", Pref(&ccp->fsm), Fsm(&ccp->fsm), FsmStateName(ccp->fsm.state));
                    589:   Printf("Enabled protocols:\r\n");
                    590:   OptStat(ctx, &ccp->options, gConfList);
                    591: 
                    592: #ifdef CCP_MPPC
                    593:   MppcStat(ctx, ac, av, arg);
                    594: #endif
                    595:   Printf("Outgoing compression:\r\n");
                    596:   Printf("\tProto\t: %s (%s)\r\n", !ccp->xmit ? "none" : ccp->xmit->name,
                    597:     (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(ctx->bund, COMP_DIR_XMIT, buf, sizeof(buf)) : "");
                    598:   if (ccp->xmit && ccp->xmit->Stat)
                    599:     ccp->xmit->Stat(ctx, COMP_DIR_XMIT);
                    600:   Printf("\tResets\t: %d\r\n", ccp->xmit_resets);
                    601: 
                    602:   Printf("Incoming decompression:\r\n");
                    603:   Printf("\tProto\t: %s (%s)\r\n", !ccp->recv ? "none" : ccp->recv->name,
                    604:     (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(ctx->bund, COMP_DIR_RECV, buf, sizeof(buf)) : "");
                    605:   if (ccp->recv && ccp->recv->Stat)
                    606:     ccp->recv->Stat(ctx, COMP_DIR_RECV);
                    607:   Printf("\tResets\t: %d\r\n", ccp->recv_resets);
                    608: 
                    609:   return(0);
                    610: }
                    611: 
                    612: /*
                    613:  * CcpSendResetReq()
                    614:  */
                    615: 
                    616: void
                    617: CcpSendResetReq(Bund b)
                    618: {
                    619:   CcpState     const ccp = &b->ccp;
                    620:   CompType     const ct = ccp->recv;
                    621:   Fsm          const fp = &ccp->fsm;
                    622:   Mbuf         bp = NULL;
                    623: 
                    624:   if (ct == NULL) {
                    625:     Log(LG_ERR, ("[%s] %s: CcpSendResetReq() call from undefined decompressor!", 
                    626:        Pref(fp), Fsm(fp)));
                    627:     return;
                    628:   }
                    629:   
                    630:   ccp->recv_resets++;
                    631:   if (ct->SendResetReq)
                    632:     bp = (*ct->SendResetReq)(b);
                    633:   Log(LG_CCP, ("[%s] %s: SendResetReq #%d link %d (%s)", 
                    634:     Pref(fp), Fsm(fp), fp->reqid, 0, FsmStateName(fp->state)));
                    635:   FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
                    636: }
                    637: 
                    638: /*
                    639:  * CcpRecvResetReq()
                    640:  */
                    641: 
                    642: static void
                    643: CcpRecvResetReq(Fsm fp, int id, Mbuf bp)
                    644: {
                    645:     Bund       b = (Bund)fp->arg;
                    646:   CcpState     const ccp = &b->ccp;
                    647:   CompType     const ct = ccp->xmit;
                    648:   int          noAck = 0;
                    649: 
                    650:   ccp->xmit_resets++;
                    651:   bp = (ct && ct->RecvResetReq) ? (*ct->RecvResetReq)(b, id, bp, &noAck) : NULL;
                    652:   if (!noAck) {
                    653:     Log(LG_CCP, ("[%s] %s: SendResetAck #%d link %d (%s)",
                    654:        Pref(fp), Fsm(fp), id, 0, FsmStateName(fp->state)));
                    655:     FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
                    656:   }
                    657: }
                    658: 
                    659: /*
                    660:  * CcpRecvResetAck()
                    661:  */
                    662: 
                    663: static void
                    664: CcpRecvResetAck(Fsm fp, int id, Mbuf bp)
                    665: {
                    666:     Bund       b = (Bund)fp->arg;
                    667:   CcpState     const ccp = &b->ccp;
                    668:   CompType     const ct = ccp->recv;
                    669: 
                    670:   if (ct && ct->RecvResetAck)
                    671:     (*ct->RecvResetAck)(b, id, bp);
                    672: }
                    673: 
                    674: /*
                    675:  * CcpInput()
                    676:  */
                    677: 
                    678: void
                    679: CcpInput(Bund b, Mbuf bp)
                    680: {
                    681:   FsmInput(&b->ccp.fsm, bp);
                    682: }
                    683: 
                    684: /*
                    685:  * CcpDataOutput()
                    686:  *
                    687:  * Compress a frame. Consumes the original packet.
                    688:  */
                    689: 
                    690: Mbuf
                    691: CcpDataOutput(Bund b, Mbuf plain)
                    692: {
                    693:   CcpState     const ccp = &b->ccp;
                    694:   Mbuf         comp;
                    695: 
                    696:   LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    697: 
                    698: /* Compress packet */
                    699: 
                    700:   if ((!ccp->xmit) || (!ccp->xmit->Compress))
                    701:   {
                    702:     Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                    703:     mbfree(plain);
                    704:     return(NULL);
                    705:   }
                    706:   comp = (*ccp->xmit->Compress)(b, plain);
                    707:   LogDumpBp(LG_FRAME, comp, "[%s] %s: xmit comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    708: 
                    709:   return(comp);
                    710: }
                    711: 
                    712: /*
                    713:  * CcpDataInput()
                    714:  *
                    715:  * Decompress incoming packet. If packet got garbled, return NULL.
                    716:  * In any case, we consume the packet passed to us.
                    717:  */
                    718: 
                    719: Mbuf
                    720: CcpDataInput(Bund b, Mbuf comp)
                    721: {
                    722:   CcpState     const ccp = &b->ccp;
                    723:   Mbuf         plain;
                    724: 
                    725:   LogDumpBp(LG_FRAME, comp, "[%s] %s: recv comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    726: 
                    727: /* Decompress packet */
                    728: 
                    729:   if ((!ccp->recv) || (!ccp->recv->Decompress))
                    730:   {
                    731:     Log(LG_ERR, ("[%s] %s: no compression for recv", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                    732:     mbfree(comp);
                    733:     return(NULL);
                    734:   }
                    735: 
                    736:   plain = (*ccp->recv->Decompress)(b, comp);
                    737: 
                    738: /* Encrypted ok? */
                    739: 
                    740:   if (plain == NULL)
                    741:   {
                    742:     Log(LG_CCP, ("[%s] %s: decompression failed", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                    743:     return(NULL);
                    744:   }
                    745:   LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    746: 
                    747:   return(plain);
                    748: }
                    749: 
                    750: /*
                    751:  * CcpBuildConfigReq()
                    752:  */
                    753: 
                    754: static u_char *
                    755: CcpBuildConfigReq(Fsm fp, u_char *cp)
                    756: {
                    757:     Bund       b = (Bund)fp->arg;
                    758:     CcpState   const ccp = &b->ccp;
1.1.1.3 ! misho     759:     unsigned   type;
1.1       misho     760:     int                ok;
                    761: 
                    762:     /* Put in all options that peer hasn't rejected in preferred order */
                    763:     ccp->xmit = NULL;
                    764:     for (type = 0; type < CCP_NUM_PROTOS; type++) {
                    765:        CompType        const ct = gCompTypes[type];
                    766: 
                    767:        if (Enabled(&ccp->options, type) && !CCP_PEER_REJECTED(ccp, type)) {
                    768:            cp = (*ct->BuildConfigReq)(b, cp, &ok);
                    769:            if (ok && (!ccp->xmit))
                    770:                ccp->xmit = ct;
                    771:        }
                    772:     }
                    773:     return(cp);
                    774: }
                    775: 
                    776: /*
                    777:  * CcpLayerUp()
                    778:  */
                    779: 
                    780: static void
                    781: CcpLayerUp(Fsm fp)
                    782: {
                    783:     Bund       b = (Bund)fp->arg;
                    784:   CcpState     const ccp = &b->ccp;
                    785:   struct ngm_connect    cn;
                    786:   char         buf[64];
                    787: 
                    788:   /* If nothing was negotiated in either direction, close CCP */
                    789:   if ((!ccp->recv || !(*ccp->recv->Negotiated)(b, COMP_DIR_RECV))
                    790:       && (!ccp->xmit || !(*ccp->xmit->Negotiated)(b, COMP_DIR_XMIT))) {
                    791:     Log(LG_CCP, ("[%s] %s: No compression negotiated", Pref(fp), Fsm(fp)));
                    792:     FsmFailure(fp, FAIL_NEGOT_FAILURE);
                    793:     return;
                    794:   }
                    795: 
                    796:   /* Check for required encryption */
                    797:   if (CcpCheckEncryption(b) < 0) {
                    798:     return;
                    799:   }
                    800: 
                    801:   /* Initialize each direction */
                    802:   if (ccp->xmit != NULL && ccp->xmit->Init != NULL
                    803:       && (*ccp->xmit->Init)(b, COMP_DIR_XMIT) < 0) {
                    804:     Log(LG_CCP, ("[%s] %s: compression init failed", Pref(fp), Fsm(fp)));
                    805:     FsmFailure(fp, FAIL_NEGOT_FAILURE);                /* XXX */
                    806:     return;
                    807:   }
                    808:   if (ccp->recv != NULL && ccp->recv->Init != NULL
                    809:       && (*ccp->recv->Init)(b, COMP_DIR_RECV) < 0) {
                    810:     Log(LG_CCP, ("[%s] %s: decompression init failed", Pref(fp), Fsm(fp)));
                    811:     FsmFailure(fp, FAIL_NEGOT_FAILURE);                /* XXX */
                    812:     return;
                    813:   }
                    814: 
                    815:   if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
                    816:     /* Connect a hook from the ppp node to our socket node */
                    817:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
                    818:     snprintf(cn.ourhook, sizeof(cn.ourhook), "c%d", b->id);
                    819:     strcpy(cn.peerhook, NG_PPP_HOOK_COMPRESS);
                    820:     if (NgSendMsg(gCcpCsock, ".:",
                    821:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    822:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    823:            b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    824:     }
                    825:   }
                    826: 
                    827:   if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
                    828:     /* Connect a hook from the ppp node to our socket node */
                    829:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
                    830:     snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
                    831:     strcpy(cn.peerhook, NG_PPP_HOOK_DECOMPRESS);
                    832:     if (NgSendMsg(gCcpCsock, ".:",
                    833:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    834:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    835:            b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    836:     }
                    837:   }
                    838: 
                    839:   /* Report what we're doing */
                    840:   Log(LG_CCP, ("[%s] CCP: Compress using: %s (%s)", b->name, !ccp->xmit ? "none" : ccp->xmit->name,
                    841:     (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(b, COMP_DIR_XMIT, buf, sizeof(buf)) : ""));
                    842:   Log(LG_CCP, ("[%s] CCP: Decompress using: %s (%s)", b->name, !ccp->recv ? "none" : ccp->recv->name,
                    843:     (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(b, COMP_DIR_RECV, buf, sizeof(buf)) : ""));
                    844: 
                    845:   /* Update PPP node config */
                    846:   b->pppConfig.bund.enableCompression = (ccp->xmit != NULL)?ccp->xmit->mode:0;
                    847:   b->pppConfig.bund.enableDecompression = (ccp->recv != NULL)?ccp->recv->mode:0;
                    848:   NgFuncSetConfig(b);
                    849: 
                    850:   /* Update interface MTU */
                    851:   BundUpdateParams(b);
                    852: }
                    853: 
                    854: /*
                    855:  * CcpLayerDown()
                    856:  */
                    857: 
                    858: static void
                    859: CcpLayerDown(Fsm fp)
                    860: {
                    861:     Bund       b = (Bund)fp->arg;
                    862:   CcpState     const ccp = &b->ccp;
                    863: 
                    864:   /* Update PPP node config */
                    865:   b->pppConfig.bund.enableCompression = 0;
                    866:   b->pppConfig.bund.enableDecompression = 0;
                    867:   NgFuncSetConfig(b);
                    868: 
                    869:   /* Update interface MTU */
                    870:   BundUpdateParams(b);
                    871:   
                    872:   if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
                    873:     char       hook[NG_HOOKSIZ];
                    874:     /* Disconnect hook. */
                    875:     snprintf(hook, sizeof(hook), "c%d", b->id);
                    876:     NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
                    877:   }
                    878:   
                    879:   if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
                    880:     char       hook[NG_HOOKSIZ];
                    881:     /* Disconnect hook. */
                    882:     snprintf(hook, sizeof(hook), "d%d", b->id);
                    883:     NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
                    884:   }
                    885:   if (ccp->recv && ccp->recv->Cleanup)
                    886:     (*ccp->recv->Cleanup)(b, COMP_DIR_RECV);
                    887:   if (ccp->xmit && ccp->xmit->Cleanup)
                    888:     (*ccp->xmit->Cleanup)(b, COMP_DIR_XMIT);
                    889: 
                    890:   ccp->xmit_resets = 0;
                    891:   ccp->recv_resets = 0;
                    892: }
                    893: 
                    894: /*
                    895:  * CcpDecodeConfig()
                    896:  */
                    897: 
                    898: static void
                    899: CcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
                    900: {
                    901:     Bund       b = (Bund)fp->arg;
                    902:   CcpState     const ccp = &b->ccp;
                    903:   u_int                ackSizeSave, rejSizeSave;
                    904:   int          k, rej;
                    905: 
                    906:   /* Forget our previous choice on new request */
                    907:   if (mode == MODE_REQ)
                    908:     ccp->recv = NULL;
                    909: 
                    910:   /* Decode each config option */
                    911:   for (k = 0; k < num; k++) {
                    912:     FsmOption  const opt = &list[k];
                    913:     int                index;
                    914:     CompType   ct;
                    915:     char       buf[32];
                    916: 
                    917:     Log(LG_CCP, ("[%s]   %s", b->name, CcpTypeName(opt->type, buf, sizeof(buf))));
                    918:     if ((ct = CcpFindComp(opt->type, &index)) == NULL) {
                    919:       if (mode == MODE_REQ) {
                    920:        Log(LG_CCP, ("[%s]     Not supported", b->name));
                    921:        FsmRej(fp, opt);
                    922:       }
                    923:       continue;
                    924:     }
                    925:     switch (mode) {
                    926:       case MODE_REQ:
                    927:        ackSizeSave = gAckSize;
                    928:        rejSizeSave = gRejSize;
                    929:        rej = (!Acceptable(&ccp->options, index)
                    930:          || CCP_SELF_REJECTED(ccp, index)
                    931:          || (ccp->recv && ccp->recv != ct));
                    932:        if (rej) {
                    933:          (*ct->DecodeConfig)(fp, opt, MODE_NOP);
                    934:          FsmRej(fp, opt);
                    935:          break;
                    936:        }
                    937:        (*ct->DecodeConfig)(fp, opt, mode);
                    938:        if (gRejSize != rejSizeSave) {          /* we rejected it */
                    939:          CCP_SELF_REJ(ccp, index);
                    940:          break;
                    941:        }
                    942:        if (gAckSize != ackSizeSave)            /* we accepted it */
                    943:          ccp->recv = ct;
                    944:        break;
                    945: 
                    946:       case MODE_REJ:
                    947:        (*ct->DecodeConfig)(fp, opt, mode);
                    948:        CCP_PEER_REJ(ccp, index);
                    949:        break;
                    950: 
                    951:       case MODE_NAK:
                    952:       case MODE_NOP:
                    953:        (*ct->DecodeConfig)(fp, opt, mode);
                    954:        break;
                    955:     }
                    956:   }
                    957: }
                    958: 
                    959: /*
                    960:  * CcpSubtractBloat()
                    961:  *
                    962:  * Given that "size" is our MTU, return the maximum length frame
                    963:  * we can compress without the result being longer than "size".
                    964:  */
                    965: 
                    966: int
                    967: CcpSubtractBloat(Bund b, int size)
                    968: {
                    969:   CcpState     const ccp = &b->ccp;
                    970: 
                    971:   /* Account for transmit compression overhead */
                    972:   if (OPEN_STATE(ccp->fsm.state) && ccp->xmit && ccp->xmit->SubtractBloat)
                    973:     size = (*ccp->xmit->SubtractBloat)(b, size);
                    974: 
                    975:   /* Account for CCP's protocol number overhead */
                    976:   if (OPEN_STATE(ccp->fsm.state))
                    977:     size -= CCP_OVERHEAD;
                    978: 
                    979:   /* Done */
                    980:   return(size);
                    981: }
                    982: 
                    983: /*
                    984:  * CcpCheckEncryption()
                    985:  *
                    986:  * Because MPPE is negotiated as an option to MPPC compression,
                    987:  * we have to check for encryption required when CCP comes up.
                    988:  */
                    989: 
                    990: static int
                    991: CcpCheckEncryption(Bund b)
                    992: {
                    993: #if 0
                    994:   CcpState     const ccp = &b->ccp;
                    995: 
                    996:   /* Already checked? */
                    997:   if (ccp->crypt_check)
                    998:     return(0);
                    999:   ccp->crypt_check = 1;
                   1000: 
                   1001:   /* Is encryption required? */
                   1002:   if (Enabled(&ccp->options, gMppePolicy)) {
                   1003:     if (b->params.msoft.policy != MPPE_POLICY_REQUIRED) 
                   1004:       return(0);
                   1005:   } else {
                   1006:     if (!Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD))
                   1007:       return(0);
                   1008:   }
                   1009: 
                   1010:   /* Was MPPE encryption enabled? If not, ignore requirement */
                   1011:   if (!Enabled(&ccp->options, gMppe40)
                   1012:       && !Enabled(&ccp->options, gMppe56)
                   1013:       && !Enabled(&ccp->options, gMppe128)
                   1014:       && !Enabled(&ccp->options, gMppePolicy))
                   1015:     return(0);
                   1016: 
                   1017:   /* Make sure MPPE was negotiated in both directions */
                   1018:   if (!OPEN_STATE(ccp->fsm.state)
                   1019:       || !ccp->xmit || ccp->xmit->type != CCP_TY_MPPC
                   1020:       || !ccp->recv || ccp->recv->type != CCP_TY_MPPC
                   1021: #ifdef CCP_MPPC
                   1022:       || !(ccp->mppc.recv_bits & MPPE_BITS)
                   1023:       || !(ccp->mppc.xmit_bits & MPPE_BITS)
                   1024: #endif
                   1025:       )
                   1026:     goto fail;
                   1027: 
                   1028:   /* Looks OK */
                   1029:   return(0);
                   1030: 
                   1031: fail:
                   1032:   Log(LG_ERR, ("[%s] %s: encryption required, but MPPE was not"
                   1033:     " negotiated in both directions", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                   1034:   FsmFailure(&ccp->fsm, FAIL_CANT_ENCRYPT);
                   1035:   FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
                   1036:   FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
                   1037:   return(-1);
1.1.1.3 ! misho    1038: #else
        !          1039:   (void)b;
1.1       misho    1040: #endif
                   1041:     return (0);
                   1042: }
                   1043: 
                   1044: /*
                   1045:  * CcpSetCommand()
                   1046:  */
                   1047: 
                   1048: static int
1.1.1.3 ! misho    1049: CcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho    1050: {
                   1051:   CcpState     const ccp = &ctx->bund->ccp;
                   1052: 
                   1053:   if (ac == 0)
                   1054:     return(-1);
                   1055:   switch ((intptr_t)arg) {
                   1056:     case SET_ACCEPT:
                   1057:       AcceptCommand(ac, av, &ccp->options, gConfList);
                   1058:       break;
                   1059: 
                   1060:     case SET_DENY:
                   1061:       DenyCommand(ac, av, &ccp->options, gConfList);
                   1062:       break;
                   1063: 
                   1064:     case SET_ENABLE:
                   1065:       EnableCommand(ac, av, &ccp->options, gConfList);
                   1066:       break;
                   1067: 
                   1068:     case SET_DISABLE:
                   1069:       DisableCommand(ac, av, &ccp->options, gConfList);
                   1070:       break;
                   1071: 
                   1072:     case SET_YES:
                   1073:       YesCommand(ac, av, &ccp->options, gConfList);
                   1074:       break;
                   1075: 
                   1076:     case SET_NO:
                   1077:       NoCommand(ac, av, &ccp->options, gConfList);
                   1078:       break;
                   1079: 
                   1080:     default:
                   1081:       assert(0);
                   1082:   }
                   1083:   return(0);
                   1084: }
                   1085: 
                   1086: /*
                   1087:  * CcpFindComp()
                   1088:  */
                   1089: 
                   1090: static CompType
                   1091: CcpFindComp(int type, int *indexp)
                   1092: {
1.1.1.3 ! misho    1093:   unsigned k;
1.1       misho    1094: 
                   1095:   for (k = 0; k < CCP_NUM_PROTOS; k++) {
                   1096:     if (gCompTypes[k]->type == type) {
                   1097:       if (indexp)
                   1098:        *indexp = k;
                   1099:       return(gCompTypes[k]);
                   1100:     }
                   1101:   }
                   1102:   return(NULL);
                   1103: }
                   1104: 
                   1105: /*
                   1106:  * CcpTypeName()
                   1107:  */
                   1108: 
                   1109: static const char *
                   1110: CcpTypeName(int type, char *buf, size_t len)
                   1111: {
                   1112:   const struct ccpname *p;
                   1113: 
                   1114:   for (p = gCcpTypeNames; p->name; p++) {
                   1115:     if (p->type == type) {
                   1116:        strlcpy(buf, p->name, len);
                   1117:         return (buf);
                   1118:     }
                   1119:   }
                   1120:   snprintf(buf, sizeof(buf), "UNKNOWN[%d]", type);
                   1121:   return(buf);
                   1122: }
                   1123: 

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