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