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

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);
                     61:   static int           CcpSetCommand(Context ctx, int ac, char *av[], void *arg);
                     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 },
                     85:     { NULL },
                     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,
                    132:     NULL,
                    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" },
                    151:     { CCP_TY_DEFLATE24,                "DEFLATE24" },
                    152:     { CCP_TY_DCE,              "DCE" },
                    153:     { CCP_TY_DEFLATE,          "DEFLATE" },
                    154:     { CCP_TY_V44,              "V.44/LZJH" },
                    155:     { 0,                       NULL },
                    156:   };
                    157: 
                    158:     int                gCcpCsock = -1;         /* Socket node control socket */
                    159:     int                gCcpDsock = -1;         /* Socket node data socket */
                    160:     EventRef   gCcpCtrlEvent;
                    161:     EventRef   gCcpDataEvent;
                    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;
                    214:     int                        k;
                    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;
                    252:     int                k;
                    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;
                    285:   int          k;
                    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: 
                    318:     /* Read message */
                    319:     if ((len = NgRecvMsg(gCcpCsock, &u.msg, sizeof(u), raddr)) < 0) {
                    320:        Perror("CcpNgCtrlEvent: can't read message");
                    321:        return;
                    322:     }
                    323:     
                    324:     if (sscanf(raddr, "[%x]:", &id) != 1) {
                    325:        Log(LG_ERR, ("CcpNgCtrlEvent: can't decode sender id: '%s'",
                    326:            raddr));
                    327:        return;
                    328:     }
                    329:     
                    330:     for (i = 0; i < gNumBundles; i++) {
                    331:        if (gBundles[i] && !gBundles[i]->dead &&
                    332:                gBundles[i]->ccp.decomp_node_id == id) {
                    333:            b = gBundles[i];
                    334:            break;
                    335:        }
                    336:     }
                    337:     if (!b)
                    338:        return;
                    339: 
                    340:     /* Examine message */
                    341:     switch (u.msg.header.typecookie) {
                    342: 
                    343: #ifdef USE_NG_MPPC
                    344:        case NGM_MPPC_COOKIE:
                    345: #endif
                    346: #ifdef USE_NG_DEFLATE
                    347:        case NGM_DEFLATE_COOKIE:
                    348: #endif
                    349: #ifdef USE_NG_PRED1
                    350:        case NGM_PRED1_COOKIE:
                    351: #endif
                    352:            CcpRecvMsg(b, &u.msg, len);
                    353:         return;
                    354: 
                    355:        default:
                    356:            /* Unknown message */
                    357:            Log(LG_ERR, ("CcpNgCtrlEvent: rec'd unknown ctrl message, cookie=%d cmd=%d",
                    358:                u.msg.header.typecookie, u.msg.header.cmd));
                    359:            break;
                    360:     }
                    361: 
                    362: }
                    363: 
                    364: /*
                    365:  * CcpNgDataEvent()
                    366:  */
                    367: 
                    368: static void
                    369: CcpNgDataEvent(int type, void *cookie)
                    370: {
                    371:     Bund               b;
                    372:     struct sockaddr_ng naddr;
                    373:     socklen_t          nsize;
                    374:     Mbuf               bp;
                    375:     int                        num = 0;
                    376:     char                *bundname, *rest;
                    377:     int                 id;
                    378:                
                    379:     while (1) {
                    380:        /* Protect from bundle shutdown and DoS */
                    381:        if (num > 100)
                    382:            return;
                    383:     
                    384:        bp = mballoc(4096);
                    385: 
                    386:        /* Read data */
                    387:        nsize = sizeof(naddr);
                    388:        if ((bp->cnt = recvfrom(gCcpDsock, MBDATA(bp), MBSPACE(bp),
                    389:                MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
                    390:            mbfree(bp);
                    391:            if (errno == EAGAIN)
                    392:                return;
                    393:            Log(LG_BUND|LG_ERR, ("CcpNgDataEvent: socket read: %s", strerror(errno)));
                    394:            return;
                    395:        }
                    396:        num++;
                    397:     
                    398:        /* Debugging */
                    399:        LogDumpBp(LG_FRAME, bp,
                    400:            "CcpNgDataEvent: rec'd %d bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
                    401: 
                    402:        bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
                    403:        if (bundname[0] != 'c' && bundname[0] != 'd') {
                    404:            Log(LG_ERR, ("CCP: Packet from unknown hook \"%s\"",
                    405:                bundname));
                    406:            mbfree(bp);
                    407:            continue;
                    408:        }
                    409:        bundname++;
                    410:        id = strtol(bundname, &rest, 10);
                    411:        if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
                    412:            Log(LG_ERR, ("CCP: Packet from unexisting bundle \"%s\"",
                    413:                bundname));
                    414:            mbfree(bp);
                    415:            continue;
                    416:        }
                    417:                
                    418:        b = gBundles[id];
                    419: 
                    420:        /* Packet requiring compression */
                    421:        if (bundname[0] == 'c') {
                    422:            bp = CcpDataOutput(b, bp);
                    423:        } else {
                    424:            /* Packet requiring decompression */
                    425:            bp = CcpDataInput(b, bp);
                    426:        }
                    427:        if (bp)
                    428:            NgFuncWriteFrame(gCcpDsock, naddr.sg_data, b->name, bp);
                    429:     }
                    430: }
                    431: 
                    432: /*
                    433:  * CcpRecvMsg()
                    434:  */
                    435: 
                    436: void
                    437: CcpRecvMsg(Bund b, struct ng_mesg *msg, int len)
                    438: {
                    439:   CcpState     const ccp = &b->ccp;
                    440:   Fsm          const fp = &ccp->fsm;
                    441: 
                    442:   switch (msg->header.typecookie) {
                    443: #ifdef USE_NG_MPPC
                    444:     case NGM_MPPC_COOKIE:
                    445:       switch (msg->header.cmd) {
                    446:        case NGM_MPPC_RESETREQ: {
                    447:            CcpSendResetReq(b);
                    448:            return;
                    449:          }
                    450:        default:
                    451:          break;
                    452:       }
                    453:       break;
                    454: #endif
                    455: #ifdef USE_NG_DEFLATE
                    456:     case NGM_DEFLATE_COOKIE:
                    457:       switch (msg->header.cmd) {
                    458:        case NGM_DEFLATE_RESETREQ: {
                    459:            CcpSendResetReq(b);
                    460:            return;
                    461:          }
                    462:        default:
                    463:          break;
                    464:       }
                    465:       break;
                    466: #endif
                    467: #ifdef USE_NG_PRED1
                    468:     case NGM_PRED1_COOKIE:
                    469:       switch (msg->header.cmd) {
                    470:        case NGM_PRED1_RESETREQ: {
                    471:            CcpSendResetReq(b);
                    472:            return;
                    473:          }
                    474:        default:
                    475:          break;
                    476:       }
                    477:       break;
                    478: #endif
                    479:     default:
                    480:       break;
                    481:   }
                    482: 
                    483:   /* Unknown! */
                    484:   Log(LG_ERR, ("[%s] %s: rec'd unknown netgraph message: cookie=%d, cmd=%d",
                    485:     Pref(fp), Fsm(fp), msg->header.typecookie, msg->header.cmd));
                    486: }
                    487: 
                    488: /*
                    489:  * CcpUp()
                    490:  */
                    491: 
                    492: void
                    493: CcpUp(Bund b)
                    494: {
                    495:   FsmUp(&b->ccp.fsm);
                    496: }
                    497: 
                    498: /*
                    499:  * CcpDown()
                    500:  */
                    501: 
                    502: void
                    503: CcpDown(Bund b)
                    504: {
                    505:   FsmDown(&b->ccp.fsm);
                    506: }
                    507: 
                    508: /*
                    509:  * CcpOpen()
                    510:  */
                    511: 
                    512: void
                    513: CcpOpen(Bund b)
                    514: {
                    515:   FsmOpen(&b->ccp.fsm);
                    516: }
                    517: 
                    518: /*
                    519:  * CcpClose()
                    520:  */
                    521: 
                    522: void
                    523: CcpClose(Bund b)
                    524: {
                    525:   FsmClose(&b->ccp.fsm);
                    526: }
                    527: 
                    528: /*
                    529:  * CcpOpenCmd()
                    530:  */
                    531: 
                    532: int
                    533: CcpOpenCmd(Context ctx)
                    534: {
                    535:     if (ctx->bund->tmpl)
                    536:        Error("impossible to open template");
                    537:     FsmOpen(&ctx->bund->ccp.fsm);
                    538:     return (0);
                    539: }
                    540: 
                    541: /*
                    542:  * CcpCloseCmd()
                    543:  */
                    544: 
                    545: int
                    546: CcpCloseCmd(Context ctx)
                    547: {
                    548:     if (ctx->bund->tmpl)
                    549:        Error("impossible to close template");
                    550:     FsmClose(&ctx->bund->ccp.fsm);
                    551:     return (0);
                    552: }
                    553: 
                    554: /*
                    555:  * CcpFailure()
                    556:  *
                    557:  * If we fail, just shut down and stop trying. However, if encryption
                    558:  * was required and MPPE encryption was enabled, then die here as well.
                    559:  */
                    560: 
                    561: static void
                    562: CcpFailure(Fsm fp, enum fsmfail reason)
                    563: {
                    564:     Bund       b = (Bund)fp->arg;
                    565:     CcpCheckEncryption(b);
                    566: }
                    567: 
                    568: /*
                    569:  * CcpStat()
                    570:  */
                    571: 
                    572: int
                    573: CcpStat(Context ctx, int ac, char *av[], void *arg)
                    574: {
                    575:   CcpState     const ccp = &ctx->bund->ccp;
                    576:   char         buf[64];
                    577: 
                    578:   Printf("[%s] %s [%s]\r\n", Pref(&ccp->fsm), Fsm(&ccp->fsm), FsmStateName(ccp->fsm.state));
                    579:   Printf("Enabled protocols:\r\n");
                    580:   OptStat(ctx, &ccp->options, gConfList);
                    581: 
                    582: #ifdef CCP_MPPC
                    583:   MppcStat(ctx, ac, av, arg);
                    584: #endif
                    585:   Printf("Outgoing compression:\r\n");
                    586:   Printf("\tProto\t: %s (%s)\r\n", !ccp->xmit ? "none" : ccp->xmit->name,
                    587:     (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(ctx->bund, COMP_DIR_XMIT, buf, sizeof(buf)) : "");
                    588:   if (ccp->xmit && ccp->xmit->Stat)
                    589:     ccp->xmit->Stat(ctx, COMP_DIR_XMIT);
                    590:   Printf("\tResets\t: %d\r\n", ccp->xmit_resets);
                    591: 
                    592:   Printf("Incoming decompression:\r\n");
                    593:   Printf("\tProto\t: %s (%s)\r\n", !ccp->recv ? "none" : ccp->recv->name,
                    594:     (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(ctx->bund, COMP_DIR_RECV, buf, sizeof(buf)) : "");
                    595:   if (ccp->recv && ccp->recv->Stat)
                    596:     ccp->recv->Stat(ctx, COMP_DIR_RECV);
                    597:   Printf("\tResets\t: %d\r\n", ccp->recv_resets);
                    598: 
                    599:   return(0);
                    600: }
                    601: 
                    602: /*
                    603:  * CcpSendResetReq()
                    604:  */
                    605: 
                    606: void
                    607: CcpSendResetReq(Bund b)
                    608: {
                    609:   CcpState     const ccp = &b->ccp;
                    610:   CompType     const ct = ccp->recv;
                    611:   Fsm          const fp = &ccp->fsm;
                    612:   Mbuf         bp = NULL;
                    613: 
                    614:   if (ct == NULL) {
                    615:     Log(LG_ERR, ("[%s] %s: CcpSendResetReq() call from undefined decompressor!", 
                    616:        Pref(fp), Fsm(fp)));
                    617:     return;
                    618:   }
                    619:   
                    620:   ccp->recv_resets++;
                    621:   if (ct->SendResetReq)
                    622:     bp = (*ct->SendResetReq)(b);
                    623:   Log(LG_CCP, ("[%s] %s: SendResetReq #%d link %d (%s)", 
                    624:     Pref(fp), Fsm(fp), fp->reqid, 0, FsmStateName(fp->state)));
                    625:   FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
                    626: }
                    627: 
                    628: /*
                    629:  * CcpRecvResetReq()
                    630:  */
                    631: 
                    632: static void
                    633: CcpRecvResetReq(Fsm fp, int id, Mbuf bp)
                    634: {
                    635:     Bund       b = (Bund)fp->arg;
                    636:   CcpState     const ccp = &b->ccp;
                    637:   CompType     const ct = ccp->xmit;
                    638:   int          noAck = 0;
                    639: 
                    640:   ccp->xmit_resets++;
                    641:   bp = (ct && ct->RecvResetReq) ? (*ct->RecvResetReq)(b, id, bp, &noAck) : NULL;
                    642:   if (!noAck) {
                    643:     Log(LG_CCP, ("[%s] %s: SendResetAck #%d link %d (%s)",
                    644:        Pref(fp), Fsm(fp), id, 0, FsmStateName(fp->state)));
                    645:     FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
                    646:   }
                    647: }
                    648: 
                    649: /*
                    650:  * CcpRecvResetAck()
                    651:  */
                    652: 
                    653: static void
                    654: CcpRecvResetAck(Fsm fp, int id, Mbuf bp)
                    655: {
                    656:     Bund       b = (Bund)fp->arg;
                    657:   CcpState     const ccp = &b->ccp;
                    658:   CompType     const ct = ccp->recv;
                    659: 
                    660:   if (ct && ct->RecvResetAck)
                    661:     (*ct->RecvResetAck)(b, id, bp);
                    662: }
                    663: 
                    664: /*
                    665:  * CcpInput()
                    666:  */
                    667: 
                    668: void
                    669: CcpInput(Bund b, Mbuf bp)
                    670: {
                    671:   FsmInput(&b->ccp.fsm, bp);
                    672: }
                    673: 
                    674: /*
                    675:  * CcpDataOutput()
                    676:  *
                    677:  * Compress a frame. Consumes the original packet.
                    678:  */
                    679: 
                    680: Mbuf
                    681: CcpDataOutput(Bund b, Mbuf plain)
                    682: {
                    683:   CcpState     const ccp = &b->ccp;
                    684:   Mbuf         comp;
                    685: 
                    686:   LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    687: 
                    688: /* Compress packet */
                    689: 
                    690:   if ((!ccp->xmit) || (!ccp->xmit->Compress))
                    691:   {
                    692:     Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                    693:     mbfree(plain);
                    694:     return(NULL);
                    695:   }
                    696:   comp = (*ccp->xmit->Compress)(b, plain);
                    697:   LogDumpBp(LG_FRAME, comp, "[%s] %s: xmit comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    698: 
                    699:   return(comp);
                    700: }
                    701: 
                    702: /*
                    703:  * CcpDataInput()
                    704:  *
                    705:  * Decompress incoming packet. If packet got garbled, return NULL.
                    706:  * In any case, we consume the packet passed to us.
                    707:  */
                    708: 
                    709: Mbuf
                    710: CcpDataInput(Bund b, Mbuf comp)
                    711: {
                    712:   CcpState     const ccp = &b->ccp;
                    713:   Mbuf         plain;
                    714: 
                    715:   LogDumpBp(LG_FRAME, comp, "[%s] %s: recv comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    716: 
                    717: /* Decompress packet */
                    718: 
                    719:   if ((!ccp->recv) || (!ccp->recv->Decompress))
                    720:   {
                    721:     Log(LG_ERR, ("[%s] %s: no compression for recv", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                    722:     mbfree(comp);
                    723:     return(NULL);
                    724:   }
                    725: 
                    726:   plain = (*ccp->recv->Decompress)(b, comp);
                    727: 
                    728: /* Encrypted ok? */
                    729: 
                    730:   if (plain == NULL)
                    731:   {
                    732:     Log(LG_CCP, ("[%s] %s: decompression failed", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                    733:     return(NULL);
                    734:   }
                    735:   LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
                    736: 
                    737:   return(plain);
                    738: }
                    739: 
                    740: /*
                    741:  * CcpBuildConfigReq()
                    742:  */
                    743: 
                    744: static u_char *
                    745: CcpBuildConfigReq(Fsm fp, u_char *cp)
                    746: {
                    747:     Bund       b = (Bund)fp->arg;
                    748:     CcpState   const ccp = &b->ccp;
                    749:     int                type;
                    750:     int                ok;
                    751: 
                    752:     /* Put in all options that peer hasn't rejected in preferred order */
                    753:     ccp->xmit = NULL;
                    754:     for (type = 0; type < CCP_NUM_PROTOS; type++) {
                    755:        CompType        const ct = gCompTypes[type];
                    756: 
                    757:        if (Enabled(&ccp->options, type) && !CCP_PEER_REJECTED(ccp, type)) {
                    758:            cp = (*ct->BuildConfigReq)(b, cp, &ok);
                    759:            if (ok && (!ccp->xmit))
                    760:                ccp->xmit = ct;
                    761:        }
                    762:     }
                    763:     return(cp);
                    764: }
                    765: 
                    766: /*
                    767:  * CcpLayerUp()
                    768:  */
                    769: 
                    770: static void
                    771: CcpLayerUp(Fsm fp)
                    772: {
                    773:     Bund       b = (Bund)fp->arg;
                    774:   CcpState     const ccp = &b->ccp;
                    775:   struct ngm_connect    cn;
                    776:   char         buf[64];
                    777: 
                    778:   /* If nothing was negotiated in either direction, close CCP */
                    779:   if ((!ccp->recv || !(*ccp->recv->Negotiated)(b, COMP_DIR_RECV))
                    780:       && (!ccp->xmit || !(*ccp->xmit->Negotiated)(b, COMP_DIR_XMIT))) {
                    781:     Log(LG_CCP, ("[%s] %s: No compression negotiated", Pref(fp), Fsm(fp)));
                    782:     FsmFailure(fp, FAIL_NEGOT_FAILURE);
                    783:     return;
                    784:   }
                    785: 
                    786:   /* Check for required encryption */
                    787:   if (CcpCheckEncryption(b) < 0) {
                    788:     return;
                    789:   }
                    790: 
                    791:   /* Initialize each direction */
                    792:   if (ccp->xmit != NULL && ccp->xmit->Init != NULL
                    793:       && (*ccp->xmit->Init)(b, COMP_DIR_XMIT) < 0) {
                    794:     Log(LG_CCP, ("[%s] %s: compression init failed", Pref(fp), Fsm(fp)));
                    795:     FsmFailure(fp, FAIL_NEGOT_FAILURE);                /* XXX */
                    796:     return;
                    797:   }
                    798:   if (ccp->recv != NULL && ccp->recv->Init != NULL
                    799:       && (*ccp->recv->Init)(b, COMP_DIR_RECV) < 0) {
                    800:     Log(LG_CCP, ("[%s] %s: decompression init failed", Pref(fp), Fsm(fp)));
                    801:     FsmFailure(fp, FAIL_NEGOT_FAILURE);                /* XXX */
                    802:     return;
                    803:   }
                    804: 
                    805:   if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
                    806:     /* Connect a hook from the ppp node to our socket node */
                    807:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
                    808:     snprintf(cn.ourhook, sizeof(cn.ourhook), "c%d", b->id);
                    809:     strcpy(cn.peerhook, NG_PPP_HOOK_COMPRESS);
                    810:     if (NgSendMsg(gCcpCsock, ".:",
                    811:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    812:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    813:            b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    814:     }
                    815:   }
                    816: 
                    817:   if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
                    818:     /* Connect a hook from the ppp node to our socket node */
                    819:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
                    820:     snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
                    821:     strcpy(cn.peerhook, NG_PPP_HOOK_DECOMPRESS);
                    822:     if (NgSendMsg(gCcpCsock, ".:",
                    823:            NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
                    824:        Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
                    825:            b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
                    826:     }
                    827:   }
                    828: 
                    829:   /* Report what we're doing */
                    830:   Log(LG_CCP, ("[%s] CCP: Compress using: %s (%s)", b->name, !ccp->xmit ? "none" : ccp->xmit->name,
                    831:     (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(b, COMP_DIR_XMIT, buf, sizeof(buf)) : ""));
                    832:   Log(LG_CCP, ("[%s] CCP: Decompress using: %s (%s)", b->name, !ccp->recv ? "none" : ccp->recv->name,
                    833:     (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(b, COMP_DIR_RECV, buf, sizeof(buf)) : ""));
                    834: 
                    835:   /* Update PPP node config */
                    836:   b->pppConfig.bund.enableCompression = (ccp->xmit != NULL)?ccp->xmit->mode:0;
                    837:   b->pppConfig.bund.enableDecompression = (ccp->recv != NULL)?ccp->recv->mode:0;
                    838:   NgFuncSetConfig(b);
                    839: 
                    840:   /* Update interface MTU */
                    841:   BundUpdateParams(b);
                    842: }
                    843: 
                    844: /*
                    845:  * CcpLayerDown()
                    846:  */
                    847: 
                    848: static void
                    849: CcpLayerDown(Fsm fp)
                    850: {
                    851:     Bund       b = (Bund)fp->arg;
                    852:   CcpState     const ccp = &b->ccp;
                    853: 
                    854:   /* Update PPP node config */
                    855:   b->pppConfig.bund.enableCompression = 0;
                    856:   b->pppConfig.bund.enableDecompression = 0;
                    857:   NgFuncSetConfig(b);
                    858: 
                    859:   /* Update interface MTU */
                    860:   BundUpdateParams(b);
                    861:   
                    862:   if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
                    863:     char       hook[NG_HOOKSIZ];
                    864:     /* Disconnect hook. */
                    865:     snprintf(hook, sizeof(hook), "c%d", b->id);
                    866:     NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
                    867:   }
                    868:   
                    869:   if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
                    870:     char       hook[NG_HOOKSIZ];
                    871:     /* Disconnect hook. */
                    872:     snprintf(hook, sizeof(hook), "d%d", b->id);
                    873:     NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
                    874:   }
                    875:   if (ccp->recv && ccp->recv->Cleanup)
                    876:     (*ccp->recv->Cleanup)(b, COMP_DIR_RECV);
                    877:   if (ccp->xmit && ccp->xmit->Cleanup)
                    878:     (*ccp->xmit->Cleanup)(b, COMP_DIR_XMIT);
                    879: 
                    880:   ccp->xmit_resets = 0;
                    881:   ccp->recv_resets = 0;
                    882: }
                    883: 
                    884: /*
                    885:  * CcpDecodeConfig()
                    886:  */
                    887: 
                    888: static void
                    889: CcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
                    890: {
                    891:     Bund       b = (Bund)fp->arg;
                    892:   CcpState     const ccp = &b->ccp;
                    893:   u_int                ackSizeSave, rejSizeSave;
                    894:   int          k, rej;
                    895: 
                    896:   /* Forget our previous choice on new request */
                    897:   if (mode == MODE_REQ)
                    898:     ccp->recv = NULL;
                    899: 
                    900:   /* Decode each config option */
                    901:   for (k = 0; k < num; k++) {
                    902:     FsmOption  const opt = &list[k];
                    903:     int                index;
                    904:     CompType   ct;
                    905:     char       buf[32];
                    906: 
                    907:     Log(LG_CCP, ("[%s]   %s", b->name, CcpTypeName(opt->type, buf, sizeof(buf))));
                    908:     if ((ct = CcpFindComp(opt->type, &index)) == NULL) {
                    909:       if (mode == MODE_REQ) {
                    910:        Log(LG_CCP, ("[%s]     Not supported", b->name));
                    911:        FsmRej(fp, opt);
                    912:       }
                    913:       continue;
                    914:     }
                    915:     switch (mode) {
                    916:       case MODE_REQ:
                    917:        ackSizeSave = gAckSize;
                    918:        rejSizeSave = gRejSize;
                    919:        rej = (!Acceptable(&ccp->options, index)
                    920:          || CCP_SELF_REJECTED(ccp, index)
                    921:          || (ccp->recv && ccp->recv != ct));
                    922:        if (rej) {
                    923:          (*ct->DecodeConfig)(fp, opt, MODE_NOP);
                    924:          FsmRej(fp, opt);
                    925:          break;
                    926:        }
                    927:        (*ct->DecodeConfig)(fp, opt, mode);
                    928:        if (gRejSize != rejSizeSave) {          /* we rejected it */
                    929:          CCP_SELF_REJ(ccp, index);
                    930:          break;
                    931:        }
                    932:        if (gAckSize != ackSizeSave)            /* we accepted it */
                    933:          ccp->recv = ct;
                    934:        break;
                    935: 
                    936:       case MODE_REJ:
                    937:        (*ct->DecodeConfig)(fp, opt, mode);
                    938:        CCP_PEER_REJ(ccp, index);
                    939:        break;
                    940: 
                    941:       case MODE_NAK:
                    942:       case MODE_NOP:
                    943:        (*ct->DecodeConfig)(fp, opt, mode);
                    944:        break;
                    945:     }
                    946:   }
                    947: }
                    948: 
                    949: /*
                    950:  * CcpSubtractBloat()
                    951:  *
                    952:  * Given that "size" is our MTU, return the maximum length frame
                    953:  * we can compress without the result being longer than "size".
                    954:  */
                    955: 
                    956: int
                    957: CcpSubtractBloat(Bund b, int size)
                    958: {
                    959:   CcpState     const ccp = &b->ccp;
                    960: 
                    961:   /* Account for transmit compression overhead */
                    962:   if (OPEN_STATE(ccp->fsm.state) && ccp->xmit && ccp->xmit->SubtractBloat)
                    963:     size = (*ccp->xmit->SubtractBloat)(b, size);
                    964: 
                    965:   /* Account for CCP's protocol number overhead */
                    966:   if (OPEN_STATE(ccp->fsm.state))
                    967:     size -= CCP_OVERHEAD;
                    968: 
                    969:   /* Done */
                    970:   return(size);
                    971: }
                    972: 
                    973: /*
                    974:  * CcpCheckEncryption()
                    975:  *
                    976:  * Because MPPE is negotiated as an option to MPPC compression,
                    977:  * we have to check for encryption required when CCP comes up.
                    978:  */
                    979: 
                    980: static int
                    981: CcpCheckEncryption(Bund b)
                    982: {
                    983: #if 0
                    984:   CcpState     const ccp = &b->ccp;
                    985: 
                    986:   /* Already checked? */
                    987:   if (ccp->crypt_check)
                    988:     return(0);
                    989:   ccp->crypt_check = 1;
                    990: 
                    991:   /* Is encryption required? */
                    992:   if (Enabled(&ccp->options, gMppePolicy)) {
                    993:     if (b->params.msoft.policy != MPPE_POLICY_REQUIRED) 
                    994:       return(0);
                    995:   } else {
                    996:     if (!Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD))
                    997:       return(0);
                    998:   }
                    999: 
                   1000:   /* Was MPPE encryption enabled? If not, ignore requirement */
                   1001:   if (!Enabled(&ccp->options, gMppe40)
                   1002:       && !Enabled(&ccp->options, gMppe56)
                   1003:       && !Enabled(&ccp->options, gMppe128)
                   1004:       && !Enabled(&ccp->options, gMppePolicy))
                   1005:     return(0);
                   1006: 
                   1007:   /* Make sure MPPE was negotiated in both directions */
                   1008:   if (!OPEN_STATE(ccp->fsm.state)
                   1009:       || !ccp->xmit || ccp->xmit->type != CCP_TY_MPPC
                   1010:       || !ccp->recv || ccp->recv->type != CCP_TY_MPPC
                   1011: #ifdef CCP_MPPC
                   1012:       || !(ccp->mppc.recv_bits & MPPE_BITS)
                   1013:       || !(ccp->mppc.xmit_bits & MPPE_BITS)
                   1014: #endif
                   1015:       )
                   1016:     goto fail;
                   1017: 
                   1018:   /* Looks OK */
                   1019:   return(0);
                   1020: 
                   1021: fail:
                   1022:   Log(LG_ERR, ("[%s] %s: encryption required, but MPPE was not"
                   1023:     " negotiated in both directions", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
                   1024:   FsmFailure(&ccp->fsm, FAIL_CANT_ENCRYPT);
                   1025:   FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
                   1026:   FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
                   1027:   return(-1);
                   1028: #endif
                   1029:     return (0);
                   1030: }
                   1031: 
                   1032: /*
                   1033:  * CcpSetCommand()
                   1034:  */
                   1035: 
                   1036: static int
                   1037: CcpSetCommand(Context ctx, int ac, char *av[], void *arg)
                   1038: {
                   1039:   CcpState     const ccp = &ctx->bund->ccp;
                   1040: 
                   1041:   if (ac == 0)
                   1042:     return(-1);
                   1043:   switch ((intptr_t)arg) {
                   1044:     case SET_ACCEPT:
                   1045:       AcceptCommand(ac, av, &ccp->options, gConfList);
                   1046:       break;
                   1047: 
                   1048:     case SET_DENY:
                   1049:       DenyCommand(ac, av, &ccp->options, gConfList);
                   1050:       break;
                   1051: 
                   1052:     case SET_ENABLE:
                   1053:       EnableCommand(ac, av, &ccp->options, gConfList);
                   1054:       break;
                   1055: 
                   1056:     case SET_DISABLE:
                   1057:       DisableCommand(ac, av, &ccp->options, gConfList);
                   1058:       break;
                   1059: 
                   1060:     case SET_YES:
                   1061:       YesCommand(ac, av, &ccp->options, gConfList);
                   1062:       break;
                   1063: 
                   1064:     case SET_NO:
                   1065:       NoCommand(ac, av, &ccp->options, gConfList);
                   1066:       break;
                   1067: 
                   1068:     default:
                   1069:       assert(0);
                   1070:   }
                   1071:   return(0);
                   1072: }
                   1073: 
                   1074: /*
                   1075:  * CcpFindComp()
                   1076:  */
                   1077: 
                   1078: static CompType
                   1079: CcpFindComp(int type, int *indexp)
                   1080: {
                   1081:   int  k;
                   1082: 
                   1083:   for (k = 0; k < CCP_NUM_PROTOS; k++) {
                   1084:     if (gCompTypes[k]->type == type) {
                   1085:       if (indexp)
                   1086:        *indexp = k;
                   1087:       return(gCompTypes[k]);
                   1088:     }
                   1089:   }
                   1090:   return(NULL);
                   1091: }
                   1092: 
                   1093: /*
                   1094:  * CcpTypeName()
                   1095:  */
                   1096: 
                   1097: static const char *
                   1098: CcpTypeName(int type, char *buf, size_t len)
                   1099: {
                   1100:   const struct ccpname *p;
                   1101: 
                   1102:   for (p = gCcpTypeNames; p->name; p++) {
                   1103:     if (p->type == type) {
                   1104:        strlcpy(buf, p->name, len);
                   1105:         return (buf);
                   1106:     }
                   1107:   }
                   1108:   snprintf(buf, sizeof(buf), "UNKNOWN[%d]", type);
                   1109:   return(buf);
                   1110: }
                   1111: 

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