File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ccp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (4 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

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

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