Annotation of embedaddon/mpd/src/ecp.c, revision 1.1.1.3
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:
1.1.1.3 ! misho 71: static int EcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 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 },
1.1.1.3 ! misho 97: { NULL, NULL, NULL, NULL, 0, NULL },
1.1 misho 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,
1.1.1.3 ! misho 144: NULL, NULL, NULL, NULL
1.1 misho 145: };
146:
147: /* Names for different types of encryption */
148:
149: static const struct ecpname
150: {
151: u_char type;
152: const char *name;
153: }
154: gEcpTypeNames[] =
155: {
156: { ECP_TY_OUI, "OUI" },
157: { ECP_TY_DESE, "DESE" },
158: { ECP_TY_3DESE, "3DESE" },
159: { ECP_TY_DESE_bis, "DESE-bis" },
160: { 0, NULL },
161: };
162:
163: int gEcpCsock = -1; /* Socket node control socket */
164: int gEcpDsock = -1; /* Socket node data socket */
1.1.1.3 ! misho 165: static EventRef gEcpDataEvent;
1.1 misho 166:
167: int
168: EcpsInit(void)
169: {
170: char name[NG_NODESIZ];
171:
172: /* Create a netgraph socket node */
173: snprintf(name, sizeof(name), "mpd%d-eso", gPid);
174: if (NgMkSockNode(name, &gEcpCsock, &gEcpDsock) < 0) {
175: Perror("EcpsInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
176: return(-1);
177: }
178: (void) fcntl(gEcpCsock, F_SETFD, 1);
179: (void) fcntl(gEcpDsock, F_SETFD, 1);
180:
181: /* Listen for happenings on our node */
182: EventRegister(&gEcpDataEvent, EVENT_READ,
183: gEcpDsock, EVENT_RECURRING, EcpNgDataEvent, NULL);
184:
185: return (0);
186: }
187:
188: void
189: EcpsShutdown(void)
190: {
191: close(gEcpCsock);
192: gEcpCsock = -1;
193: EventUnRegister(&gEcpDataEvent);
194: close(gEcpDsock);
195: gEcpDsock = -1;
196: }
197:
198: /*
199: * EcpInit()
200: */
201:
202: void
203: EcpInit(Bund b)
204: {
205: EcpState ecp = &b->ecp;
206:
207: /* Init ECP state for this bundle */
208:
209: memset(ecp, 0, sizeof(*ecp));
210: FsmInit(&ecp->fsm, &gEcpFsmType, b);
211: ecp->fsm.conf.maxfailure = ECP_MAXFAILURE;
212:
213: /* Construct options list if we haven't done so already */
214:
215: if (gConfList == NULL)
216: {
217: struct confinfo *ci;
1.1.1.3 ! misho 218: unsigned k;
1.1 misho 219:
220: ci = Malloc(MB_CRYPT, (ECP_NUM_PROTOS + 1) * sizeof(*ci));
221: for (k = 0; k < ECP_NUM_PROTOS; k++)
222: {
223: ci[k].option = k;
224: ci[k].peered = TRUE;
225: ci[k].name = gEncTypes[k]->name;
226: }
227: ci[k].name = NULL;
228: gConfList = (const struct confinfo *) ci;
229: }
230: }
231:
232: /*
233: * EcpInst()
234: */
235:
236: void
237: EcpInst(Bund b, Bund bt)
238: {
239: EcpState ecp = &b->ecp;
240:
241: /* Init ECP state for this bundle */
242: memcpy(ecp, &bt->ecp, sizeof(*ecp));
243: FsmInst(&ecp->fsm, &bt->ecp.fsm, b);
244: }
245:
246: /*
247: * EcpConfigure()
248: */
249:
250: static void
251: EcpConfigure(Fsm fp)
252: {
253: Bund b = (Bund)fp->arg;
254: EcpState const ecp = &b->ecp;
1.1.1.3 ! misho 255: unsigned k;
1.1 misho 256:
257: for (k = 0; k < ECP_NUM_PROTOS; k++)
258: {
259: EncType const et = gEncTypes[k];
260:
261: if (et->Configure)
262: (*et->Configure)(b);
263: }
264: ecp->xmit = NULL;
265: ecp->recv = NULL;
266: ecp->self_reject = 0;
267: ecp->peer_reject = 0;
268: }
269:
270: /*
271: * EcpUnConfigure()
272: */
273:
274: static void
275: EcpUnConfigure(Fsm fp)
276: {
277: Bund b = (Bund)fp->arg;
278: EcpState const ecp = &b->ecp;
1.1.1.3 ! misho 279: unsigned k;
1.1 misho 280:
281: for (k = 0; k < ECP_NUM_PROTOS; k++)
282: {
283: EncType const et = gEncTypes[k];
284:
285: if (et->UnConfigure)
286: (*et->UnConfigure)(b);
287: }
288: ecp->xmit = NULL;
289: ecp->recv = NULL;
290: ecp->self_reject = 0;
291: ecp->peer_reject = 0;
292: }
293:
294: /*
295: * EcpNgDataEvent()
296: */
297:
298: static void
299: EcpNgDataEvent(int type, void *cookie)
300: {
301: Bund b;
302: struct sockaddr_ng naddr;
303: socklen_t nsize;
304: Mbuf bp;
305: int num = 0;
1.1.1.2 misho 306: char *bundname, *rest, *b1;
1.1 misho 307: int id;
308:
1.1.1.3 ! misho 309: (void)type;
! 310: (void)cookie;
1.1 misho 311: while (1) {
312: /* Protect from bundle shutdown and DoS */
313: if (num > 100)
314: return;
315:
316: bp = mballoc(4096);
317:
318: /* Read data */
319: nsize = sizeof(naddr);
320: if ((bp->cnt = recvfrom(gEcpDsock, MBDATA(bp), MBSPACE(bp),
321: MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
322: mbfree(bp);
323: if (errno == EAGAIN)
324: return;
325: Log(LG_BUND|LG_ERR, ("EcpNgDataEvent: socket read: %s", strerror(errno)));
326: return;
327: }
328: num++;
329:
330: /* Debugging */
331: LogDumpBp(LG_FRAME, bp,
1.1.1.2 misho 332: "EcpNgDataEvent: rec'd %zu bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
1.1 misho 333:
334: bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
335: if (bundname[0] != 'e' && bundname[0] != 'd') {
336: Log(LG_ERR, ("ECP: Packet from unknown hook \"%s\"",
337: bundname));
338: mbfree(bp);
339: continue;
340: }
1.1.1.2 misho 341: /* Keep old value */
342: b1 = bundname;
1.1 misho 343: bundname++;
344: id = strtol(bundname, &rest, 10);
345: if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
346: Log(LG_ERR, ("ECP: Packet from unexisting bundle \"%s\"",
347: bundname));
348: mbfree(bp);
349: continue;
350: }
351:
352: b = gBundles[id];
353:
354: /* Packet requiring compression */
1.1.1.2 misho 355: if (b1[0] == 'e') {
1.1 misho 356: bp = EcpDataOutput(b, bp);
357: } else {
358: /* Packet requiring decompression */
359: bp = EcpDataInput(b, bp);
360: }
361: if (bp)
362: NgFuncWriteFrame(gEcpDsock, naddr.sg_data, b->name, bp);
363: }
364: }
365:
366:
367: /*
368: * EcpDataOutput()
369: *
370: * Encrypt a frame. Consumes the original packet.
371: */
372:
373: Mbuf
374: EcpDataOutput(Bund b, Mbuf plain)
375: {
376: EcpState const ecp = &b->ecp;
377: Mbuf cypher;
378:
379: LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
380:
381: /* Encrypt packet */
382:
383: if ((!ecp->xmit) || (!ecp->xmit->Encrypt))
384: {
385: Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
386: mbfree(plain);
387: return(NULL);
388: }
389: cypher = (*ecp->xmit->Encrypt)(b, plain);
390: LogDumpBp(LG_FRAME, cypher, "[%s] %s: xmit cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
391:
392: /* Return result, with new protocol number */
393:
394: return(cypher);
395: }
396:
397: /*
398: * EcpDataInput()
399: *
400: * Decrypt incoming packet. If packet got garbled, return NULL.
401: * In any case, we consume the packet passed to us.
402: */
403:
404: Mbuf
405: EcpDataInput(Bund b, Mbuf cypher)
406: {
407: EcpState const ecp = &b->ecp;
408: Mbuf plain;
409:
410: LogDumpBp(LG_FRAME, cypher, "[%s] %s: recv cypher", Pref(&ecp->fsm), Fsm(&ecp->fsm));
411:
412: /* Decrypt packet */
413:
414: if ((!ecp->recv) || (!ecp->recv->Decrypt))
415: {
416: Log(LG_ERR, ("[%s] %s: no encryption for recv", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
417: mbfree(cypher);
418: return(NULL);
419: }
420:
421: plain = (*ecp->recv->Decrypt)(b, cypher);
422:
423: /* Decrypted ok? */
424:
425: if (plain == NULL)
426: {
427: Log(LG_ECP, ("[%s] %s: decryption failed", Pref(&ecp->fsm), Fsm(&ecp->fsm)));
428: return(NULL);
429: }
430:
431: LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ecp->fsm), Fsm(&ecp->fsm));
432: /* Done */
433:
434: return(plain);
435: }
436:
437: /*
438: * EcpUp()
439: */
440:
441: void
442: EcpUp(Bund b)
443: {
444: FsmUp(&b->ecp.fsm);
445: }
446:
447: /*
448: * EcpDown()
449: */
450:
451: void
452: EcpDown(Bund b)
453: {
454: FsmDown(&b->ecp.fsm);
455: }
456:
457: /*
458: * EcpOpen()
459: */
460:
461: void
462: EcpOpen(Bund b)
463: {
464: FsmOpen(&b->ecp.fsm);
465: }
466:
467: /*
468: * EcpClose()
469: */
470:
471: void
472: EcpClose(Bund b)
473: {
474: FsmClose(&b->ecp.fsm);
475: }
476:
477: /*
478: * EcpOpenCmd()
479: */
480:
481: int
482: EcpOpenCmd(Context ctx)
483: {
484: if (ctx->bund->tmpl)
485: Error("impossible to open template");
486: FsmOpen(&ctx->bund->ecp.fsm);
487: return (0);
488: }
489:
490: /*
491: * EcpCloseCmd()
492: */
493:
494: int
495: EcpCloseCmd(Context ctx)
496: {
497: if (ctx->bund->tmpl)
498: Error("impossible to close template");
499: FsmClose(&ctx->bund->ecp.fsm);
500: return (0);
501: }
502:
503: /*
504: * EcpFailure()
505: *
506: * This is fatal to the entire link if encryption is required.
507: */
508:
509: static void
510: EcpFailure(Fsm fp, enum fsmfail reason)
511: {
512: Bund b = (Bund)fp->arg;
1.1.1.3 ! misho 513:
! 514: (void)reason;
1.1 misho 515: if (Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD)) {
516: FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
517: FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
518: }
519: }
520:
521: /*
522: * EcpStat()
523: */
524:
525: int
1.1.1.3 ! misho 526: EcpStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 527: {
528: EcpState const ecp = &ctx->bund->ecp;
529:
1.1.1.3 ! misho 530: (void)ac;
! 531: (void)av;
! 532: (void)arg;
! 533:
1.1 misho 534: Printf("[%s] %s [%s]\r\n", Pref(&ecp->fsm), Fsm(&ecp->fsm), FsmStateName(ecp->fsm.state));
535: Printf("Enabled protocols:\r\n");
536: OptStat(ctx, &ecp->options, gConfList);
537: Printf("Outgoing encryption:\r\n");
538: Printf("\tProto\t: %s\r\n", ecp->xmit ? ecp->xmit->name : "none");
539: if (ecp->xmit && ecp->xmit->Stat)
540: ecp->xmit->Stat(ctx, ECP_DIR_XMIT);
541: Printf("\tResets\t: %d\r\n", ecp->xmit_resets);
542: Printf("Incoming decryption:\r\n");
543: Printf("\tProto\t: %s\r\n", ecp->recv ? ecp->recv->name : "none");
544: if (ecp->recv && ecp->recv->Stat)
545: ecp->recv->Stat(ctx, ECP_DIR_RECV);
546: Printf("\tResets\t: %d\r\n", ecp->recv_resets);
547: return(0);
548: }
549:
550: /*
551: * EcpSendResetReq()
552: */
553:
554: void
555: EcpSendResetReq(Fsm fp)
556: {
557: Bund b = (Bund)fp->arg;
558: EcpState const ecp = &b->ecp;
559: EncType const et = ecp->recv;
560: Mbuf bp = NULL;
561:
562: assert(et);
563: ecp->recv_resets++;
564: if (et->SendResetReq)
565: bp = (*et->SendResetReq)(b);
566: Log(LG_ECP, ("[%s] %s: SendResetReq", Pref(fp), Fsm(fp)));
567: FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
568: }
569:
570: /*
571: * EcpRecvResetReq()
572: */
573:
574: void
575: EcpRecvResetReq(Fsm fp, int id, Mbuf bp)
576: {
577: Bund b = (Bund)fp->arg;
578: EcpState const ecp = &b->ecp;
579: EncType const et = ecp->xmit;
580:
581: ecp->xmit_resets++;
582: bp = (et && et->RecvResetReq) ? (*et->RecvResetReq)(b, id, bp) : NULL;
583: Log(fp->log, ("[%s] %s: SendResetAck", Pref(fp), Fsm(fp)));
584: FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
585: }
586:
587: /*
588: * EcpRecvResetAck()
589: */
590:
591: static void
592: EcpRecvResetAck(Fsm fp, int id, Mbuf bp)
593: {
594: Bund b = (Bund)fp->arg;
595: EcpState const ecp = &b->ecp;
596: EncType const et = ecp->recv;
597:
598: if (et && et->RecvResetAck)
599: (*et->RecvResetAck)(b, id, bp);
600: }
601:
602: /*
603: * EcpInput()
604: */
605:
606: void
607: EcpInput(Bund b, Mbuf bp)
608: {
609: FsmInput(&b->ecp.fsm, bp);
610: }
611:
612: /*
613: * EcpBuildConfigReq()
614: */
615:
616: static u_char *
617: EcpBuildConfigReq(Fsm fp, u_char *cp)
618: {
619: Bund b = (Bund)fp->arg;
620: EcpState const ecp = &b->ecp;
1.1.1.3 ! misho 621: unsigned type;
1.1 misho 622:
623: /* Put in all options that peer hasn't rejected */
624:
625: for (ecp->xmit = NULL, type = 0; type < ECP_NUM_PROTOS; type++)
626: {
627: EncType const et = gEncTypes[type];
628:
629: if (Enabled(&ecp->options, type) && !ECP_PEER_REJECTED(ecp, type))
630: {
631: cp = (*et->BuildConfigReq)(b, cp);
632: if (!ecp->xmit)
633: ecp->xmit = et;
634: }
635: }
636: return(cp);
637: }
638:
639: /*
640: * EcpLayerUp()
641: *
642: * Called when ECP has reached the OPENED state
643: */
644:
645: static void
646: EcpLayerUp(Fsm fp)
647: {
648: Bund b = (Bund)fp->arg;
649: EcpState const ecp = &b->ecp;
650: struct ngm_connect cn;
651:
652: /* Initialize */
653: if (ecp->xmit && ecp->xmit->Init)
654: (*ecp->xmit->Init)(b, ECP_DIR_XMIT);
655: if (ecp->recv && ecp->recv->Init)
656: (*ecp->recv->Init)(b, ECP_DIR_RECV);
657:
658: if (ecp->recv && ecp->recv->Decrypt)
659: {
660: /* Connect a hook from the bpf node to our socket node */
661: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
662: snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
663: strcpy(cn.peerhook, NG_PPP_HOOK_DECRYPT);
664: if (NgSendMsg(gEcpCsock, ".:",
665: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
666: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
667: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
668: }
669: }
670: if (ecp->xmit && ecp->xmit->Encrypt)
671: {
672: /* Connect a hook from the bpf node to our socket node */
673: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
674: snprintf(cn.ourhook, sizeof(cn.ourhook), "e%d", b->id);
675: strcpy(cn.peerhook, NG_PPP_HOOK_ENCRYPT);
676: if (NgSendMsg(gEcpCsock, ".:",
677: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
678: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
679: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
680: }
681: }
682:
683: Log(LG_ECP, ("[%s] ECP: Encrypt using: %s", b->name, !ecp->xmit ? "none" : ecp->xmit->name));
684: Log(LG_ECP, ("[%s] ECP: Decrypt using: %s", b->name, !ecp->recv ? "none" : ecp->recv->name));
685:
686: /* Update PPP node config */
687: b->pppConfig.bund.enableEncryption = (ecp->xmit != NULL);
688: b->pppConfig.bund.enableDecryption = (ecp->recv != NULL);
689: NgFuncSetConfig(b);
690:
691: /* Update interface MTU */
692: BundUpdateParams(b);
693: }
694:
695: /*
696: * EcpLayerDown()
697: *
698: * Called when ECP leaves the OPENED state
699: */
700:
701: static void
702: EcpLayerDown(Fsm fp)
703: {
704: Bund b = (Bund)fp->arg;
705: EcpState const ecp = &b->ecp;
706:
707: /* Update PPP node config */
708: b->pppConfig.bund.enableEncryption = 0;
709: b->pppConfig.bund.enableDecryption = 0;
710: NgFuncSetConfig(b);
711:
712: /* Update interface MTU */
713: BundUpdateParams(b);
714:
715: if (ecp->xmit != NULL && ecp->xmit->Encrypt != NULL) {
716: char hook[NG_HOOKSIZ];
717: /* Disconnect hook. */
718: snprintf(hook, sizeof(hook), "e%d", b->id);
719: NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
720: }
721:
722: if (ecp->recv != NULL && ecp->recv->Decrypt != NULL) {
723: char hook[NG_HOOKSIZ];
724: /* Disconnect hook. */
725: snprintf(hook, sizeof(hook), "d%d", b->id);
726: NgFuncDisconnect(gEcpCsock, b->name, ".:", hook);
727: }
728:
729: if (ecp->xmit && ecp->xmit->Cleanup)
730: (ecp->xmit->Cleanup)(b, ECP_DIR_XMIT);
731: if (ecp->recv && ecp->recv->Cleanup)
732: (ecp->recv->Cleanup)(b, ECP_DIR_RECV);
733:
734: ecp->xmit_resets = 0;
735: ecp->recv_resets = 0;
736: }
737:
738: /*
739: * EcpDecodeConfig()
740: */
741:
742: static void
743: EcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
744: {
745: Bund b = (Bund)fp->arg;
746: EcpState const ecp = &b->ecp;
747: u_int ackSizeSave, rejSizeSave;
748: int k, rej;
749:
750: /* Forget our previous choice on new request */
751: if (mode == MODE_REQ)
752: ecp->recv = NULL;
753:
754: /* Decode each config option */
755:
756: for (k = 0; k < num; k++)
757: {
758: FsmOption const opt = &list[k];
759: int index;
760: EncType et;
761:
762: Log(LG_ECP, ("[%s] %s", b->name, EcpTypeName(opt->type)));
763: if ((et = EcpFindType(opt->type, &index)) == NULL)
764: {
765: if (mode == MODE_REQ)
766: {
767: Log(LG_ECP, ("[%s] Not supported", b->name));
768: FsmRej(fp, opt);
769: }
770: continue;
771: }
772: switch (mode)
773: {
774: case MODE_REQ:
775: ackSizeSave = gAckSize;
776: rejSizeSave = gRejSize;
777: rej = (!Acceptable(&ecp->options, index)
778: || ECP_SELF_REJECTED(ecp, index)
779: || (ecp->recv && ecp->recv != et));
780: if (rej)
781: {
782: (*et->DecodeConfig)(fp, opt, MODE_NOP);
783: FsmRej(fp, opt);
784: break;
785: }
786: (*et->DecodeConfig)(fp, opt, mode);
787: if (gRejSize != rejSizeSave) /* we rejected it */
788: {
789: ECP_SELF_REJ(ecp, index);
790: break;
791: }
792: if (gAckSize != ackSizeSave) /* we accepted it */
793: ecp->recv = et;
794: break;
795:
796: case MODE_NAK:
797: (*et->DecodeConfig)(fp, opt, mode);
798: break;
799:
800: case MODE_REJ:
801: (*et->DecodeConfig)(fp, opt, mode);
802: ECP_PEER_REJ(ecp, index);
803: break;
804:
805: case MODE_NOP:
806: (*et->DecodeConfig)(fp, opt, mode);
807: break;
808: }
809: }
810: }
811:
812: /*
813: * EcpSubtractBloat()
814: *
815: * Given that "size" is our MTU, return the maximum length frame
816: * we can encrypt without the result being longer than "size".
817: */
818:
819: int
820: EcpSubtractBloat(Bund b, int size)
821: {
822: EcpState const ecp = &b->ecp;
823:
824: /* Check transmit encryption */
825: if (OPEN_STATE(ecp->fsm.state) && ecp->xmit && ecp->xmit->SubtractBloat)
826: size = (*ecp->xmit->SubtractBloat)(b, size);
827:
828: /* Account for ECP's protocol number overhead */
829: if (OPEN_STATE(ecp->fsm.state))
830: size -= ECP_OVERHEAD;
831:
832: /* Done */
833: return(size);
834: }
835:
836: /*
837: * EcpSetCommand()
838: */
839:
840: static int
1.1.1.3 ! misho 841: EcpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 842: {
843: EcpState const ecp = &ctx->bund->ecp;
844:
845: if (ac == 0)
846: return(-1);
847: switch ((intptr_t)arg)
848: {
849: case SET_KEY:
850: if (ac != 1)
851: return(-1);
852: strlcpy(ecp->key, av[0], sizeof(ecp->key));
853: break;
854:
855: case SET_ACCEPT:
856: AcceptCommand(ac, av, &ecp->options, gConfList);
857: break;
858:
859: case SET_DENY:
860: DenyCommand(ac, av, &ecp->options, gConfList);
861: break;
862:
863: case SET_ENABLE:
864: EnableCommand(ac, av, &ecp->options, gConfList);
865: break;
866:
867: case SET_DISABLE:
868: DisableCommand(ac, av, &ecp->options, gConfList);
869: break;
870:
871: case SET_YES:
872: YesCommand(ac, av, &ecp->options, gConfList);
873: break;
874:
875: case SET_NO:
876: NoCommand(ac, av, &ecp->options, gConfList);
877: break;
878:
879: default:
880: assert(0);
881: }
882: return(0);
883: }
884:
885: /*
886: * EcpFindType()
887: */
888:
889: static EncType
890: EcpFindType(int type, int *indexp)
891: {
1.1.1.3 ! misho 892: unsigned k;
1.1 misho 893:
894: for (k = 0; k < ECP_NUM_PROTOS; k++)
895: if (gEncTypes[k]->type == type)
896: {
897: if (indexp)
898: *indexp = k;
899: return(gEncTypes[k]);
900: }
901: return(NULL);
902: }
903:
904: /*
905: * EcpTypeName()
906: */
907:
908: static const char *
909: EcpTypeName(int type)
910: {
911: const struct ecpname *p;
912:
913: for (p = gEcpTypeNames; p->name; p++)
914: if (p->type == type)
915: return(p->name);
916: return("UNKNOWN");
917: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>