File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ipv6cp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:44:29 2013 UTC (10 years, 11 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, v5_7p0, v5_7, v5_6, HEAD
5.7

    1: 
    2: /*
    3:  * ipv6cp.c
    4:  *
    5:  * Written by Alexander Motin <mav@FreeBSD.org>
    6:  */
    7: 
    8: #include "ppp.h"
    9: #include "ipv6cp.h"
   10: #include "fsm.h"
   11: #include "ip.h"
   12: #include "iface.h"
   13: #include "msg.h"
   14: #include "ngfunc.h"
   15: #include "util.h"
   16: 
   17: #include <netgraph.h>
   18: #include <sys/mbuf.h>
   19: 
   20: /*
   21:  * DEFINITIONS
   22:  */
   23: 
   24:   #define IPV6CP_KNOWN_CODES	(   (1 << CODE_CONFIGREQ)	\
   25: 				  | (1 << CODE_CONFIGACK)	\
   26: 				  | (1 << CODE_CONFIGNAK)	\
   27: 				  | (1 << CODE_CONFIGREJ)	\
   28: 				  | (1 << CODE_TERMREQ)		\
   29: 				  | (1 << CODE_TERMACK)		\
   30: 				  | (1 << CODE_CODEREJ)		)
   31: 
   32:   #define TY_INTIDENT		1
   33:   #define TY_COMPPROTO		2
   34: 
   35:   #define IPV6CP_REJECTED(p,x)	((p)->peer_reject & (1<<(x)))
   36:   #define IPV6CP_PEER_REJ(p,x)	do{(p)->peer_reject |= (1<<(x));}while(0)
   37: 
   38:   #define IPV6CP_VJCOMP_MIN_MAXCHAN	(NG_VJC_MIN_CHANNELS - 1)
   39:   #define IPV6CP_VJCOMP_MAX_MAXCHAN	(NG_VJC_MAX_CHANNELS - 1)
   40:   #define IPV6CP_VJCOMP_DEFAULT_MAXCHAN	IPV6CP_VJCOMP_MAX_MAXCHAN
   41: 
   42:   /* Set menu options */
   43:   enum {
   44:     SET_ENABLE,
   45:     SET_DISABLE,
   46:     SET_ACCEPT,
   47:     SET_DENY,
   48:     SET_YES,
   49:     SET_NO
   50:   };
   51: 
   52: /*
   53:  * INTERNAL FUNCTIONS
   54:  */
   55: 
   56:   static void	Ipv6cpConfigure(Fsm fp);
   57:   static void	Ipv6cpUnConfigure(Fsm fp);
   58: 
   59:   static u_char	*Ipv6cpBuildConfigReq(Fsm fp, u_char *cp);
   60:   static void	Ipv6cpDecodeConfig(Fsm fp, FsmOption list, int num, int mode);
   61:   static void	Ipv6cpLayerStart(Fsm fp);
   62:   static void	Ipv6cpLayerFinish(Fsm fp);
   63:   static void	Ipv6cpLayerUp(Fsm fp);
   64:   static void	Ipv6cpLayerDown(Fsm fp);
   65:   static void	Ipv6cpFailure(Fsm fp, enum fsmfail reason);
   66: 
   67:   static int	Ipv6cpSetCommand(Context ctx, int ac, char *av[], void *arg);
   68: 
   69:   void 		CreateInterfaceID(u_char *intid, int random);
   70: /*
   71:  * GLOBAL VARIABLES
   72:  */
   73: 
   74:   const struct cmdtab Ipv6cpSetCmds[] = {
   75:     { "enable [opt ...]",		"Enable option",
   76: 	Ipv6cpSetCommand, NULL, 2, (void *) SET_ENABLE},
   77:     { "disable [opt ...]",		"Disable option",
   78: 	Ipv6cpSetCommand, NULL, 2, (void *) SET_DISABLE},
   79:     { "accept [opt ...]",		"Accept option",
   80: 	Ipv6cpSetCommand, NULL, 2, (void *) SET_ACCEPT},
   81:     { "deny [opt ...]",			"Deny option",
   82: 	Ipv6cpSetCommand, NULL, 2, (void *) SET_DENY},
   83:     { "yes [opt ...]",			"Enable and accept option",
   84: 	Ipv6cpSetCommand, NULL, 2, (void *) SET_YES},
   85:     { "no [opt ...]",			"Disable and deny option",
   86: 	Ipv6cpSetCommand, NULL, 2, (void *) SET_NO},
   87:     { NULL },
   88:   };
   89: 
   90: /*
   91:  * INTERNAL VARIABLES
   92:  */
   93: 
   94:   static const struct fsmoptinfo	gIpv6cpConfOpts[] = {
   95:     { "INTIDENT",	TY_INTIDENT,		8, 8, TRUE },
   96:     { "COMPPROTO",	TY_COMPPROTO,		4, 4, FALSE },
   97:     { NULL }
   98:   };
   99: 
  100:   static const struct confinfo gConfList[] = {
  101: /*    { 1,	IPV6CP_CONF_VJCOMP,	"vjcomp"	},*/
  102:     { 0,	0,			NULL		},
  103:   };
  104: 
  105:   static const struct fsmtype gIpv6cpFsmType = {
  106:     "IPV6CP",
  107:     PROTO_IPV6CP,
  108:     IPV6CP_KNOWN_CODES,
  109:     FALSE,
  110:     LG_IPV6CP, LG_IPV6CP2,
  111:     NULL,
  112:     Ipv6cpLayerUp,
  113:     Ipv6cpLayerDown,
  114:     Ipv6cpLayerStart,
  115:     Ipv6cpLayerFinish,
  116:     Ipv6cpBuildConfigReq,
  117:     Ipv6cpDecodeConfig,
  118:     Ipv6cpConfigure,
  119:     Ipv6cpUnConfigure,
  120:     NULL,
  121:     NULL,
  122:     NULL,
  123:     NULL,
  124:     Ipv6cpFailure,
  125:     NULL,
  126:     NULL,
  127:     NULL,
  128:   };
  129: 
  130: /*
  131:  * Ipv6cpStat()
  132:  */
  133: 
  134: int
  135: Ipv6cpStat(Context ctx, int ac, char *av[], void *arg)
  136: {
  137:   Ipv6cpState		const ipv6cp = &ctx->bund->ipv6cp;
  138:   Fsm			fp = &ipv6cp->fsm;
  139: 
  140:   Printf("[%s] %s [%s]\r\n", Pref(fp), Fsm(fp), FsmStateName(fp->state));
  141:   Printf("Interface identificators:\r\n");
  142:   Printf("\tSelf: %02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
  143:     ipv6cp->myintid[0], ipv6cp->myintid[1], ipv6cp->myintid[2], ipv6cp->myintid[3],
  144:     ipv6cp->myintid[4], ipv6cp->myintid[5], ipv6cp->myintid[6], ipv6cp->myintid[7]);
  145:   Printf("\tPeer: %02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
  146:     ipv6cp->hisintid[0], ipv6cp->hisintid[1], ipv6cp->hisintid[2], ipv6cp->hisintid[3],
  147:     ipv6cp->hisintid[4], ipv6cp->hisintid[5], ipv6cp->hisintid[6], ipv6cp->hisintid[7]);
  148:   Printf("IPV6CP Options:\r\n");
  149:   OptStat(ctx, &ipv6cp->conf.options, gConfList);
  150: 
  151:   return(0);
  152: }
  153: 
  154: /*
  155:  * CreateInterfaceID()
  156:  */
  157: 
  158: void
  159: CreateInterfaceID(u_char *intid, int r)
  160: {
  161:     struct sockaddr_dl hwaddr;
  162:     u_char	*ether;
  163: 
  164:     if (!r) {
  165: 	if (!GetEther(NULL, &hwaddr)) {
  166: 	    ether = (u_char *) LLADDR(&hwaddr);
  167: 	    intid[0]=ether[0] ^ 0x02; /* reverse the u/l bit*/
  168: 	    intid[1]=ether[1];
  169: 	    intid[2]=ether[2];
  170: 	    intid[3]=0xff;
  171: 	    intid[4]=0xfe;
  172: 	    intid[5]=ether[3];
  173: 	    intid[6]=ether[4];
  174: 	    intid[7]=ether[5];
  175: 	    return;
  176: 	}
  177:     }
  178: 
  179:     srandomdev();
  180:     ((u_int32_t*)intid)[0]=(((u_int32_t)random()) % 0xFFFFFFFF) + 1;
  181:     ((u_int32_t*)intid)[1]=(((u_int32_t)random()) % 0xFFFFFFFF) + 1;
  182:     intid[0] &= 0xfd;
  183: 
  184: }
  185: 
  186: /*
  187:  * Ipv6cpInit()
  188:  */
  189: 
  190: void
  191: Ipv6cpInit(Bund b)
  192: {
  193:   Ipv6cpState	ipv6cp = &b->ipv6cp;
  194: 
  195:   /* Init state machine */
  196:   memset(ipv6cp, 0, sizeof(*ipv6cp));
  197:   FsmInit(&ipv6cp->fsm, &gIpv6cpFsmType, b);
  198: 
  199:   CreateInterfaceID(ipv6cp->myintid,0);
  200: 
  201: }
  202: 
  203: /*
  204:  * Ipv6cpInst()
  205:  */
  206: 
  207: void
  208: Ipv6cpInst(Bund b, Bund bt)
  209: {
  210:   Ipv6cpState	ipv6cp = &b->ipv6cp;
  211: 
  212:   /* Init state machine */
  213:   memcpy(ipv6cp, &bt->ipv6cp, sizeof(*ipv6cp));
  214:   FsmInst(&ipv6cp->fsm, &bt->ipv6cp.fsm, b);
  215: }
  216: 
  217: /*
  218:  * Ipv6cpConfigure()
  219:  */
  220: 
  221: static void
  222: Ipv6cpConfigure(Fsm fp)
  223: {
  224:     Bund 	b = (Bund)fp->arg;
  225:   Ipv6cpState	const ipv6cp = &b->ipv6cp;
  226: 
  227:   /* FSM stuff */
  228:   ipv6cp->peer_reject = 0;
  229: 
  230: }
  231: 
  232: /*
  233:  * Ipv6cpUnConfigure()
  234:  */
  235: 
  236: static void
  237: Ipv6cpUnConfigure(Fsm fp)
  238: {
  239: }
  240: 
  241: /*
  242:  * Ipv6cpBuildConfigReq()
  243:  */
  244: 
  245: static u_char *
  246: Ipv6cpBuildConfigReq(Fsm fp, u_char *cp)
  247: {
  248:     Bund 	b = (Bund)fp->arg;
  249:   Ipv6cpState	const ipv6cp = &b->ipv6cp;
  250: 
  251:   cp = FsmConfValue(cp, TY_INTIDENT, 8, ipv6cp->myintid);
  252: 
  253: /* Done */
  254: 
  255:   return(cp);
  256: }
  257: 
  258: /*
  259:  * Ipv6cpLayerStart()
  260:  *
  261:  * Tell the lower layer (the bundle) that we need it
  262:  */
  263: 
  264: static void
  265: Ipv6cpLayerStart(Fsm fp)
  266: {
  267:     BundNcpsStart((Bund)(fp->arg), NCP_IPV6CP);
  268: }
  269: 
  270: /*
  271:  * Ipv6cpLayerFinish()
  272:  *
  273:  * Tell the lower layer (the bundle) that we no longer need it
  274:  */
  275: 
  276: static void
  277: Ipv6cpLayerFinish(Fsm fp)
  278: {
  279:     BundNcpsFinish((Bund)(fp->arg), NCP_IPV6CP);
  280: }
  281: 
  282: /*
  283:  * Ipv6cpLayerUp()
  284:  *
  285:  * Called when IPV6CP has reached the OPEN state
  286:  */
  287: 
  288: static void
  289: Ipv6cpLayerUp(Fsm fp)
  290: {
  291:     Bund 	b = (Bund)fp->arg;
  292:     Ipv6cpState		const ipv6cp = &b->ipv6cp;
  293: 
  294:     /* Report */
  295:     Log(fp->log, ("[%s]   %02x%02x:%02x%02x:%02x%02x:%02x%02x -> %02x%02x:%02x%02x:%02x%02x:%02x%02x", b->name,
  296: 	ipv6cp->myintid[0], ipv6cp->myintid[1], ipv6cp->myintid[2], ipv6cp->myintid[3],
  297: 	ipv6cp->myintid[4], ipv6cp->myintid[5], ipv6cp->myintid[6], ipv6cp->myintid[7],
  298: 	ipv6cp->hisintid[0], ipv6cp->hisintid[1], ipv6cp->hisintid[2], ipv6cp->hisintid[3],
  299: 	ipv6cp->hisintid[4], ipv6cp->hisintid[5], ipv6cp->hisintid[6], ipv6cp->hisintid[7]));
  300: 
  301:     /* Enable IP packets in the PPP node */
  302:     b->pppConfig.bund.enableIPv6 = 1;
  303:     NgFuncSetConfig(b);
  304: 
  305:     BundNcpsJoin(b, NCP_IPV6CP);
  306: }
  307: 
  308: /*
  309:  * Ipv6cpLayerDown()
  310:  *
  311:  * Called when IPV6CP leaves the OPEN state
  312:  */
  313: 
  314: static void
  315: Ipv6cpLayerDown(Fsm fp)
  316: {
  317:     Bund 	b = (Bund)fp->arg;
  318: 
  319:     BundNcpsLeave(b, NCP_IPV6CP);
  320: 
  321:     /* Turn off IP packets */
  322:     b->pppConfig.bund.enableIPv6 = 0;
  323:     NgFuncSetConfig(b);
  324: }
  325: 
  326: /*
  327:  * Ipv6cpUp()
  328:  */
  329: 
  330: void
  331: Ipv6cpUp(Bund b)
  332: {
  333:   FsmUp(&b->ipv6cp.fsm);
  334: }
  335: 
  336: /*
  337:  * Ipv6cpDown()
  338:  */
  339: 
  340: void
  341: Ipv6cpDown(Bund b)
  342: {
  343:   FsmDown(&b->ipv6cp.fsm);
  344: }
  345: 
  346: /*
  347:  * Ipv6cpOpen()
  348:  */
  349: 
  350: void
  351: Ipv6cpOpen(Bund b)
  352: {
  353:   FsmOpen(&b->ipv6cp.fsm);
  354: }
  355: 
  356: /*
  357:  * Ipv6cpClose()
  358:  */
  359: 
  360: void
  361: Ipv6cpClose(Bund b)
  362: {
  363:   FsmClose(&b->ipv6cp.fsm);
  364: }
  365: 
  366: /*
  367:  * Ipv6cpOpenCmd()
  368:  */
  369: 
  370: int
  371: Ipv6cpOpenCmd(Context ctx)
  372: {
  373:     if (ctx->bund->tmpl)
  374: 	Error("impossible to open template");
  375:     FsmOpen(&ctx->bund->ipv6cp.fsm);
  376:     return (0);
  377: }
  378: 
  379: /*
  380:  * Ipv6cpCloseCmd()
  381:  */
  382: 
  383: int
  384: Ipv6cpCloseCmd(Context ctx)
  385: {
  386:     if (ctx->bund->tmpl)
  387: 	Error("impossible to close template");
  388:     FsmClose(&ctx->bund->ipv6cp.fsm);
  389:     return (0);
  390: }
  391: 
  392: /*
  393:  * Ipv6cpFailure()
  394:  */
  395: 
  396: static void
  397: Ipv6cpFailure(Fsm fp, enum fsmfail reason)
  398: {
  399:     Bund 	b = (Bund)fp->arg;
  400:     RecordLinkUpDownReason(b, NULL, 0, STR_PROTO_ERR, STR_IPV6CP_FAILED, FsmFailureStr(reason));
  401: }
  402: 
  403: /*
  404:  * Ipv6cpDecodeConfig()
  405:  */
  406: 
  407: static void
  408: Ipv6cpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
  409: {
  410:     Bund 	b = (Bund)fp->arg;
  411:   Ipv6cpState		const ipv6cp = &b->ipv6cp;
  412:   int			k;
  413: 
  414:   /* Decode each config option */
  415:   for (k = 0; k < num; k++) {
  416:     FsmOption	const opt = &list[k];
  417:     FsmOptInfo	const oi = FsmFindOptInfo(gIpv6cpConfOpts, opt->type);
  418: 
  419:     if (!oi) {
  420:       Log(LG_IPV6CP, ("[%s]   UNKNOWN[%d] len=%d", b->name, opt->type, opt->len));
  421:       if (mode == MODE_REQ)
  422: 	FsmRej(fp, opt);
  423:       continue;
  424:     }
  425:     if (!oi->supported) {
  426:       Log(LG_IPV6CP, ("[%s]   %s", b->name, oi->name));
  427:       if (mode == MODE_REQ) {
  428: 	Log(LG_IPV6CP, ("[%s]     Not supported", b->name));
  429: 	FsmRej(fp, opt);
  430:       }
  431:       continue;
  432:     }
  433:     if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
  434:       Log(LG_IPV6CP, ("[%s]   %s", b->name, oi->name));
  435:       if (mode == MODE_REQ) {
  436: 	Log(LG_IPV6CP, ("[%s]     bogus len=%d min=%d max=%d", b->name, opt->len, oi->minLen + 2, oi->maxLen + 2));
  437: 	FsmRej(fp, opt);
  438:       }
  439:       continue;
  440:     }
  441:     switch (opt->type) {
  442:       case TY_INTIDENT:
  443: 	{
  444: 	  Log(LG_IPV6CP2, ("[%s]   %s %02x%02x:%02x%02x:%02x%02x:%02x%02x", b->name, oi->name,
  445: 	    opt->data[0], opt->data[1], opt->data[2], opt->data[3],
  446: 	    opt->data[4], opt->data[5], opt->data[6], opt->data[7]));
  447: 	  switch (mode) {
  448: 	    case MODE_REQ:
  449: 	      if ((((u_int32_t*)opt->data)[0]==0) && (((u_int32_t*)opt->data)[1]==0)) {
  450: 		Log(LG_IPV6CP2, ("[%s]     Empty INTIDENT, propose our.", b->name));
  451: 		CreateInterfaceID(ipv6cp->hisintid, 1);
  452: 	        memcpy(opt->data, ipv6cp->hisintid, 8);
  453: 	        FsmNak(fp, opt);
  454: 	      } else if (bcmp(opt->data, ipv6cp->myintid, 8) == 0) {
  455: 		Log(LG_IPV6CP2, ("[%s]     Duplicate INTIDENT, generate and propose other.", b->name));
  456: 		CreateInterfaceID(ipv6cp->hisintid, 1);
  457: 	        memcpy(opt->data, ipv6cp->hisintid, 8);
  458: 	        FsmNak(fp, opt);
  459: 	      } else {
  460: 		Log(LG_IPV6CP2, ("[%s]     It's OK.", b->name));
  461: 	        memcpy(ipv6cp->hisintid, opt->data, 8);
  462: 	        FsmAck(fp, opt);
  463: 	      }
  464: 	      break;
  465: 	    case MODE_NAK:
  466: 		Log(LG_IPV6CP2, ("[%s]     I agree to get this to myself.", b->name));
  467: 	        memcpy(ipv6cp->myintid, opt->data, 8);
  468: 	      break;
  469: 	    case MODE_REJ:
  470: 	      IPV6CP_PEER_REJ(ipv6cp, opt->type);
  471: 	      break;
  472: 	  }
  473: 	}
  474: 	break;
  475: 
  476:       default:
  477: 	assert(0);
  478:     }
  479:   }
  480: }
  481: 
  482: /*
  483:  * Ipv6cpInput()
  484:  *
  485:  * Deal with an incoming IPV6CP packet
  486:  */
  487: 
  488: void
  489: Ipv6cpInput(Bund b, Mbuf bp)
  490: {
  491:   FsmInput(&b->ipv6cp.fsm, bp);
  492: }
  493: 
  494: /*
  495:  * Ipv6cpSetCommand()
  496:  */
  497: 
  498: static int
  499: Ipv6cpSetCommand(Context ctx, int ac, char *av[], void *arg)
  500: {
  501:   Ipv6cpState		const ipv6cp = &ctx->bund->ipv6cp;
  502: 
  503:   if (ac == 0)
  504:     return(-1);
  505:   switch ((intptr_t)arg) {
  506:     case SET_ACCEPT:
  507:       AcceptCommand(ac, av, &ipv6cp->conf.options, gConfList);
  508:       break;
  509: 
  510:     case SET_DENY:
  511:       DenyCommand(ac, av, &ipv6cp->conf.options, gConfList);
  512:       break;
  513: 
  514:     case SET_ENABLE:
  515:       EnableCommand(ac, av, &ipv6cp->conf.options, gConfList);
  516:       break;
  517: 
  518:     case SET_DISABLE:
  519:       DisableCommand(ac, av, &ipv6cp->conf.options, gConfList);
  520:       break;
  521: 
  522:     case SET_YES:
  523:       YesCommand(ac, av, &ipv6cp->conf.options, gConfList);
  524:       break;
  525: 
  526:     case SET_NO:
  527:       NoCommand(ac, av, &ipv6cp->conf.options, gConfList);
  528:       break;
  529: 
  530:     default:
  531:       assert(0);
  532:   }
  533:   return(0);
  534: }
  535: 

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