Annotation of embedaddon/mpd/src/ipv6cp.c, revision 1.1
1.1 ! misho 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>