File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ecp.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:  * ecp.c
    4:  *
    5:  * Written by Archie Cobbs <archie@freebsd.org>
    6:  * Copyright (c) 1998-1999 Whistle Communications, Inc. All rights reserved.
    7:  * See ``COPYRIGHT.whistle''
    8:  */
    9: 
   10: #include "ppp.h"
   11: #include "bund.h"
   12: #include "ecp.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 ECP_MAXFAILURE	7
   25: 
   26:   #define ECP_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:   #define ECP_OVERHEAD		2
   37: 
   38:   #define ECP_PEER_REJECTED(p,x)	((p)->peer_reject & (1<<(x)))
   39:   #define ECP_SELF_REJECTED(p,x)	((p)->self_reject & (1<<(x)))
   40: 
   41:   #define ECP_PEER_REJ(p,x)	do{(p)->peer_reject |= (1<<(x));}while(0)
   42:   #define ECP_SELF_REJ(p,x)	do{(p)->self_reject |= (1<<(x));}while(0)
   43: 
   44: /* Set menu options */
   45: 
   46:   enum
   47:   {
   48:     SET_KEY,
   49:     SET_ACCEPT,
   50:     SET_DENY,
   51:     SET_ENABLE,
   52:     SET_DISABLE,
   53:     SET_YES,
   54:     SET_NO
   55:   };
   56: 
   57: /*
   58:  * INTERNAL FUNCTIONS
   59:  */
   60: 
   61:   static void		EcpConfigure(Fsm fp);
   62:   static void		EcpUnConfigure(Fsm fp);
   63:   static u_char		*EcpBuildConfigReq(Fsm fp, u_char *cp);
   64:   static void		EcpDecodeConfig(Fsm fp, FsmOption a, int num, int mode);
   65:   static void		EcpLayerUp(Fsm fp);
   66:   static void		EcpLayerDown(Fsm fp);
   67:   static void		EcpFailure(Fsm f, enum fsmfail reason);
   68:   static void		EcpRecvResetReq(Fsm fp, int id, Mbuf bp);
   69:   static void		EcpRecvResetAck(Fsm fp, int id, Mbuf bp);
   70: 
   71:   static int		EcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
   72:   static EncType	EcpFindType(int type, int *indexp);
   73:   static const char	*EcpTypeName(int type);
   74: 
   75:   static void		EcpNgDataEvent(int type, void *cookie);
   76: 
   77: /*
   78:  * GLOBAL VARIABLES
   79:  */
   80: 
   81:   const struct cmdtab EcpSetCmds[] =
   82:   {
   83:     { "key {string}",			"Set encryption key",
   84: 	EcpSetCommand, NULL, 2, (void *) SET_KEY },
   85:     { "accept [opt ...]",		"Accept option",
   86: 	EcpSetCommand, NULL, 2, (void *) SET_ACCEPT },
   87:     { "deny [opt ...]",			"Deny option",
   88: 	EcpSetCommand, NULL, 2, (void *) SET_DENY },
   89:     { "enable [opt ...]",		"Enable option",
   90: 	EcpSetCommand, NULL, 2, (void *) SET_ENABLE },
   91:     { "disable [opt ...]",		"Disable option",
   92: 	EcpSetCommand, NULL, 2, (void *) SET_DISABLE },
   93:     { "yes [opt ...]",			"Enable and accept option",
   94: 	EcpSetCommand, NULL, 2, (void *) SET_YES },
   95:     { "no [opt ...]",			"Disable and deny option",
   96: 	EcpSetCommand, NULL, 2, (void *) SET_NO },
   97:     { NULL, NULL, NULL, NULL, 0, NULL },
   98:   };
   99: 
  100: /*
  101:  * INTERNAL VARIABLES
  102:  */
  103: 
  104: /* These should be listed in order of preference */
  105: 
  106:   static const EncType gEncTypes[] =
  107:   {
  108: #ifdef ECP_DES
  109:     &gDeseBisEncType,
  110:     &gDeseEncType,
  111: #endif
  112:   };
  113:   #define ECP_NUM_PROTOS	(sizeof(gEncTypes) / sizeof(*gEncTypes))
  114: 
  115: /* Corresponding option list */
  116: 
  117:   static const struct confinfo *gConfList;
  118: 
  119: /* Initializer for struct fsm fields */
  120: 
  121:   static const struct fsmtype gEcpFsmType =
  122:   {
  123:     "ECP",
  124:     PROTO_ECP,
  125:     ECP_KNOWN_CODES,
  126:     FALSE,
  127:     LG_ECP, LG_ECP2,
  128:     NULL,
  129:     EcpLayerUp,
  130:     EcpLayerDown,
  131:     NULL,
  132:     NULL,
  133:     EcpBuildConfigReq,
  134:     EcpDecodeConfig,
  135:     EcpConfigure,
  136:     EcpUnConfigure,
  137:     NULL,
  138:     NULL,
  139:     NULL,
  140:     NULL,
  141:     EcpFailure,
  142:     EcpRecvResetReq,
  143:     EcpRecvResetAck,
  144:     NULL, NULL, NULL, NULL
  145:   };
  146: 
  147: /* Names for different types of encryption */
  148: 
  149:   static const struct ecpname
  150:   {
  151:     u_char	type;
  152:     const char	*name;
  153:   }
  154:   gEcpTypeNames[] =
  155:   {
  156:     { ECP_TY_OUI,	"OUI" },
  157:     { ECP_TY_DESE,	"DESE" },
  158:     { ECP_TY_3DESE,	"3DESE" },
  159:     { ECP_TY_DESE_bis,	"DESE-bis" },
  160:     { 0,		NULL },
  161:   };
  162: 
  163:     int		gEcpCsock = -1;		/* Socket node control socket */
  164:     int		gEcpDsock = -1;		/* Socket node data socket */
  165:     static EventRef gEcpDataEvent;
  166: 
  167: int
  168: EcpsInit(void)
  169: {
  170:     char	name[NG_NODESIZ];
  171: 
  172:     /* Create a netgraph socket node */
  173:     snprintf(name, sizeof(name), "mpd%d-eso", gPid);
  174:     if (NgMkSockNode(name, &gEcpCsock, &gEcpDsock) < 0) {
  175: 	Perror("EcpsInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
  176: 	return(-1);
  177:     }
  178:     (void) fcntl(gEcpCsock, F_SETFD, 1);
  179:     (void) fcntl(gEcpDsock, F_SETFD, 1);
  180: 
  181:     /* Listen for happenings on our node */
  182:     EventRegister(&gEcpDataEvent, EVENT_READ,
  183: 	gEcpDsock, EVENT_RECURRING, EcpNgDataEvent, NULL);
  184: 	
  185:     return (0);
  186: }
  187: 
  188: void
  189: EcpsShutdown(void)
  190: {
  191:     close(gEcpCsock);
  192:     gEcpCsock = -1;
  193:     EventUnRegister(&gEcpDataEvent);
  194:     close(gEcpDsock);
  195:     gEcpDsock = -1;
  196: }
  197: 
  198: /*
  199:  * EcpInit()
  200:  */
  201: 
  202: void
  203: EcpInit(Bund b)
  204: {
  205:   EcpState	ecp = &b->ecp;
  206: 
  207: /* Init ECP state for this bundle */
  208: 
  209:   memset(ecp, 0, sizeof(*ecp));
  210:   FsmInit(&ecp->fsm, &gEcpFsmType, b);
  211:   ecp->fsm.conf.maxfailure = ECP_MAXFAILURE;
  212: 
  213: /* Construct options list if we haven't done so already */
  214: 
  215:   if (gConfList == NULL)
  216:   {
  217:     struct confinfo	*ci;
  218:     unsigned		k;
  219: 
  220:     ci = Malloc(MB_CRYPT, (ECP_NUM_PROTOS + 1) * sizeof(*ci));
  221:     for (k = 0; k < ECP_NUM_PROTOS; k++)
  222:     {
  223:       ci[k].option = k;
  224:       ci[k].peered = TRUE;
  225:       ci[k].name = gEncTypes[k]->name;
  226:     }
  227:     ci[k].name = NULL;
  228:     gConfList = (const struct confinfo *) ci;
  229:   }
  230: }
  231: 
  232: /*
  233:  * EcpInst()
  234:  */
  235: 
  236: void
  237: EcpInst(Bund b, Bund bt)
  238: {
  239:   EcpState	ecp = &b->ecp;
  240: 
  241: /* Init ECP state for this bundle */
  242:   memcpy(ecp, &bt->ecp, sizeof(*ecp));
  243:   FsmInst(&ecp->fsm, &bt->ecp.fsm, b);
  244: }
  245: 
  246: /*
  247:  * EcpConfigure()
  248:  */
  249: 
  250: static void
  251: EcpConfigure(Fsm fp)
  252: {
  253:     Bund 	b = (Bund)fp->arg;
  254:   EcpState	const ecp = &b->ecp;
  255:   unsigned	k;
  256: 
  257:   for (k = 0; k < ECP_NUM_PROTOS; k++)
  258:   {
  259:     EncType	const et = gEncTypes[k];
  260: 
  261:     if (et->Configure)
  262:       (*et->Configure)(b);
  263:   }
  264:   ecp->xmit = NULL;
  265:   ecp->recv = NULL;
  266:   ecp->self_reject = 0;
  267:   ecp->peer_reject = 0;
  268: }
  269: 
  270: /*
  271:  * EcpUnConfigure()
  272:  */
  273: 
  274: static void
  275: EcpUnConfigure(Fsm fp)
  276: {
  277:     Bund 	b = (Bund)fp->arg;
  278:   EcpState	const ecp = &b->ecp;
  279:   unsigned	k;
  280: 
  281:   for (k = 0; k < ECP_NUM_PROTOS; k++)
  282:   {
  283:     EncType	const et = gEncTypes[k];
  284: 
  285:     if (et->UnConfigure)
  286:       (*et->UnConfigure)(b);
  287:   }
  288:   ecp->xmit = NULL;
  289:   ecp->recv = NULL;
  290:   ecp->self_reject = 0;
  291:   ecp->peer_reject = 0;
  292: }
  293: 
  294: /*
  295:  * EcpNgDataEvent()
  296:  */
  297: 
  298: static void
  299: EcpNgDataEvent(int type, void *cookie)
  300: {
  301:     Bund		b;
  302:     struct sockaddr_ng	naddr;
  303:     socklen_t		nsize;
  304:     Mbuf		bp;
  305:     int			num = 0;
  306:     char                *bundname, *rest, *b1;
  307:     int                 id;
  308: 		
  309:     (void)type;
  310:     (void)cookie;
  311:     while (1) {
  312: 	/* Protect from bundle shutdown and DoS */
  313: 	if (num > 100)
  314: 	    return;
  315:     
  316: 	bp = mballoc(4096);
  317: 
  318: 	/* Read data */
  319: 	nsize = sizeof(naddr);
  320: 	if ((bp->cnt = recvfrom(gEcpDsock, MBDATA(bp), MBSPACE(bp),
  321:     		MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
  322: 	    mbfree(bp);
  323: 	    if (errno == EAGAIN)
  324:     		return;
  325: 	    Log(LG_BUND|LG_ERR, ("EcpNgDataEvent: socket read: %s", strerror(errno)));
  326: 	    return;
  327: 	}
  328: 	num++;
  329:     
  330: 	/* Debugging */
  331: 	LogDumpBp(LG_FRAME, bp,
  332: 	    "EcpNgDataEvent: rec'd %zu bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
  333: 
  334: 	bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
  335: 	if (bundname[0] != 'e' && bundname[0] != 'd') {
  336:     	    Log(LG_ERR, ("ECP: Packet from unknown hook \"%s\"",
  337:     	        bundname));
  338: 	    mbfree(bp);
  339:     	    continue;
  340: 	}
  341: 	/* Keep old value */
  342: 	b1 = bundname;
  343: 	bundname++;
  344: 	id = strtol(bundname, &rest, 10);
  345: 	if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
  346:     	    Log(LG_ERR, ("ECP: Packet from unexisting bundle \"%s\"",
  347: 		bundname));
  348: 	    mbfree(bp);
  349: 	    continue;
  350: 	}
  351: 		
  352: 	b = gBundles[id];
  353: 
  354: 	/* Packet requiring compression */
  355: 	if (b1[0] == 'e') {
  356: 	    bp = EcpDataOutput(b, bp);
  357: 	} else {
  358: 	    /* Packet requiring decompression */
  359: 	    bp = EcpDataInput(b, bp);
  360: 	}
  361: 	if (bp)
  362: 	    NgFuncWriteFrame(gEcpDsock, naddr.sg_data, b->name, bp);
  363:     }
  364: }
  365: 
  366: 
  367: /*
  368:  * EcpDataOutput()
  369:  *
  370:  * Encrypt a frame. Consumes the original packet.
  371:  */
  372: 
  373: Mbuf
  374: EcpDataOutput(Bund b, Mbuf plain)
  375: {
  376:   EcpState	const ecp = &b->ecp;
  377:   Mbuf		cypher;
  378: 
  379:   LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
  380: 
  381: /* Encrypt packet */
  382: 
  383:   if ((!ecp->xmit) || (!ecp->xmit->Encrypt))
  384:   {
  385:     Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
  386:     mbfree(plain);
  387:     return(NULL);
  388:   }
  389:   cypher = (*ecp->xmit->Encrypt)(b, plain);
  390:   LogDumpBp(LG_FRAME, cypher, "[%s] %s: xmit cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
  391: 
  392: /* Return result, with new protocol number */
  393: 
  394:   return(cypher);
  395: }
  396: 
  397: /*
  398:  * EcpDataInput()
  399:  *
  400:  * Decrypt incoming packet. If packet got garbled, return NULL.
  401:  * In any case, we consume the packet passed to us.
  402:  */
  403: 
  404: Mbuf
  405: EcpDataInput(Bund b, Mbuf cypher)
  406: {
  407:   EcpState	const ecp = &b->ecp;
  408:   Mbuf		plain;
  409: 
  410:   LogDumpBp(LG_FRAME, cypher, "[%s] %s: recv cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
  411: 
  412: /* Decrypt packet */
  413: 
  414:   if ((!ecp->recv) || (!ecp->recv->Decrypt))
  415:   {
  416:     Log(LG_ERR, ("[%s] %s: no encryption for recv", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
  417:     mbfree(cypher);
  418:     return(NULL);
  419:   }
  420: 
  421:   plain = (*ecp->recv->Decrypt)(b, cypher);
  422: 
  423: /* Decrypted ok? */
  424: 
  425:   if (plain == NULL)
  426:   {
  427:     Log(LG_ECP, ("[%s] %s: decryption failed", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
  428:     return(NULL);
  429:   }
  430: 
  431:   LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
  432: /* Done */
  433: 
  434:   return(plain);
  435: }
  436: 
  437: /*
  438:  * EcpUp()
  439:  */
  440: 
  441: void
  442: EcpUp(Bund b)
  443: {
  444:   FsmUp(&b->ecp.fsm);
  445: }
  446: 
  447: /*
  448:  * EcpDown()
  449:  */
  450: 
  451: void
  452: EcpDown(Bund b)
  453: {
  454:   FsmDown(&b->ecp.fsm);
  455: }
  456: 
  457: /*
  458:  * EcpOpen()
  459:  */
  460: 
  461: void
  462: EcpOpen(Bund b)
  463: {
  464:   FsmOpen(&b->ecp.fsm);
  465: }
  466: 
  467: /*
  468:  * EcpClose()
  469:  */
  470: 
  471: void
  472: EcpClose(Bund b)
  473: {
  474:   FsmClose(&b->ecp.fsm);
  475: }
  476: 
  477: /*
  478:  * EcpOpenCmd()
  479:  */
  480: 
  481: int
  482: EcpOpenCmd(Context ctx)
  483: {
  484:     if (ctx->bund->tmpl)
  485: 	Error("impossible to open template");
  486:     FsmOpen(&ctx->bund->ecp.fsm);
  487:     return (0);
  488: }
  489: 
  490: /*
  491:  * EcpCloseCmd()
  492:  */
  493: 
  494: int
  495: EcpCloseCmd(Context ctx)
  496: {
  497:     if (ctx->bund->tmpl)
  498: 	Error("impossible to close template");
  499:     FsmClose(&ctx->bund->ecp.fsm);
  500:     return (0);
  501: }
  502: 
  503: /*
  504:  * EcpFailure()
  505:  *
  506:  * This is fatal to the entire link if encryption is required.
  507:  */
  508: 
  509: static void
  510: EcpFailure(Fsm fp, enum fsmfail reason)
  511: {
  512:     Bund 	b = (Bund)fp->arg;
  513: 
  514:     (void)reason;
  515:     if (Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD)) {
  516: 	FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
  517: 	FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
  518:     }
  519: }
  520: 
  521: /*
  522:  * EcpStat()
  523:  */
  524: 
  525: int
  526: EcpStat(Context ctx, int ac, const char *const av[], const void *arg)
  527: {
  528:   EcpState	const ecp = &ctx->bund->ecp;
  529: 
  530:   (void)ac;
  531:   (void)av;
  532:   (void)arg;
  533: 
  534:   Printf("[%s] %s [%s]\r\n", Pref(&ecp->fsm), Fsm(&ecp->fsm), FsmStateName(ecp->fsm.state));
  535:   Printf("Enabled protocols:\r\n");
  536:   OptStat(ctx, &ecp->options, gConfList);
  537:   Printf("Outgoing encryption:\r\n");
  538:   Printf("\tProto\t: %s\r\n", ecp->xmit ? ecp->xmit->name : "none");
  539:   if (ecp->xmit && ecp->xmit->Stat)
  540:     ecp->xmit->Stat(ctx, ECP_DIR_XMIT);
  541:   Printf("\tResets\t: %d\r\n", ecp->xmit_resets);
  542:   Printf("Incoming decryption:\r\n");
  543:   Printf("\tProto\t: %s\r\n", ecp->recv ? ecp->recv->name : "none");
  544:   if (ecp->recv && ecp->recv->Stat)
  545:     ecp->recv->Stat(ctx, ECP_DIR_RECV);
  546:   Printf("\tResets\t: %d\r\n", ecp->recv_resets);
  547:   return(0);
  548: }
  549: 
  550: /*
  551:  * EcpSendResetReq()
  552:  */
  553: 
  554: void
  555: EcpSendResetReq(Fsm fp)
  556: {
  557:     Bund 	b = (Bund)fp->arg;
  558:   EcpState	const ecp = &b->ecp;
  559:   EncType	const et = ecp->recv;
  560:   Mbuf		bp = NULL;
  561: 
  562:   assert(et);
  563:   ecp->recv_resets++;
  564:   if (et->SendResetReq)
  565:     bp = (*et->SendResetReq)(b);
  566:   Log(LG_ECP, ("[%s] %s: SendResetReq", Pref(fp), Fsm(fp)));
  567:   FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
  568: }
  569: 
  570: /*
  571:  * EcpRecvResetReq()
  572:  */
  573: 
  574: void
  575: EcpRecvResetReq(Fsm fp, int id, Mbuf bp)
  576: {
  577:     Bund 	b = (Bund)fp->arg;
  578:   EcpState	const ecp = &b->ecp;
  579:   EncType	const et = ecp->xmit;
  580: 
  581:   ecp->xmit_resets++;
  582:   bp = (et && et->RecvResetReq) ? (*et->RecvResetReq)(b, id, bp) : NULL;
  583:   Log(fp->log, ("[%s] %s: SendResetAck", Pref(fp), Fsm(fp)));
  584:   FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
  585: }
  586: 
  587: /*
  588:  * EcpRecvResetAck()
  589:  */
  590: 
  591: static void
  592: EcpRecvResetAck(Fsm fp, int id, Mbuf bp)
  593: {
  594:     Bund 	b = (Bund)fp->arg;
  595:   EcpState	const ecp = &b->ecp;
  596:   EncType	const et = ecp->recv;
  597: 
  598:   if (et && et->RecvResetAck)
  599:     (*et->RecvResetAck)(b, id, bp);
  600: }
  601: 
  602: /*
  603:  * EcpInput()
  604:  */
  605: 
  606: void
  607: EcpInput(Bund b, Mbuf bp)
  608: {
  609:   FsmInput(&b->ecp.fsm, bp);
  610: }
  611: 
  612: /*
  613:  * EcpBuildConfigReq()
  614:  */
  615: 
  616: static u_char *
  617: EcpBuildConfigReq(Fsm fp, u_char *cp)
  618: {
  619:     Bund 	b = (Bund)fp->arg;
  620:   EcpState	const ecp = &b->ecp;
  621:   unsigned	type;
  622: 
  623: /* Put in all options that peer hasn't rejected */
  624: 
  625:   for (ecp->xmit = NULL, type = 0; type < ECP_NUM_PROTOS; type++)
  626:   {
  627:     EncType	const et = gEncTypes[type];
  628: 
  629:     if (Enabled(&ecp->options, type) && !ECP_PEER_REJECTED(ecp, type))
  630:     {
  631:       cp = (*et->BuildConfigReq)(b, cp);
  632:       if (!ecp->xmit)
  633: 	ecp->xmit = et;
  634:     }
  635:   }
  636:   return(cp);
  637: }
  638: 
  639: /*
  640:  * EcpLayerUp()
  641:  *
  642:  * Called when ECP has reached the OPENED state
  643:  */
  644: 
  645: static void
  646: EcpLayerUp(Fsm fp)
  647: {
  648:     Bund 	b = (Bund)fp->arg;
  649:   EcpState	const ecp = &b->ecp;
  650:   struct ngm_connect    cn;
  651: 
  652:   /* Initialize */
  653:   if (ecp->xmit && ecp->xmit->Init)
  654:     (*ecp->xmit->Init)(b, ECP_DIR_XMIT);
  655:   if (ecp->recv && ecp->recv->Init)
  656:     (*ecp->recv->Init)(b, ECP_DIR_RECV);
  657: 
  658:   if (ecp->recv && ecp->recv->Decrypt) 
  659:   {
  660:     /* Connect a hook from the bpf node to our socket node */
  661:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
  662:     snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
  663:     strcpy(cn.peerhook, NG_PPP_HOOK_DECRYPT);
  664:     if (NgSendMsg(gEcpCsock, ".:",
  665: 	    NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
  666: 	Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
  667:           b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
  668:     }
  669:   }
  670:   if (ecp->xmit && ecp->xmit->Encrypt)
  671:   {
  672:     /* Connect a hook from the bpf node to our socket node */
  673:     snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
  674:     snprintf(cn.ourhook, sizeof(cn.ourhook), "e%d", b->id);
  675:     strcpy(cn.peerhook, NG_PPP_HOOK_ENCRYPT);
  676:     if (NgSendMsg(gEcpCsock, ".:",
  677: 	    NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
  678: 	Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
  679:           b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
  680:     }
  681:   }
  682: 
  683:   Log(LG_ECP, ("[%s] ECP: Encrypt using: %s", b->name, !ecp->xmit ? "none" : ecp->xmit->name));
  684:   Log(LG_ECP, ("[%s] ECP: Decrypt using: %s", b->name, !ecp->recv ? "none" : ecp->recv->name));
  685: 
  686:   /* Update PPP node config */
  687:   b->pppConfig.bund.enableEncryption = (ecp->xmit != NULL);
  688:   b->pppConfig.bund.enableDecryption = (ecp->recv != NULL);
  689:   NgFuncSetConfig(b);
  690: 
  691:   /* Update interface MTU */
  692:   BundUpdateParams(b);
  693: }
  694: 
  695: /*
  696:  * EcpLayerDown()
  697:  *
  698:  * Called when ECP leaves the OPENED state
  699:  */
  700: 
  701: static void
  702: EcpLayerDown(Fsm fp)
  703: {
  704:     Bund 	b = (Bund)fp->arg;
  705:   EcpState	const ecp = &b->ecp;
  706: 
  707:   /* Update PPP node config */
  708:   b->pppConfig.bund.enableEncryption = 0;
  709:   b->pppConfig.bund.enableDecryption = 0;
  710:   NgFuncSetConfig(b);
  711: 
  712:   /* Update interface MTU */
  713:   BundUpdateParams(b);
  714: 
  715:   if (ecp->xmit != NULL && ecp->xmit->Encrypt != NULL) {
  716:     char	hook[NG_HOOKSIZ];
  717:     /* Disconnect hook. */
  718:     snprintf(hook, sizeof(hook), "e%d", b->id);
  719:     NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
  720:   }
  721:   
  722:   if (ecp->recv != NULL && ecp->recv->Decrypt != NULL) {
  723:     char	hook[NG_HOOKSIZ];
  724:     /* Disconnect hook. */
  725:     snprintf(hook, sizeof(hook), "d%d", b->id);
  726:     NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
  727:   }
  728: 
  729:   if (ecp->xmit && ecp->xmit->Cleanup)
  730:     (ecp->xmit->Cleanup)(b, ECP_DIR_XMIT);
  731:   if (ecp->recv && ecp->recv->Cleanup)
  732:     (ecp->recv->Cleanup)(b, ECP_DIR_RECV);
  733:     
  734:   ecp->xmit_resets = 0;
  735:   ecp->recv_resets = 0;
  736: }
  737: 
  738: /*
  739:  * EcpDecodeConfig()
  740:  */
  741: 
  742: static void
  743: EcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
  744: {
  745:     Bund 	b = (Bund)fp->arg;
  746:   EcpState	const ecp = &b->ecp;
  747:   u_int		ackSizeSave, rejSizeSave;
  748:   int		k, rej;
  749: 
  750:   /* Forget our previous choice on new request */
  751:   if (mode == MODE_REQ)
  752:     ecp->recv = NULL;
  753: 
  754: /* Decode each config option */
  755: 
  756:   for (k = 0; k < num; k++)
  757:   {
  758:     FsmOption	const opt = &list[k];
  759:     int		index;
  760:     EncType	et;
  761: 
  762:     Log(LG_ECP, ("[%s] %s", b->name, EcpTypeName(opt->type)));
  763:     if ((et = EcpFindType(opt->type, &index)) == NULL)
  764:     {
  765:       if (mode == MODE_REQ)
  766:       {
  767: 	Log(LG_ECP, ("[%s]   Not supported", b->name));
  768: 	FsmRej(fp, opt);
  769:       }
  770:       continue;
  771:     }
  772:     switch (mode)
  773:     {
  774:       case MODE_REQ:
  775: 	ackSizeSave = gAckSize;
  776: 	rejSizeSave = gRejSize;
  777: 	rej = (!Acceptable(&ecp->options, index)
  778: 	  || ECP_SELF_REJECTED(ecp, index)
  779: 	  || (ecp->recv && ecp->recv != et));
  780: 	if (rej)
  781: 	{
  782: 	  (*et->DecodeConfig)(fp, opt, MODE_NOP);
  783: 	  FsmRej(fp, opt);
  784: 	  break;
  785: 	}
  786: 	(*et->DecodeConfig)(fp, opt, mode);
  787: 	if (gRejSize != rejSizeSave)		/* we rejected it */
  788: 	{
  789: 	  ECP_SELF_REJ(ecp, index);
  790: 	  break;
  791: 	}
  792: 	if (gAckSize != ackSizeSave)		/* we accepted it */
  793: 	  ecp->recv = et;
  794: 	break;
  795: 
  796:       case MODE_NAK:
  797: 	(*et->DecodeConfig)(fp, opt, mode);
  798: 	break;
  799: 
  800:       case MODE_REJ:
  801: 	(*et->DecodeConfig)(fp, opt, mode);
  802: 	ECP_PEER_REJ(ecp, index);
  803: 	break;
  804: 
  805:       case MODE_NOP:
  806: 	(*et->DecodeConfig)(fp, opt, mode);
  807: 	break;
  808:     }
  809:   }
  810: }
  811: 
  812: /*
  813:  * EcpSubtractBloat()
  814:  *
  815:  * Given that "size" is our MTU, return the maximum length frame
  816:  * we can encrypt without the result being longer than "size".
  817:  */
  818: 
  819: int
  820: EcpSubtractBloat(Bund b, int size)
  821: {
  822:   EcpState	const ecp = &b->ecp;
  823: 
  824:   /* Check transmit encryption */
  825:   if (OPEN_STATE(ecp->fsm.state) && ecp->xmit && ecp->xmit->SubtractBloat)
  826:     size = (*ecp->xmit->SubtractBloat)(b, size);
  827: 
  828:   /* Account for ECP's protocol number overhead */
  829:   if (OPEN_STATE(ecp->fsm.state))
  830:     size -= ECP_OVERHEAD;
  831: 
  832:   /* Done */
  833:   return(size);
  834: }
  835: 
  836: /*
  837:  * EcpSetCommand()
  838:  */
  839: 
  840: static int
  841: EcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
  842: {
  843:   EcpState	const ecp = &ctx->bund->ecp;
  844: 
  845:   if (ac == 0)
  846:     return(-1);
  847:   switch ((intptr_t)arg)
  848:   {
  849:     case SET_KEY:
  850:       if (ac != 1)
  851: 	return(-1);
  852:       strlcpy(ecp->key, av[0], sizeof(ecp->key));
  853:       break;
  854: 
  855:     case SET_ACCEPT:
  856:       AcceptCommand(ac, av, &ecp->options, gConfList);
  857:       break;
  858: 
  859:     case SET_DENY:
  860:       DenyCommand(ac, av, &ecp->options, gConfList);
  861:       break;
  862: 
  863:     case SET_ENABLE:
  864:       EnableCommand(ac, av, &ecp->options, gConfList);
  865:       break;
  866: 
  867:     case SET_DISABLE:
  868:       DisableCommand(ac, av, &ecp->options, gConfList);
  869:       break;
  870: 
  871:     case SET_YES:
  872:       YesCommand(ac, av, &ecp->options, gConfList);
  873:       break;
  874: 
  875:     case SET_NO:
  876:       NoCommand(ac, av, &ecp->options, gConfList);
  877:       break;
  878: 
  879:     default:
  880:       assert(0);
  881:   }
  882:   return(0);
  883: }
  884: 
  885: /*
  886:  * EcpFindType()
  887:  */
  888: 
  889: static EncType
  890: EcpFindType(int type, int *indexp)
  891: {
  892:   unsigned k;
  893: 
  894:   for (k = 0; k < ECP_NUM_PROTOS; k++)
  895:     if (gEncTypes[k]->type == type)
  896:     {
  897:       if (indexp)
  898: 	*indexp = k;
  899:       return(gEncTypes[k]);
  900:     }
  901:   return(NULL);
  902: }
  903: 
  904: /*
  905:  * EcpTypeName()
  906:  */
  907: 
  908: static const char *
  909: EcpTypeName(int type)
  910: {
  911:   const struct ecpname	*p;
  912: 
  913:   for (p = gEcpTypeNames; p->name; p++)
  914:     if (p->type == type)
  915:       return(p->name);
  916:   return("UNKNOWN");
  917: }

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