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

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