File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ccp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

    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 %zu 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>