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