Annotation of embedaddon/mpd/src/ccp.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * ccp.c
4: *
5: * Written by Archie Cobbs <archie@freebsd.org>
6: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
7: * See ``COPYRIGHT.whistle''
8: */
9:
10: #include "defs.h"
11: #include "ppp.h"
12: #include "ccp.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 CCP_MAXFAILURE 7
25:
26: #define CCP_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: /* Set menu options */
37: enum {
38: SET_ACCEPT,
39: SET_DENY,
40: SET_ENABLE,
41: SET_DISABLE,
42: SET_YES,
43: SET_NO
44: };
45:
46: /*
47: * INTERNAL FUNCTIONS
48: */
49:
50: static void CcpConfigure(Fsm fp);
51: static void CcpUnConfigure(Fsm fp);
52: static u_char *CcpBuildConfigReq(Fsm fp, u_char *cp);
53: static void CcpDecodeConfig(Fsm f, FsmOption a, int num, int mode);
54: static void CcpLayerUp(Fsm fp);
55: static void CcpLayerDown(Fsm fp);
56: static void CcpFailure(Fsm f, enum fsmfail reason);
57: static void CcpRecvResetReq(Fsm fp, int id, Mbuf bp);
58: static void CcpRecvResetAck(Fsm fp, int id, Mbuf bp);
59:
60: static int CcpCheckEncryption(Bund b);
61: static int CcpSetCommand(Context ctx, int ac, char *av[], void *arg);
62: static CompType CcpFindComp(int type, int *indexp);
63: static const char *CcpTypeName(int type, char *buf, size_t len);
64:
65: static void CcpNgCtrlEvent(int type, void *cookie);
66: static void CcpNgDataEvent(int type, void *cookie);
67:
68: /*
69: * GLOBAL VARIABLES
70: */
71:
72: const struct cmdtab CcpSetCmds[] = {
73: { "accept [opt ...]", "Accept option",
74: CcpSetCommand, NULL, 2, (void *) SET_ACCEPT },
75: { "deny [opt ...]", "Deny option",
76: CcpSetCommand, NULL, 2, (void *) SET_DENY },
77: { "enable [opt ...]", "Enable option",
78: CcpSetCommand, NULL, 2, (void *) SET_ENABLE },
79: { "disable [opt ...]", "Disable option",
80: CcpSetCommand, NULL, 2, (void *) SET_DISABLE },
81: { "yes [opt ...]", "Enable and accept option",
82: CcpSetCommand, NULL, 2, (void *) SET_YES },
83: { "no [opt ...]", "Disable and deny option",
84: CcpSetCommand, NULL, 2, (void *) SET_NO },
85: { NULL },
86: };
87:
88: /*
89: * INTERNAL VARIABLES
90: */
91:
92: /* These should be listed in order of preference */
93: static const CompType gCompTypes[] = {
94: #ifdef CCP_MPPC
95: &gCompMppcInfo,
96: #endif
97: #ifdef CCP_DEFLATE
98: &gCompDeflateInfo,
99: #endif
100: #ifdef CCP_PRED1
101: &gCompPred1Info,
102: #endif
103: };
104: #define CCP_NUM_PROTOS (sizeof(gCompTypes) / sizeof(*gCompTypes))
105:
106: /* Corresponding option list */
107: static const struct confinfo *gConfList;
108:
109: /* FSM Initializer */
110: static const struct fsmtype gCcpFsmType = {
111: "CCP",
112: PROTO_CCP,
113: CCP_KNOWN_CODES,
114: FALSE,
115: LG_CCP, LG_CCP2,
116: NULL,
117: CcpLayerUp,
118: CcpLayerDown,
119: NULL,
120: NULL,
121: CcpBuildConfigReq,
122: CcpDecodeConfig,
123: CcpConfigure,
124: CcpUnConfigure,
125: NULL,
126: NULL,
127: NULL,
128: NULL,
129: CcpFailure,
130: CcpRecvResetReq,
131: CcpRecvResetAck,
132: NULL,
133: };
134:
135: /* Names for different types of compression */
136: static const struct ccpname {
137: u_char type;
138: const char *name;
139: } gCcpTypeNames[] = {
140: { CCP_TY_OUI, "OUI" },
141: { CCP_TY_PRED1, "PRED1" },
142: { CCP_TY_PRED2, "PRED2" },
143: { CCP_TY_PUDDLE, "PUDDLE" },
144: { CCP_TY_HWPPC, "HWPPC" },
145: { CCP_TY_STAC, "STAC" },
146: { CCP_TY_MPPC, "MPPC" },
147: { CCP_TY_GAND, "GAND" },
148: { CCP_TY_V42BIS, "V42BIS" },
149: { CCP_TY_BSD, "BSD" },
150: { CCP_TY_LZS_DCP, "LZS-DCP" },
151: { CCP_TY_DEFLATE24, "DEFLATE24" },
152: { CCP_TY_DCE, "DCE" },
153: { CCP_TY_DEFLATE, "DEFLATE" },
154: { CCP_TY_V44, "V.44/LZJH" },
155: { 0, NULL },
156: };
157:
158: int gCcpCsock = -1; /* Socket node control socket */
159: int gCcpDsock = -1; /* Socket node data socket */
160: EventRef gCcpCtrlEvent;
161: EventRef gCcpDataEvent;
162:
163: int
164: CcpsInit(void)
165: {
166: char name[NG_NODESIZ];
167:
168: /* Create a netgraph socket node */
169: snprintf(name, sizeof(name), "mpd%d-cso", gPid);
170: if (NgMkSockNode(name, &gCcpCsock, &gCcpDsock) < 0) {
171: Perror("CcpsInit(): can't create %s node", NG_SOCKET_NODE_TYPE);
172: return(-1);
173: }
174: (void) fcntl(gCcpCsock, F_SETFD, 1);
175: (void) fcntl(gCcpDsock, F_SETFD, 1);
176:
177: /* Listen for happenings on our node */
178: EventRegister(&gCcpCtrlEvent, EVENT_READ,
179: gCcpCsock, EVENT_RECURRING, CcpNgCtrlEvent, NULL);
180: EventRegister(&gCcpDataEvent, EVENT_READ,
181: gCcpDsock, EVENT_RECURRING, CcpNgDataEvent, NULL);
182:
183: return (0);
184: }
185:
186: void
187: CcpsShutdown(void)
188: {
189: EventUnRegister(&gCcpCtrlEvent);
190: close(gCcpCsock);
191: gCcpCsock = -1;
192: EventUnRegister(&gCcpDataEvent);
193: close(gCcpDsock);
194: gCcpDsock = -1;
195: }
196:
197: /*
198: * CcpInit()
199: */
200:
201: void
202: CcpInit(Bund b)
203: {
204: CcpState ccp = &b->ccp;
205:
206: /* Init CCP state for this bundle */
207: memset(ccp, 0, sizeof(*ccp));
208: FsmInit(&ccp->fsm, &gCcpFsmType, b);
209: ccp->fsm.conf.maxfailure = CCP_MAXFAILURE;
210:
211: /* Construct options list if we haven't done so already */
212: if (gConfList == NULL) {
213: struct confinfo *ci;
214: int k;
215:
216: ci = Malloc(MB_COMP, (CCP_NUM_PROTOS + 1) * sizeof(*ci));
217: for (k = 0; k < CCP_NUM_PROTOS; k++) {
218: ci[k].option = k;
219: ci[k].peered = TRUE;
220: ci[k].name = gCompTypes[k]->name;
221: }
222:
223: /* Terminate list */
224: ci[k].name = NULL;
225: gConfList = (const struct confinfo *) ci;
226: }
227: }
228:
229: /*
230: * CcpInst()
231: */
232:
233: void
234: CcpInst(Bund b, Bund bt)
235: {
236: CcpState ccp = &b->ccp;
237:
238: /* Init CCP state for this bundle */
239: memcpy(ccp, &bt->ccp, sizeof(*ccp));
240: FsmInst(&ccp->fsm, &bt->ccp.fsm, b);
241: }
242:
243: /*
244: * CcpConfigure()
245: */
246:
247: static void
248: CcpConfigure(Fsm fp)
249: {
250: Bund b = (Bund)fp->arg;
251: CcpState const ccp = &b->ccp;
252: int k;
253:
254: /* Reset state */
255: ccp->self_reject = 0;
256: ccp->peer_reject = 0;
257: ccp->crypt_check = 0;
258: ccp->xmit = NULL;
259: ccp->recv = NULL;
260: for (k = 0; k < CCP_NUM_PROTOS; k++) {
261: CompType const ct = gCompTypes[k];
262:
263: if (ct->Configure) {
264: if ((*ct->Configure)(b)) {
265: if (Enabled(&ccp->options, k)) {
266: Log(LG_CCP, ("[%s] CCP: Protocol %s disabled "
267: "as useless for this setup",
268: b->name, ct->name));
269: }
270: CCP_SELF_REJ(ccp, k);
271: };
272: }
273: }
274: }
275:
276: /*
277: * CcpUnConfigure()
278: */
279:
280: static void
281: CcpUnConfigure(Fsm fp)
282: {
283: Bund b = (Bund)fp->arg;
284: CcpState const ccp = &b->ccp;
285: int k;
286:
287: /* Reset state */
288: ccp->self_reject = 0;
289: ccp->peer_reject = 0;
290: ccp->crypt_check = 0;
291: ccp->xmit = NULL;
292: ccp->recv = NULL;
293: for (k = 0; k < CCP_NUM_PROTOS; k++) {
294: CompType const ct = gCompTypes[k];
295:
296: if (ct->UnConfigure)
297: (*ct->UnConfigure)(b);
298: }
299: }
300:
301: /*
302: * CcpNgCtrlEvent()
303: *
304: */
305:
306: void
307: CcpNgCtrlEvent(int type, void *cookie)
308: {
309: Bund b = NULL;
310: union {
311: u_char buf[2048];
312: struct ng_mesg msg;
313: } u;
314: char raddr[NG_PATHSIZ];
315: int i, len;
316: ng_ID_t id;
317:
318: /* Read message */
319: if ((len = NgRecvMsg(gCcpCsock, &u.msg, sizeof(u), raddr)) < 0) {
320: Perror("CcpNgCtrlEvent: can't read message");
321: return;
322: }
323:
324: if (sscanf(raddr, "[%x]:", &id) != 1) {
325: Log(LG_ERR, ("CcpNgCtrlEvent: can't decode sender id: '%s'",
326: raddr));
327: return;
328: }
329:
330: for (i = 0; i < gNumBundles; i++) {
331: if (gBundles[i] && !gBundles[i]->dead &&
332: gBundles[i]->ccp.decomp_node_id == id) {
333: b = gBundles[i];
334: break;
335: }
336: }
337: if (!b)
338: return;
339:
340: /* Examine message */
341: switch (u.msg.header.typecookie) {
342:
343: #ifdef USE_NG_MPPC
344: case NGM_MPPC_COOKIE:
345: #endif
346: #ifdef USE_NG_DEFLATE
347: case NGM_DEFLATE_COOKIE:
348: #endif
349: #ifdef USE_NG_PRED1
350: case NGM_PRED1_COOKIE:
351: #endif
352: CcpRecvMsg(b, &u.msg, len);
353: return;
354:
355: default:
356: /* Unknown message */
357: Log(LG_ERR, ("CcpNgCtrlEvent: rec'd unknown ctrl message, cookie=%d cmd=%d",
358: u.msg.header.typecookie, u.msg.header.cmd));
359: break;
360: }
361:
362: }
363:
364: /*
365: * CcpNgDataEvent()
366: */
367:
368: static void
369: CcpNgDataEvent(int type, void *cookie)
370: {
371: Bund b;
372: struct sockaddr_ng naddr;
373: socklen_t nsize;
374: Mbuf bp;
375: int num = 0;
376: char *bundname, *rest;
377: int id;
378:
379: while (1) {
380: /* Protect from bundle shutdown and DoS */
381: if (num > 100)
382: return;
383:
384: bp = mballoc(4096);
385:
386: /* Read data */
387: nsize = sizeof(naddr);
388: if ((bp->cnt = recvfrom(gCcpDsock, MBDATA(bp), MBSPACE(bp),
389: MSG_DONTWAIT, (struct sockaddr *)&naddr, &nsize)) < 0) {
390: mbfree(bp);
391: if (errno == EAGAIN)
392: return;
393: Log(LG_BUND|LG_ERR, ("CcpNgDataEvent: socket read: %s", strerror(errno)));
394: return;
395: }
396: num++;
397:
398: /* Debugging */
399: LogDumpBp(LG_FRAME, bp,
400: "CcpNgDataEvent: rec'd %d bytes frame on %s hook", MBLEN(bp), naddr.sg_data);
401:
402: bundname = ((struct sockaddr_ng *)&naddr)->sg_data;
403: if (bundname[0] != 'c' && bundname[0] != 'd') {
404: Log(LG_ERR, ("CCP: Packet from unknown hook \"%s\"",
405: bundname));
406: mbfree(bp);
407: continue;
408: }
409: bundname++;
410: id = strtol(bundname, &rest, 10);
411: if (rest[0] != 0 || !gBundles[id] || gBundles[id]->dead) {
412: Log(LG_ERR, ("CCP: Packet from unexisting bundle \"%s\"",
413: bundname));
414: mbfree(bp);
415: continue;
416: }
417:
418: b = gBundles[id];
419:
420: /* Packet requiring compression */
421: if (bundname[0] == 'c') {
422: bp = CcpDataOutput(b, bp);
423: } else {
424: /* Packet requiring decompression */
425: bp = CcpDataInput(b, bp);
426: }
427: if (bp)
428: NgFuncWriteFrame(gCcpDsock, naddr.sg_data, b->name, bp);
429: }
430: }
431:
432: /*
433: * CcpRecvMsg()
434: */
435:
436: void
437: CcpRecvMsg(Bund b, struct ng_mesg *msg, int len)
438: {
439: CcpState const ccp = &b->ccp;
440: Fsm const fp = &ccp->fsm;
441:
442: switch (msg->header.typecookie) {
443: #ifdef USE_NG_MPPC
444: case NGM_MPPC_COOKIE:
445: switch (msg->header.cmd) {
446: case NGM_MPPC_RESETREQ: {
447: CcpSendResetReq(b);
448: return;
449: }
450: default:
451: break;
452: }
453: break;
454: #endif
455: #ifdef USE_NG_DEFLATE
456: case NGM_DEFLATE_COOKIE:
457: switch (msg->header.cmd) {
458: case NGM_DEFLATE_RESETREQ: {
459: CcpSendResetReq(b);
460: return;
461: }
462: default:
463: break;
464: }
465: break;
466: #endif
467: #ifdef USE_NG_PRED1
468: case NGM_PRED1_COOKIE:
469: switch (msg->header.cmd) {
470: case NGM_PRED1_RESETREQ: {
471: CcpSendResetReq(b);
472: return;
473: }
474: default:
475: break;
476: }
477: break;
478: #endif
479: default:
480: break;
481: }
482:
483: /* Unknown! */
484: Log(LG_ERR, ("[%s] %s: rec'd unknown netgraph message: cookie=%d, cmd=%d",
485: Pref(fp), Fsm(fp), msg->header.typecookie, msg->header.cmd));
486: }
487:
488: /*
489: * CcpUp()
490: */
491:
492: void
493: CcpUp(Bund b)
494: {
495: FsmUp(&b->ccp.fsm);
496: }
497:
498: /*
499: * CcpDown()
500: */
501:
502: void
503: CcpDown(Bund b)
504: {
505: FsmDown(&b->ccp.fsm);
506: }
507:
508: /*
509: * CcpOpen()
510: */
511:
512: void
513: CcpOpen(Bund b)
514: {
515: FsmOpen(&b->ccp.fsm);
516: }
517:
518: /*
519: * CcpClose()
520: */
521:
522: void
523: CcpClose(Bund b)
524: {
525: FsmClose(&b->ccp.fsm);
526: }
527:
528: /*
529: * CcpOpenCmd()
530: */
531:
532: int
533: CcpOpenCmd(Context ctx)
534: {
535: if (ctx->bund->tmpl)
536: Error("impossible to open template");
537: FsmOpen(&ctx->bund->ccp.fsm);
538: return (0);
539: }
540:
541: /*
542: * CcpCloseCmd()
543: */
544:
545: int
546: CcpCloseCmd(Context ctx)
547: {
548: if (ctx->bund->tmpl)
549: Error("impossible to close template");
550: FsmClose(&ctx->bund->ccp.fsm);
551: return (0);
552: }
553:
554: /*
555: * CcpFailure()
556: *
557: * If we fail, just shut down and stop trying. However, if encryption
558: * was required and MPPE encryption was enabled, then die here as well.
559: */
560:
561: static void
562: CcpFailure(Fsm fp, enum fsmfail reason)
563: {
564: Bund b = (Bund)fp->arg;
565: CcpCheckEncryption(b);
566: }
567:
568: /*
569: * CcpStat()
570: */
571:
572: int
573: CcpStat(Context ctx, int ac, char *av[], void *arg)
574: {
575: CcpState const ccp = &ctx->bund->ccp;
576: char buf[64];
577:
578: Printf("[%s] %s [%s]\r\n", Pref(&ccp->fsm), Fsm(&ccp->fsm), FsmStateName(ccp->fsm.state));
579: Printf("Enabled protocols:\r\n");
580: OptStat(ctx, &ccp->options, gConfList);
581:
582: #ifdef CCP_MPPC
583: MppcStat(ctx, ac, av, arg);
584: #endif
585: Printf("Outgoing compression:\r\n");
586: Printf("\tProto\t: %s (%s)\r\n", !ccp->xmit ? "none" : ccp->xmit->name,
587: (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(ctx->bund, COMP_DIR_XMIT, buf, sizeof(buf)) : "");
588: if (ccp->xmit && ccp->xmit->Stat)
589: ccp->xmit->Stat(ctx, COMP_DIR_XMIT);
590: Printf("\tResets\t: %d\r\n", ccp->xmit_resets);
591:
592: Printf("Incoming decompression:\r\n");
593: Printf("\tProto\t: %s (%s)\r\n", !ccp->recv ? "none" : ccp->recv->name,
594: (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(ctx->bund, COMP_DIR_RECV, buf, sizeof(buf)) : "");
595: if (ccp->recv && ccp->recv->Stat)
596: ccp->recv->Stat(ctx, COMP_DIR_RECV);
597: Printf("\tResets\t: %d\r\n", ccp->recv_resets);
598:
599: return(0);
600: }
601:
602: /*
603: * CcpSendResetReq()
604: */
605:
606: void
607: CcpSendResetReq(Bund b)
608: {
609: CcpState const ccp = &b->ccp;
610: CompType const ct = ccp->recv;
611: Fsm const fp = &ccp->fsm;
612: Mbuf bp = NULL;
613:
614: if (ct == NULL) {
615: Log(LG_ERR, ("[%s] %s: CcpSendResetReq() call from undefined decompressor!",
616: Pref(fp), Fsm(fp)));
617: return;
618: }
619:
620: ccp->recv_resets++;
621: if (ct->SendResetReq)
622: bp = (*ct->SendResetReq)(b);
623: Log(LG_CCP, ("[%s] %s: SendResetReq #%d link %d (%s)",
624: Pref(fp), Fsm(fp), fp->reqid, 0, FsmStateName(fp->state)));
625: FsmOutputMbuf(fp, CODE_RESETREQ, fp->reqid++, bp);
626: }
627:
628: /*
629: * CcpRecvResetReq()
630: */
631:
632: static void
633: CcpRecvResetReq(Fsm fp, int id, Mbuf bp)
634: {
635: Bund b = (Bund)fp->arg;
636: CcpState const ccp = &b->ccp;
637: CompType const ct = ccp->xmit;
638: int noAck = 0;
639:
640: ccp->xmit_resets++;
641: bp = (ct && ct->RecvResetReq) ? (*ct->RecvResetReq)(b, id, bp, &noAck) : NULL;
642: if (!noAck) {
643: Log(LG_CCP, ("[%s] %s: SendResetAck #%d link %d (%s)",
644: Pref(fp), Fsm(fp), id, 0, FsmStateName(fp->state)));
645: FsmOutputMbuf(fp, CODE_RESETACK, id, bp);
646: }
647: }
648:
649: /*
650: * CcpRecvResetAck()
651: */
652:
653: static void
654: CcpRecvResetAck(Fsm fp, int id, Mbuf bp)
655: {
656: Bund b = (Bund)fp->arg;
657: CcpState const ccp = &b->ccp;
658: CompType const ct = ccp->recv;
659:
660: if (ct && ct->RecvResetAck)
661: (*ct->RecvResetAck)(b, id, bp);
662: }
663:
664: /*
665: * CcpInput()
666: */
667:
668: void
669: CcpInput(Bund b, Mbuf bp)
670: {
671: FsmInput(&b->ccp.fsm, bp);
672: }
673:
674: /*
675: * CcpDataOutput()
676: *
677: * Compress a frame. Consumes the original packet.
678: */
679:
680: Mbuf
681: CcpDataOutput(Bund b, Mbuf plain)
682: {
683: CcpState const ccp = &b->ccp;
684: Mbuf comp;
685:
686: LogDumpBp(LG_FRAME, plain, "[%s] %s: xmit plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
687:
688: /* Compress packet */
689:
690: if ((!ccp->xmit) || (!ccp->xmit->Compress))
691: {
692: Log(LG_ERR, ("[%s] %s: no encryption for xmit", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
693: mbfree(plain);
694: return(NULL);
695: }
696: comp = (*ccp->xmit->Compress)(b, plain);
697: LogDumpBp(LG_FRAME, comp, "[%s] %s: xmit comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
698:
699: return(comp);
700: }
701:
702: /*
703: * CcpDataInput()
704: *
705: * Decompress incoming packet. If packet got garbled, return NULL.
706: * In any case, we consume the packet passed to us.
707: */
708:
709: Mbuf
710: CcpDataInput(Bund b, Mbuf comp)
711: {
712: CcpState const ccp = &b->ccp;
713: Mbuf plain;
714:
715: LogDumpBp(LG_FRAME, comp, "[%s] %s: recv comp", Pref(&ccp->fsm), Fsm(&ccp->fsm));
716:
717: /* Decompress packet */
718:
719: if ((!ccp->recv) || (!ccp->recv->Decompress))
720: {
721: Log(LG_ERR, ("[%s] %s: no compression for recv", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
722: mbfree(comp);
723: return(NULL);
724: }
725:
726: plain = (*ccp->recv->Decompress)(b, comp);
727:
728: /* Encrypted ok? */
729:
730: if (plain == NULL)
731: {
732: Log(LG_CCP, ("[%s] %s: decompression failed", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
733: return(NULL);
734: }
735: LogDumpBp(LG_FRAME, plain, "[%s] %s: recv plain", Pref(&ccp->fsm), Fsm(&ccp->fsm));
736:
737: return(plain);
738: }
739:
740: /*
741: * CcpBuildConfigReq()
742: */
743:
744: static u_char *
745: CcpBuildConfigReq(Fsm fp, u_char *cp)
746: {
747: Bund b = (Bund)fp->arg;
748: CcpState const ccp = &b->ccp;
749: int type;
750: int ok;
751:
752: /* Put in all options that peer hasn't rejected in preferred order */
753: ccp->xmit = NULL;
754: for (type = 0; type < CCP_NUM_PROTOS; type++) {
755: CompType const ct = gCompTypes[type];
756:
757: if (Enabled(&ccp->options, type) && !CCP_PEER_REJECTED(ccp, type)) {
758: cp = (*ct->BuildConfigReq)(b, cp, &ok);
759: if (ok && (!ccp->xmit))
760: ccp->xmit = ct;
761: }
762: }
763: return(cp);
764: }
765:
766: /*
767: * CcpLayerUp()
768: */
769:
770: static void
771: CcpLayerUp(Fsm fp)
772: {
773: Bund b = (Bund)fp->arg;
774: CcpState const ccp = &b->ccp;
775: struct ngm_connect cn;
776: char buf[64];
777:
778: /* If nothing was negotiated in either direction, close CCP */
779: if ((!ccp->recv || !(*ccp->recv->Negotiated)(b, COMP_DIR_RECV))
780: && (!ccp->xmit || !(*ccp->xmit->Negotiated)(b, COMP_DIR_XMIT))) {
781: Log(LG_CCP, ("[%s] %s: No compression negotiated", Pref(fp), Fsm(fp)));
782: FsmFailure(fp, FAIL_NEGOT_FAILURE);
783: return;
784: }
785:
786: /* Check for required encryption */
787: if (CcpCheckEncryption(b) < 0) {
788: return;
789: }
790:
791: /* Initialize each direction */
792: if (ccp->xmit != NULL && ccp->xmit->Init != NULL
793: && (*ccp->xmit->Init)(b, COMP_DIR_XMIT) < 0) {
794: Log(LG_CCP, ("[%s] %s: compression init failed", Pref(fp), Fsm(fp)));
795: FsmFailure(fp, FAIL_NEGOT_FAILURE); /* XXX */
796: return;
797: }
798: if (ccp->recv != NULL && ccp->recv->Init != NULL
799: && (*ccp->recv->Init)(b, COMP_DIR_RECV) < 0) {
800: Log(LG_CCP, ("[%s] %s: decompression init failed", Pref(fp), Fsm(fp)));
801: FsmFailure(fp, FAIL_NEGOT_FAILURE); /* XXX */
802: return;
803: }
804:
805: if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
806: /* Connect a hook from the ppp node to our socket node */
807: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
808: snprintf(cn.ourhook, sizeof(cn.ourhook), "c%d", b->id);
809: strcpy(cn.peerhook, NG_PPP_HOOK_COMPRESS);
810: if (NgSendMsg(gCcpCsock, ".:",
811: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
812: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
813: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
814: }
815: }
816:
817: if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
818: /* Connect a hook from the ppp node to our socket node */
819: snprintf(cn.path, sizeof(cn.path), "[%x]:", b->nodeID);
820: snprintf(cn.ourhook, sizeof(cn.ourhook), "d%d", b->id);
821: strcpy(cn.peerhook, NG_PPP_HOOK_DECOMPRESS);
822: if (NgSendMsg(gCcpCsock, ".:",
823: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
824: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
825: b->name, ".:", cn.ourhook, cn.path, cn.peerhook);
826: }
827: }
828:
829: /* Report what we're doing */
830: Log(LG_CCP, ("[%s] CCP: Compress using: %s (%s)", b->name, !ccp->xmit ? "none" : ccp->xmit->name,
831: (ccp->xmit && ccp->xmit->Describe) ? (*ccp->xmit->Describe)(b, COMP_DIR_XMIT, buf, sizeof(buf)) : ""));
832: Log(LG_CCP, ("[%s] CCP: Decompress using: %s (%s)", b->name, !ccp->recv ? "none" : ccp->recv->name,
833: (ccp->recv && ccp->recv->Describe) ? (*ccp->recv->Describe)(b, COMP_DIR_RECV, buf, sizeof(buf)) : ""));
834:
835: /* Update PPP node config */
836: b->pppConfig.bund.enableCompression = (ccp->xmit != NULL)?ccp->xmit->mode:0;
837: b->pppConfig.bund.enableDecompression = (ccp->recv != NULL)?ccp->recv->mode:0;
838: NgFuncSetConfig(b);
839:
840: /* Update interface MTU */
841: BundUpdateParams(b);
842: }
843:
844: /*
845: * CcpLayerDown()
846: */
847:
848: static void
849: CcpLayerDown(Fsm fp)
850: {
851: Bund b = (Bund)fp->arg;
852: CcpState const ccp = &b->ccp;
853:
854: /* Update PPP node config */
855: b->pppConfig.bund.enableCompression = 0;
856: b->pppConfig.bund.enableDecompression = 0;
857: NgFuncSetConfig(b);
858:
859: /* Update interface MTU */
860: BundUpdateParams(b);
861:
862: if (ccp->xmit != NULL && ccp->xmit->Compress != NULL) {
863: char hook[NG_HOOKSIZ];
864: /* Disconnect hook. */
865: snprintf(hook, sizeof(hook), "c%d", b->id);
866: NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
867: }
868:
869: if (ccp->recv != NULL && ccp->recv->Decompress != NULL) {
870: char hook[NG_HOOKSIZ];
871: /* Disconnect hook. */
872: snprintf(hook, sizeof(hook), "d%d", b->id);
873: NgFuncDisconnect(gCcpCsock, b->name, ".:", hook);
874: }
875: if (ccp->recv && ccp->recv->Cleanup)
876: (*ccp->recv->Cleanup)(b, COMP_DIR_RECV);
877: if (ccp->xmit && ccp->xmit->Cleanup)
878: (*ccp->xmit->Cleanup)(b, COMP_DIR_XMIT);
879:
880: ccp->xmit_resets = 0;
881: ccp->recv_resets = 0;
882: }
883:
884: /*
885: * CcpDecodeConfig()
886: */
887:
888: static void
889: CcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
890: {
891: Bund b = (Bund)fp->arg;
892: CcpState const ccp = &b->ccp;
893: u_int ackSizeSave, rejSizeSave;
894: int k, rej;
895:
896: /* Forget our previous choice on new request */
897: if (mode == MODE_REQ)
898: ccp->recv = NULL;
899:
900: /* Decode each config option */
901: for (k = 0; k < num; k++) {
902: FsmOption const opt = &list[k];
903: int index;
904: CompType ct;
905: char buf[32];
906:
907: Log(LG_CCP, ("[%s] %s", b->name, CcpTypeName(opt->type, buf, sizeof(buf))));
908: if ((ct = CcpFindComp(opt->type, &index)) == NULL) {
909: if (mode == MODE_REQ) {
910: Log(LG_CCP, ("[%s] Not supported", b->name));
911: FsmRej(fp, opt);
912: }
913: continue;
914: }
915: switch (mode) {
916: case MODE_REQ:
917: ackSizeSave = gAckSize;
918: rejSizeSave = gRejSize;
919: rej = (!Acceptable(&ccp->options, index)
920: || CCP_SELF_REJECTED(ccp, index)
921: || (ccp->recv && ccp->recv != ct));
922: if (rej) {
923: (*ct->DecodeConfig)(fp, opt, MODE_NOP);
924: FsmRej(fp, opt);
925: break;
926: }
927: (*ct->DecodeConfig)(fp, opt, mode);
928: if (gRejSize != rejSizeSave) { /* we rejected it */
929: CCP_SELF_REJ(ccp, index);
930: break;
931: }
932: if (gAckSize != ackSizeSave) /* we accepted it */
933: ccp->recv = ct;
934: break;
935:
936: case MODE_REJ:
937: (*ct->DecodeConfig)(fp, opt, mode);
938: CCP_PEER_REJ(ccp, index);
939: break;
940:
941: case MODE_NAK:
942: case MODE_NOP:
943: (*ct->DecodeConfig)(fp, opt, mode);
944: break;
945: }
946: }
947: }
948:
949: /*
950: * CcpSubtractBloat()
951: *
952: * Given that "size" is our MTU, return the maximum length frame
953: * we can compress without the result being longer than "size".
954: */
955:
956: int
957: CcpSubtractBloat(Bund b, int size)
958: {
959: CcpState const ccp = &b->ccp;
960:
961: /* Account for transmit compression overhead */
962: if (OPEN_STATE(ccp->fsm.state) && ccp->xmit && ccp->xmit->SubtractBloat)
963: size = (*ccp->xmit->SubtractBloat)(b, size);
964:
965: /* Account for CCP's protocol number overhead */
966: if (OPEN_STATE(ccp->fsm.state))
967: size -= CCP_OVERHEAD;
968:
969: /* Done */
970: return(size);
971: }
972:
973: /*
974: * CcpCheckEncryption()
975: *
976: * Because MPPE is negotiated as an option to MPPC compression,
977: * we have to check for encryption required when CCP comes up.
978: */
979:
980: static int
981: CcpCheckEncryption(Bund b)
982: {
983: #if 0
984: CcpState const ccp = &b->ccp;
985:
986: /* Already checked? */
987: if (ccp->crypt_check)
988: return(0);
989: ccp->crypt_check = 1;
990:
991: /* Is encryption required? */
992: if (Enabled(&ccp->options, gMppePolicy)) {
993: if (b->params.msoft.policy != MPPE_POLICY_REQUIRED)
994: return(0);
995: } else {
996: if (!Enabled(&b->conf.options, BUND_CONF_CRYPT_REQD))
997: return(0);
998: }
999:
1000: /* Was MPPE encryption enabled? If not, ignore requirement */
1001: if (!Enabled(&ccp->options, gMppe40)
1002: && !Enabled(&ccp->options, gMppe56)
1003: && !Enabled(&ccp->options, gMppe128)
1004: && !Enabled(&ccp->options, gMppePolicy))
1005: return(0);
1006:
1007: /* Make sure MPPE was negotiated in both directions */
1008: if (!OPEN_STATE(ccp->fsm.state)
1009: || !ccp->xmit || ccp->xmit->type != CCP_TY_MPPC
1010: || !ccp->recv || ccp->recv->type != CCP_TY_MPPC
1011: #ifdef CCP_MPPC
1012: || !(ccp->mppc.recv_bits & MPPE_BITS)
1013: || !(ccp->mppc.xmit_bits & MPPE_BITS)
1014: #endif
1015: )
1016: goto fail;
1017:
1018: /* Looks OK */
1019: return(0);
1020:
1021: fail:
1022: Log(LG_ERR, ("[%s] %s: encryption required, but MPPE was not"
1023: " negotiated in both directions", Pref(&ccp->fsm), Fsm(&ccp->fsm)));
1024: FsmFailure(&ccp->fsm, FAIL_CANT_ENCRYPT);
1025: FsmFailure(&b->ipcp.fsm, FAIL_CANT_ENCRYPT);
1026: FsmFailure(&b->ipv6cp.fsm, FAIL_CANT_ENCRYPT);
1027: return(-1);
1028: #endif
1029: return (0);
1030: }
1031:
1032: /*
1033: * CcpSetCommand()
1034: */
1035:
1036: static int
1037: CcpSetCommand(Context ctx, int ac, char *av[], void *arg)
1038: {
1039: CcpState const ccp = &ctx->bund->ccp;
1040:
1041: if (ac == 0)
1042: return(-1);
1043: switch ((intptr_t)arg) {
1044: case SET_ACCEPT:
1045: AcceptCommand(ac, av, &ccp->options, gConfList);
1046: break;
1047:
1048: case SET_DENY:
1049: DenyCommand(ac, av, &ccp->options, gConfList);
1050: break;
1051:
1052: case SET_ENABLE:
1053: EnableCommand(ac, av, &ccp->options, gConfList);
1054: break;
1055:
1056: case SET_DISABLE:
1057: DisableCommand(ac, av, &ccp->options, gConfList);
1058: break;
1059:
1060: case SET_YES:
1061: YesCommand(ac, av, &ccp->options, gConfList);
1062: break;
1063:
1064: case SET_NO:
1065: NoCommand(ac, av, &ccp->options, gConfList);
1066: break;
1067:
1068: default:
1069: assert(0);
1070: }
1071: return(0);
1072: }
1073:
1074: /*
1075: * CcpFindComp()
1076: */
1077:
1078: static CompType
1079: CcpFindComp(int type, int *indexp)
1080: {
1081: int k;
1082:
1083: for (k = 0; k < CCP_NUM_PROTOS; k++) {
1084: if (gCompTypes[k]->type == type) {
1085: if (indexp)
1086: *indexp = k;
1087: return(gCompTypes[k]);
1088: }
1089: }
1090: return(NULL);
1091: }
1092:
1093: /*
1094: * CcpTypeName()
1095: */
1096:
1097: static const char *
1098: CcpTypeName(int type, char *buf, size_t len)
1099: {
1100: const struct ccpname *p;
1101:
1102: for (p = gCcpTypeNames; p->name; p++) {
1103: if (p->type == type) {
1104: strlcpy(buf, p->name, len);
1105: return (buf);
1106: }
1107: }
1108: snprintf(buf, sizeof(buf), "UNKNOWN[%d]", type);
1109: return(buf);
1110: }
1111:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>