Annotation of embedaddon/mpd/src/ipv6cp.c, revision 1.1.1.2
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:
1.1.1.2 ! misho 67: static int Ipv6cpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 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},
1.1.1.2 ! misho 87: { NULL, NULL, NULL, NULL, 0, NULL },
1.1 misho 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 },
1.1.1.2 ! misho 97: { NULL, 0, 0, 0, 0 }
1.1 misho 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,
1.1.1.2 ! misho 127: NULL, NULL, NULL, NULL
1.1 misho 128: };
129:
130: /*
131: * Ipv6cpStat()
132: */
133:
134: int
1.1.1.2 ! misho 135: Ipv6cpStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 136: {
137: Ipv6cpState const ipv6cp = &ctx->bund->ipv6cp;
138: Fsm fp = &ipv6cp->fsm;
139:
1.1.1.2 ! misho 140: (void)ac;
! 141: (void)av;
! 142: (void)arg;
! 143:
1.1 misho 144: Printf("[%s] %s [%s]\r\n", Pref(fp), Fsm(fp), FsmStateName(fp->state));
145: Printf("Interface identificators:\r\n");
146: Printf("\tSelf: %02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
147: ipv6cp->myintid[0], ipv6cp->myintid[1], ipv6cp->myintid[2], ipv6cp->myintid[3],
148: ipv6cp->myintid[4], ipv6cp->myintid[5], ipv6cp->myintid[6], ipv6cp->myintid[7]);
149: Printf("\tPeer: %02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
150: ipv6cp->hisintid[0], ipv6cp->hisintid[1], ipv6cp->hisintid[2], ipv6cp->hisintid[3],
151: ipv6cp->hisintid[4], ipv6cp->hisintid[5], ipv6cp->hisintid[6], ipv6cp->hisintid[7]);
152: Printf("IPV6CP Options:\r\n");
153: OptStat(ctx, &ipv6cp->conf.options, gConfList);
154:
155: return(0);
156: }
157:
158: /*
159: * CreateInterfaceID()
160: */
161:
162: void
163: CreateInterfaceID(u_char *intid, int r)
164: {
165: struct sockaddr_dl hwaddr;
166: u_char *ether;
167:
168: if (!r) {
169: if (!GetEther(NULL, &hwaddr)) {
170: ether = (u_char *) LLADDR(&hwaddr);
171: intid[0]=ether[0] ^ 0x02; /* reverse the u/l bit*/
172: intid[1]=ether[1];
173: intid[2]=ether[2];
174: intid[3]=0xff;
175: intid[4]=0xfe;
176: intid[5]=ether[3];
177: intid[6]=ether[4];
178: intid[7]=ether[5];
179: return;
180: }
181: }
182:
183: srandomdev();
1.1.1.2 ! misho 184: ((u_int32_t*)(void*)intid)[0]=(((u_int32_t)random()) % 0xFFFFFFFF) + 1;
! 185: ((u_int32_t*)(void*)intid)[1]=(((u_int32_t)random()) % 0xFFFFFFFF) + 1;
1.1 misho 186: intid[0] &= 0xfd;
187:
188: }
189:
190: /*
191: * Ipv6cpInit()
192: */
193:
194: void
195: Ipv6cpInit(Bund b)
196: {
197: Ipv6cpState ipv6cp = &b->ipv6cp;
198:
199: /* Init state machine */
200: memset(ipv6cp, 0, sizeof(*ipv6cp));
201: FsmInit(&ipv6cp->fsm, &gIpv6cpFsmType, b);
202:
203: CreateInterfaceID(ipv6cp->myintid,0);
204:
205: }
206:
207: /*
208: * Ipv6cpInst()
209: */
210:
211: void
212: Ipv6cpInst(Bund b, Bund bt)
213: {
214: Ipv6cpState ipv6cp = &b->ipv6cp;
215:
216: /* Init state machine */
217: memcpy(ipv6cp, &bt->ipv6cp, sizeof(*ipv6cp));
218: FsmInst(&ipv6cp->fsm, &bt->ipv6cp.fsm, b);
219: }
220:
221: /*
222: * Ipv6cpConfigure()
223: */
224:
225: static void
226: Ipv6cpConfigure(Fsm fp)
227: {
228: Bund b = (Bund)fp->arg;
229: Ipv6cpState const ipv6cp = &b->ipv6cp;
230:
231: /* FSM stuff */
232: ipv6cp->peer_reject = 0;
233:
234: }
235:
236: /*
237: * Ipv6cpUnConfigure()
238: */
239:
240: static void
241: Ipv6cpUnConfigure(Fsm fp)
242: {
1.1.1.2 ! misho 243: (void)fp;
1.1 misho 244: }
245:
246: /*
247: * Ipv6cpBuildConfigReq()
248: */
249:
250: static u_char *
251: Ipv6cpBuildConfigReq(Fsm fp, u_char *cp)
252: {
253: Bund b = (Bund)fp->arg;
254: Ipv6cpState const ipv6cp = &b->ipv6cp;
255:
256: cp = FsmConfValue(cp, TY_INTIDENT, 8, ipv6cp->myintid);
257:
258: /* Done */
259:
260: return(cp);
261: }
262:
263: /*
264: * Ipv6cpLayerStart()
265: *
266: * Tell the lower layer (the bundle) that we need it
267: */
268:
269: static void
270: Ipv6cpLayerStart(Fsm fp)
271: {
272: BundNcpsStart((Bund)(fp->arg), NCP_IPV6CP);
273: }
274:
275: /*
276: * Ipv6cpLayerFinish()
277: *
278: * Tell the lower layer (the bundle) that we no longer need it
279: */
280:
281: static void
282: Ipv6cpLayerFinish(Fsm fp)
283: {
284: BundNcpsFinish((Bund)(fp->arg), NCP_IPV6CP);
285: }
286:
287: /*
288: * Ipv6cpLayerUp()
289: *
290: * Called when IPV6CP has reached the OPEN state
291: */
292:
293: static void
294: Ipv6cpLayerUp(Fsm fp)
295: {
296: Bund b = (Bund)fp->arg;
297: Ipv6cpState const ipv6cp = &b->ipv6cp;
298:
299: /* Report */
300: Log(fp->log, ("[%s] %02x%02x:%02x%02x:%02x%02x:%02x%02x -> %02x%02x:%02x%02x:%02x%02x:%02x%02x", b->name,
301: ipv6cp->myintid[0], ipv6cp->myintid[1], ipv6cp->myintid[2], ipv6cp->myintid[3],
302: ipv6cp->myintid[4], ipv6cp->myintid[5], ipv6cp->myintid[6], ipv6cp->myintid[7],
303: ipv6cp->hisintid[0], ipv6cp->hisintid[1], ipv6cp->hisintid[2], ipv6cp->hisintid[3],
304: ipv6cp->hisintid[4], ipv6cp->hisintid[5], ipv6cp->hisintid[6], ipv6cp->hisintid[7]));
305:
306: /* Enable IP packets in the PPP node */
307: b->pppConfig.bund.enableIPv6 = 1;
308: NgFuncSetConfig(b);
309:
310: BundNcpsJoin(b, NCP_IPV6CP);
311: }
312:
313: /*
314: * Ipv6cpLayerDown()
315: *
316: * Called when IPV6CP leaves the OPEN state
317: */
318:
319: static void
320: Ipv6cpLayerDown(Fsm fp)
321: {
322: Bund b = (Bund)fp->arg;
323:
324: BundNcpsLeave(b, NCP_IPV6CP);
325:
326: /* Turn off IP packets */
327: b->pppConfig.bund.enableIPv6 = 0;
328: NgFuncSetConfig(b);
329: }
330:
331: /*
332: * Ipv6cpUp()
333: */
334:
335: void
336: Ipv6cpUp(Bund b)
337: {
338: FsmUp(&b->ipv6cp.fsm);
339: }
340:
341: /*
342: * Ipv6cpDown()
343: */
344:
345: void
346: Ipv6cpDown(Bund b)
347: {
348: FsmDown(&b->ipv6cp.fsm);
349: }
350:
351: /*
352: * Ipv6cpOpen()
353: */
354:
355: void
356: Ipv6cpOpen(Bund b)
357: {
358: FsmOpen(&b->ipv6cp.fsm);
359: }
360:
361: /*
362: * Ipv6cpClose()
363: */
364:
365: void
366: Ipv6cpClose(Bund b)
367: {
368: FsmClose(&b->ipv6cp.fsm);
369: }
370:
371: /*
372: * Ipv6cpOpenCmd()
373: */
374:
375: int
376: Ipv6cpOpenCmd(Context ctx)
377: {
378: if (ctx->bund->tmpl)
379: Error("impossible to open template");
380: FsmOpen(&ctx->bund->ipv6cp.fsm);
381: return (0);
382: }
383:
384: /*
385: * Ipv6cpCloseCmd()
386: */
387:
388: int
389: Ipv6cpCloseCmd(Context ctx)
390: {
391: if (ctx->bund->tmpl)
392: Error("impossible to close template");
393: FsmClose(&ctx->bund->ipv6cp.fsm);
394: return (0);
395: }
396:
397: /*
398: * Ipv6cpFailure()
399: */
400:
401: static void
402: Ipv6cpFailure(Fsm fp, enum fsmfail reason)
403: {
404: Bund b = (Bund)fp->arg;
405: RecordLinkUpDownReason(b, NULL, 0, STR_PROTO_ERR, STR_IPV6CP_FAILED, FsmFailureStr(reason));
406: }
407:
408: /*
409: * Ipv6cpDecodeConfig()
410: */
411:
412: static void
413: Ipv6cpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
414: {
415: Bund b = (Bund)fp->arg;
416: Ipv6cpState const ipv6cp = &b->ipv6cp;
417: int k;
418:
419: /* Decode each config option */
420: for (k = 0; k < num; k++) {
421: FsmOption const opt = &list[k];
422: FsmOptInfo const oi = FsmFindOptInfo(gIpv6cpConfOpts, opt->type);
423:
424: if (!oi) {
425: Log(LG_IPV6CP, ("[%s] UNKNOWN[%d] len=%d", b->name, opt->type, opt->len));
426: if (mode == MODE_REQ)
427: FsmRej(fp, opt);
428: continue;
429: }
430: if (!oi->supported) {
431: Log(LG_IPV6CP, ("[%s] %s", b->name, oi->name));
432: if (mode == MODE_REQ) {
433: Log(LG_IPV6CP, ("[%s] Not supported", b->name));
434: FsmRej(fp, opt);
435: }
436: continue;
437: }
438: if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
439: Log(LG_IPV6CP, ("[%s] %s", b->name, oi->name));
440: if (mode == MODE_REQ) {
441: Log(LG_IPV6CP, ("[%s] bogus len=%d min=%d max=%d", b->name, opt->len, oi->minLen + 2, oi->maxLen + 2));
442: FsmRej(fp, opt);
443: }
444: continue;
445: }
446: switch (opt->type) {
447: case TY_INTIDENT:
448: {
449: Log(LG_IPV6CP2, ("[%s] %s %02x%02x:%02x%02x:%02x%02x:%02x%02x", b->name, oi->name,
450: opt->data[0], opt->data[1], opt->data[2], opt->data[3],
451: opt->data[4], opt->data[5], opt->data[6], opt->data[7]));
452: switch (mode) {
1.1.1.2 ! misho 453: u_int32_t *ui32p;
1.1 misho 454: case MODE_REQ:
1.1.1.2 ! misho 455: ui32p = (u_int32_t *)(void *)opt->data;
! 456: if ((ui32p[0]==0) && (ui32p[1]==0)) {
1.1 misho 457: Log(LG_IPV6CP2, ("[%s] Empty INTIDENT, propose our.", b->name));
458: CreateInterfaceID(ipv6cp->hisintid, 1);
459: memcpy(opt->data, ipv6cp->hisintid, 8);
460: FsmNak(fp, opt);
461: } else if (bcmp(opt->data, ipv6cp->myintid, 8) == 0) {
462: Log(LG_IPV6CP2, ("[%s] Duplicate INTIDENT, generate and propose other.", b->name));
463: CreateInterfaceID(ipv6cp->hisintid, 1);
464: memcpy(opt->data, ipv6cp->hisintid, 8);
465: FsmNak(fp, opt);
466: } else {
467: Log(LG_IPV6CP2, ("[%s] It's OK.", b->name));
468: memcpy(ipv6cp->hisintid, opt->data, 8);
469: FsmAck(fp, opt);
470: }
471: break;
472: case MODE_NAK:
473: Log(LG_IPV6CP2, ("[%s] I agree to get this to myself.", b->name));
474: memcpy(ipv6cp->myintid, opt->data, 8);
475: break;
476: case MODE_REJ:
477: IPV6CP_PEER_REJ(ipv6cp, opt->type);
478: break;
479: }
480: }
481: break;
482:
483: default:
484: assert(0);
485: }
486: }
487: }
488:
489: /*
490: * Ipv6cpInput()
491: *
492: * Deal with an incoming IPV6CP packet
493: */
494:
495: void
496: Ipv6cpInput(Bund b, Mbuf bp)
497: {
498: FsmInput(&b->ipv6cp.fsm, bp);
499: }
500:
501: /*
502: * Ipv6cpSetCommand()
503: */
504:
505: static int
1.1.1.2 ! misho 506: Ipv6cpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 507: {
508: Ipv6cpState const ipv6cp = &ctx->bund->ipv6cp;
509:
510: if (ac == 0)
511: return(-1);
512: switch ((intptr_t)arg) {
513: case SET_ACCEPT:
514: AcceptCommand(ac, av, &ipv6cp->conf.options, gConfList);
515: break;
516:
517: case SET_DENY:
518: DenyCommand(ac, av, &ipv6cp->conf.options, gConfList);
519: break;
520:
521: case SET_ENABLE:
522: EnableCommand(ac, av, &ipv6cp->conf.options, gConfList);
523: break;
524:
525: case SET_DISABLE:
526: DisableCommand(ac, av, &ipv6cp->conf.options, gConfList);
527: break;
528:
529: case SET_YES:
530: YesCommand(ac, av, &ipv6cp->conf.options, gConfList);
531: break;
532:
533: case SET_NO:
534: NoCommand(ac, av, &ipv6cp->conf.options, gConfList);
535: break;
536:
537: default:
538: assert(0);
539: }
540: return(0);
541: }
542:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>