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