Annotation of embedaddon/mpd/src/ecp.c, revision 1.1.1.1
1.1 misho 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;
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 %d 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: bundname++;
339: id = strtol(bundname, &rest, 10);
340: if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
341: Log(LG_ERR, ("ECP: Packet from unexisting bundle \"%s\"",
342: bundname));
343: mbfree(bp);
344: continue;
345: }
346:
347: b = gBundles[id];
348:
349: /* Packet requiring compression */
350: if (bundname[0] == 'e') {
351: bp = EcpDataOutput(b, bp);
352: } else {
353: /* Packet requiring decompression */
354: bp = EcpDataInput(b, bp);
355: }
356: if (bp)
357: NgFuncWriteFrame(gEcpDsock, naddr.sg_data, b->name, bp);
358: }
359: }
360:
361:
362: /*
363: * EcpDataOutput()
364: *
365: * Encrypt a frame. Consumes the original packet.
366: */
367:
368: Mbuf
369: EcpDataOutput(Bund b, Mbuf plain)
370: {
371: EcpState const ecp = &b->ecp;
372: Mbuf cypher;
373:
374: LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
375:
376: /* Encrypt packet */
377:
378: if ((!ecp->xmit) || (!ecp->xmit->Encrypt))
379: {
380: Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
381: mbfree(plain);
382: return(NULL);
383: }
384: cypher = (*ecp->xmit->Encrypt)(b, plain);
385: LogDumpBp(LG_FRAME, cypher, "[%s] %s: xmit cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
386:
387: /* Return result, with new protocol number */
388:
389: return(cypher);
390: }
391:
392: /*
393: * EcpDataInput()
394: *
395: * Decrypt incoming packet. If packet got garbled, return NULL.
396: * In any case, we consume the packet passed to us.
397: */
398:
399: Mbuf
400: EcpDataInput(Bund b, Mbuf cypher)
401: {
402: EcpState const ecp = &b->ecp;
403: Mbuf plain;
404:
405: LogDumpBp(LG_FRAME, cypher, "[%s] %s: recv cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
406:
407: /* Decrypt packet */
408:
409: if ((!ecp->recv) || (!ecp->recv->Decrypt))
410: {
411: Log(LG_ERR, ("[%s] %s: no encryption for recv", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
412: mbfree(cypher);
413: return(NULL);
414: }
415:
416: plain = (*ecp->recv->Decrypt)(b, cypher);
417:
418: /* Decrypted ok? */
419:
420: if (plain == NULL)
421: {
422: Log(LG_ECP, ("[%s] %s: decryption failed", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
423: return(NULL);
424: }
425:
426: LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
427: /* Done */
428:
429: return(plain);
430: }
431:
432: /*
433: * EcpUp()
434: */
435:
436: void
437: EcpUp(Bund b)
438: {
439: FsmUp(&b->ecp.fsm);
440: }
441:
442: /*
443: * EcpDown()
444: */
445:
446: void
447: EcpDown(Bund b)
448: {
449: FsmDown(&b->ecp.fsm);
450: }
451:
452: /*
453: * EcpOpen()
454: */
455:
456: void
457: EcpOpen(Bund b)
458: {
459: FsmOpen(&b->ecp.fsm);
460: }
461:
462: /*
463: * EcpClose()
464: */
465:
466: void
467: EcpClose(Bund b)
468: {
469: FsmClose(&b->ecp.fsm);
470: }
471:
472: /*
473: * EcpOpenCmd()
474: */
475:
476: int
477: EcpOpenCmd(Context ctx)
478: {
479: if (ctx->bund->tmpl)
480: Error("impossible to open template");
481: FsmOpen(&ctx->bund->ecp.fsm);
482: return (0);
483: }
484:
485: /*
486: * EcpCloseCmd()
487: */
488:
489: int
490: EcpCloseCmd(Context ctx)
491: {
492: if (ctx->bund->tmpl)
493: Error("impossible to close template");
494: FsmClose(&ctx->bund->ecp.fsm);
495: return (0);
496: }
497:
498: /*
499: * EcpFailure()
500: *
501: * This is fatal to the entire link if encryption is required.
502: */
503:
504: static void
505: EcpFailure(Fsm fp, enum fsmfail reason)
506: {
507: Bund b = (Bund)fp->arg;
508: if (Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD)) {
509: FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
510: FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
511: }
512: }
513:
514: /*
515: * EcpStat()
516: */
517:
518: int
519: EcpStat(Context ctx, int ac, char *av[], void *arg)
520: {
521: EcpState const ecp = &ctx->bund->ecp;
522:
523: Printf("[%s] %s [%s]\r\n", Pref(&ecp->fsm), Fsm(&ecp->fsm), FsmStateName(ecp->fsm.state));
524: Printf("Enabled protocols:\r\n");
525: OptStat(ctx, &ecp->options, gConfList);
526: Printf("Outgoing encryption:\r\n");
527: Printf("\tProto\t: %s\r\n", ecp->xmit ? ecp->xmit->name : "none");
528: if (ecp->xmit && ecp->xmit->Stat)
529: ecp->xmit->Stat(ctx, ECP_DIR_XMIT);
530: Printf("\tResets\t: %d\r\n", ecp->xmit_resets);
531: Printf("Incoming decryption:\r\n");
532: Printf("\tProto\t: %s\r\n", ecp->recv ? ecp->recv->name : "none");
533: if (ecp->recv && ecp->recv->Stat)
534: ecp->recv->Stat(ctx, ECP_DIR_RECV);
535: Printf("\tResets\t: %d\r\n", ecp->recv_resets);
536: return(0);
537: }
538:
539: /*
540: * EcpSendResetReq()
541: */
542:
543: void
544: EcpSendResetReq(Fsm fp)
545: {
546: Bund b = (Bund)fp->arg;
547: EcpState const ecp = &b->ecp;
548: EncType const et = ecp->recv;
549: Mbuf bp = NULL;
550:
551: assert(et);
552: ecp->recv_resets++;
553: if (et->SendResetReq)
554: bp = (*et->SendResetReq)(b);
555: Log(LG_ECP, ("[%s] %s: SendResetReq", Pref(fp), Fsm(fp)));
556: FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
557: }
558:
559: /*
560: * EcpRecvResetReq()
561: */
562:
563: void
564: EcpRecvResetReq(Fsm fp, int id, Mbuf bp)
565: {
566: Bund b = (Bund)fp->arg;
567: EcpState const ecp = &b->ecp;
568: EncType const et = ecp->xmit;
569:
570: ecp->xmit_resets++;
571: bp = (et && et->RecvResetReq) ? (*et->RecvResetReq)(b, id, bp) : NULL;
572: Log(fp->log, ("[%s] %s: SendResetAck", Pref(fp), Fsm(fp)));
573: FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
574: }
575:
576: /*
577: * EcpRecvResetAck()
578: */
579:
580: static void
581: EcpRecvResetAck(Fsm fp, int id, Mbuf bp)
582: {
583: Bund b = (Bund)fp->arg;
584: EcpState const ecp = &b->ecp;
585: EncType const et = ecp->recv;
586:
587: if (et && et->RecvResetAck)
588: (*et->RecvResetAck)(b, id, bp);
589: }
590:
591: /*
592: * EcpInput()
593: */
594:
595: void
596: EcpInput(Bund b, Mbuf bp)
597: {
598: FsmInput(&b->ecp.fsm, bp);
599: }
600:
601: /*
602: * EcpBuildConfigReq()
603: */
604:
605: static u_char *
606: EcpBuildConfigReq(Fsm fp, u_char *cp)
607: {
608: Bund b = (Bund)fp->arg;
609: EcpState const ecp = &b->ecp;
610: int type;
611:
612: /* Put in all options that peer hasn't rejected */
613:
614: for (ecp->xmit = NULL, type = 0; type < ECP_NUM_PROTOS; type++)
615: {
616: EncType const et = gEncTypes[type];
617:
618: if (Enabled(&ecp->options, type) && !ECP_PEER_REJECTED(ecp, type))
619: {
620: cp = (*et->BuildConfigReq)(b, cp);
621: if (!ecp->xmit)
622: ecp->xmit = et;
623: }
624: }
625: return(cp);
626: }
627:
628: /*
629: * EcpLayerUp()
630: *
631: * Called when ECP has reached the OPENED state
632: */
633:
634: static void
635: EcpLayerUp(Fsm fp)
636: {
637: Bund b = (Bund)fp->arg;
638: EcpState const ecp = &b->ecp;
639: struct ngm_connect cn;
640:
641: /* Initialize */
642: if (ecp->xmit && ecp->xmit->Init)
643: (*ecp->xmit->Init)(b, ECP_DIR_XMIT);
644: if (ecp->recv && ecp->recv->Init)
645: (*ecp->recv->Init)(b, ECP_DIR_RECV);
646:
647: if (ecp->recv && ecp->recv->Decrypt)
648: {
649: /* Connect a hook from the bpf node to our socket node */
650: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
651: snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
652: strcpy(cn.peerhook, NG_PPP_HOOK_DECRYPT);
653: if (NgSendMsg(gEcpCsock, ".:",
654: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
655: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
656: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
657: }
658: }
659: if (ecp->xmit && ecp->xmit->Encrypt)
660: {
661: /* Connect a hook from the bpf node to our socket node */
662: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
663: snprintf(cn.ourhook, sizeof(cn.ourhook), "e%d", b->id);
664: strcpy(cn.peerhook, NG_PPP_HOOK_ENCRYPT);
665: if (NgSendMsg(gEcpCsock, ".:",
666: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
667: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
668: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
669: }
670: }
671:
672: Log(LG_ECP, ("[%s] ECP: Encrypt using: %s", b->name, !ecp->xmit ? "none" : ecp->xmit->name));
673: Log(LG_ECP, ("[%s] ECP: Decrypt using: %s", b->name, !ecp->recv ? "none" : ecp->recv->name));
674:
675: /* Update PPP node config */
676: b->pppConfig.bund.enableEncryption = (ecp->xmit != NULL);
677: b->pppConfig.bund.enableDecryption = (ecp->recv != NULL);
678: NgFuncSetConfig(b);
679:
680: /* Update interface MTU */
681: BundUpdateParams(b);
682: }
683:
684: /*
685: * EcpLayerDown()
686: *
687: * Called when ECP leaves the OPENED state
688: */
689:
690: static void
691: EcpLayerDown(Fsm fp)
692: {
693: Bund b = (Bund)fp->arg;
694: EcpState const ecp = &b->ecp;
695:
696: /* Update PPP node config */
697: b->pppConfig.bund.enableEncryption = 0;
698: b->pppConfig.bund.enableDecryption = 0;
699: NgFuncSetConfig(b);
700:
701: /* Update interface MTU */
702: BundUpdateParams(b);
703:
704: if (ecp->xmit != NULL && ecp->xmit->Encrypt != NULL) {
705: char hook[NG_HOOKSIZ];
706: /* Disconnect hook. */
707: snprintf(hook, sizeof(hook), "e%d", b->id);
708: NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
709: }
710:
711: if (ecp->recv != NULL && ecp->recv->Decrypt != NULL) {
712: char hook[NG_HOOKSIZ];
713: /* Disconnect hook. */
714: snprintf(hook, sizeof(hook), "d%d", b->id);
715: NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
716: }
717:
718: if (ecp->xmit && ecp->xmit->Cleanup)
719: (ecp->xmit->Cleanup)(b, ECP_DIR_XMIT);
720: if (ecp->recv && ecp->recv->Cleanup)
721: (ecp->recv->Cleanup)(b, ECP_DIR_RECV);
722:
723: ecp->xmit_resets = 0;
724: ecp->recv_resets = 0;
725: }
726:
727: /*
728: * EcpDecodeConfig()
729: */
730:
731: static void
732: EcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
733: {
734: Bund b = (Bund)fp->arg;
735: EcpState const ecp = &b->ecp;
736: u_int ackSizeSave, rejSizeSave;
737: int k, rej;
738:
739: /* Forget our previous choice on new request */
740: if (mode == MODE_REQ)
741: ecp->recv = NULL;
742:
743: /* Decode each config option */
744:
745: for (k = 0; k < num; k++)
746: {
747: FsmOption const opt = &list[k];
748: int index;
749: EncType et;
750:
751: Log(LG_ECP, ("[%s] %s", b->name, EcpTypeName(opt->type)));
752: if ((et = EcpFindType(opt->type, &index)) == NULL)
753: {
754: if (mode == MODE_REQ)
755: {
756: Log(LG_ECP, ("[%s] Not supported", b->name));
757: FsmRej(fp, opt);
758: }
759: continue;
760: }
761: switch (mode)
762: {
763: case MODE_REQ:
764: ackSizeSave = gAckSize;
765: rejSizeSave = gRejSize;
766: rej = (!Acceptable(&ecp->options, index)
767: || ECP_SELF_REJECTED(ecp, index)
768: || (ecp->recv && ecp->recv != et));
769: if (rej)
770: {
771: (*et->DecodeConfig)(fp, opt, MODE_NOP);
772: FsmRej(fp, opt);
773: break;
774: }
775: (*et->DecodeConfig)(fp, opt, mode);
776: if (gRejSize != rejSizeSave) /* we rejected it */
777: {
778: ECP_SELF_REJ(ecp, index);
779: break;
780: }
781: if (gAckSize != ackSizeSave) /* we accepted it */
782: ecp->recv = et;
783: break;
784:
785: case MODE_NAK:
786: (*et->DecodeConfig)(fp, opt, mode);
787: break;
788:
789: case MODE_REJ:
790: (*et->DecodeConfig)(fp, opt, mode);
791: ECP_PEER_REJ(ecp, index);
792: break;
793:
794: case MODE_NOP:
795: (*et->DecodeConfig)(fp, opt, mode);
796: break;
797: }
798: }
799: }
800:
801: /*
802: * EcpSubtractBloat()
803: *
804: * Given that "size" is our MTU, return the maximum length frame
805: * we can encrypt without the result being longer than "size".
806: */
807:
808: int
809: EcpSubtractBloat(Bund b, int size)
810: {
811: EcpState const ecp = &b->ecp;
812:
813: /* Check transmit encryption */
814: if (OPEN_STATE(ecp->fsm.state) && ecp->xmit && ecp->xmit->SubtractBloat)
815: size = (*ecp->xmit->SubtractBloat)(b, size);
816:
817: /* Account for ECP's protocol number overhead */
818: if (OPEN_STATE(ecp->fsm.state))
819: size -= ECP_OVERHEAD;
820:
821: /* Done */
822: return(size);
823: }
824:
825: /*
826: * EcpSetCommand()
827: */
828:
829: static int
830: EcpSetCommand(Context ctx, int ac, char *av[], void *arg)
831: {
832: EcpState const ecp = &ctx->bund->ecp;
833:
834: if (ac == 0)
835: return(-1);
836: switch ((intptr_t)arg)
837: {
838: case SET_KEY:
839: if (ac != 1)
840: return(-1);
841: strlcpy(ecp->key, av[0], sizeof(ecp->key));
842: break;
843:
844: case SET_ACCEPT:
845: AcceptCommand(ac, av, &ecp->options, gConfList);
846: break;
847:
848: case SET_DENY:
849: DenyCommand(ac, av, &ecp->options, gConfList);
850: break;
851:
852: case SET_ENABLE:
853: EnableCommand(ac, av, &ecp->options, gConfList);
854: break;
855:
856: case SET_DISABLE:
857: DisableCommand(ac, av, &ecp->options, gConfList);
858: break;
859:
860: case SET_YES:
861: YesCommand(ac, av, &ecp->options, gConfList);
862: break;
863:
864: case SET_NO:
865: NoCommand(ac, av, &ecp->options, gConfList);
866: break;
867:
868: default:
869: assert(0);
870: }
871: return(0);
872: }
873:
874: /*
875: * EcpFindType()
876: */
877:
878: static EncType
879: EcpFindType(int type, int *indexp)
880: {
881: int k;
882:
883: for (k = 0; k < ECP_NUM_PROTOS; k++)
884: if (gEncTypes[k]->type == type)
885: {
886: if (indexp)
887: *indexp = k;
888: return(gEncTypes[k]);
889: }
890: return(NULL);
891: }
892:
893: /*
894: * EcpTypeName()
895: */
896:
897: static const char *
898: EcpTypeName(int type)
899: {
900: const struct ecpname *p;
901:
902: for (p = gEcpTypeNames; p->name; p++)
903: if (p->type == type)
904: return(p->name);
905: return("UNKNOWN");
906: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>