Annotation of embedaddon/mpd/src/pptp.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * pptp.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 "phys.h"
12: #include "mbuf.h"
13: #include "ngfunc.h"
14: #include "pptp.h"
15: #include "pptp_ctrl.h"
16: #include "log.h"
17: #include "util.h"
18:
19: #include <netgraph/ng_message.h>
20: #include <netgraph/ng_socket.h>
21: #include <netgraph/ng_ksocket.h>
22: #include <netgraph/ng_pptpgre.h>
23: #include <netgraph.h>
24:
25: /*
26: * DEFINITIONS
27: */
28:
29: #define PPTP_MRU PPTP_MTU
30:
31: #define PPTP_CALL_MIN_BPS 56000
32: #define PPTP_CALL_MAX_BPS 64000
33:
34: struct pptptun {
35: struct u_addr self_addr; /* Current self IP address */
36: struct u_addr peer_addr; /* Current peer IP address */
37: ng_ID_t node_id;
38: int refs;
39: };
40: typedef struct pptptun *PptpTun;
41:
42: struct pptpinfo {
43: struct {
44: struct u_addr self_addr; /* self IP address */
45: struct u_range peer_addr; /* Peer IP addresses allowed */
46: in_port_t self_port; /* self port */
47: in_port_t peer_port; /* Peer port required (or zero) */
48: struct optinfo options;
49: char callingnum[64]; /* PPTP phone number to use */
50: char callednum[64]; /* PPTP phone number to use */
51: char *fqdn_peer_addr; /* FQDN Peer address */
52: } conf;
53: void *listener; /* Listener pointer */
54: struct u_addr self_addr; /* Current self IP address */
55: struct u_addr peer_addr; /* Current peer IP address */
56: char peer_iface[IFNAMSIZ]; /* Peer iface */
57: u_char peer_mac_addr[6]; /* Peer MAC address */
58: in_port_t peer_port; /* Current peer port */
59: u_char originate; /* Call originated locally */
60: u_char outcall; /* Call is outgoing vs. incoming */
61: u_char sync; /* Call is sync vs. async */
62: u_int16_t cid; /* call id */
63: PptpTun tun;
64: struct pptpctrlinfo cinfo;
65: char callingnum[64]; /* PPTP phone number to use */
66: char callednum[64]; /* PPTP phone number to use */
67: };
68: typedef struct pptpinfo *PptpInfo;
69:
70: /* Set menu options */
71: enum {
72: SET_SELFADDR,
73: SET_PEERADDR,
74: SET_CALLINGNUM,
75: SET_CALLEDNUM,
76: SET_ENABLE,
77: SET_DISABLE
78: };
79:
80: /* Binary options */
81: enum {
82: PPTP_CONF_OUTCALL, /* when originating, calls are "outgoing" */
83: PPTP_CONF_DELAYED_ACK, /* enable delayed receive ack algorithm */
84: PPTP_CONF_ALWAYS_ACK, /* include ack with all outgoing data packets */
85: PPTP_CONF_RESOLVE_ONCE, /* Only once resolve peer_addr */
86: #if NGM_PPTPGRE_COOKIE >= 1082548365
87: PPTP_CONF_WINDOWING /* control (stupid) windowing algorithm */
88: #endif
89: };
90:
91: /*
92: * INTERNAL FUNCTIONS
93: */
94:
95: static int PptpTInit(void);
96: static void PptpTShutdown(void);
97: static int PptpInit(Link l);
98: static int PptpInst(Link l, Link lt);
99: static void PptpOpen(Link l);
100: static void PptpClose(Link l);
101: static void PptpShutdown(Link l);
102: static void PptpStat(Context ctx);
103: static int PptpOriginated(Link l);
104: static int PptpIsSync(Link l);
105: static int PptpSetAccm(Link l, u_int32_t xmit, u_int32_t recv);
106: static int PptpSetCallingNum(Link l, void *buf);
107: static int PptpSetCalledNum(Link l, void *buf);
108: static int PptpSelfName(Link l, void *buf, size_t buf_len);
109: static int PptpPeerName(Link l, void *buf, size_t buf_len);
110: static int PptpSelfAddr(Link l, void *buf, size_t buf_len);
111: static int PptpPeerAddr(Link l, void *buf, size_t buf_len);
112: static int PptpPeerPort(Link l, void *buf, size_t buf_len);
113: static int PptpPeerMacAddr(Link l, void *buf, size_t buf_len);
114: static int PptpPeerIface(Link l, void *buf, size_t buf_len);
115: static int PptpCallingNum(Link l, void *buf, size_t buf_len);
116: static int PptpCalledNum(Link l, void *buf, size_t buf_len);
117:
118: static int PptpOriginate(Link l);
119: static void PptpDoClose(Link l);
120: static void PptpUnhook(Link l);
121: static void PptpResult(void *cookie, const char *errmsg, int frameType);
122: static void PptpSetLinkInfo(void *cookie, u_int32_t sa, u_int32_t ra);
123: static void PptpCancel(void *cookie);
124: static int PptpHookUp(Link l);
125: static void PptpListenUpdate(Link l);
126:
127: static struct pptplinkinfo PptpIncoming(struct pptpctrlinfo *cinfo,
128: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
129: const char *callingNum,
130: const char *calledNum,
131: const char *subAddress);
132:
133: static struct pptplinkinfo PptpOutgoing(struct pptpctrlinfo *cinfo,
134: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
135: int frameType, int minBps, int maxBps,
136: const char *calledNum,
137: const char *subAddress);
138:
139: static struct pptplinkinfo PptpPeerCall(struct pptpctrlinfo *cinfo,
140: struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
141: const char *callingNum,
142: const char *calledNum,
143: const char *subAddress);
144:
145: static int PptpSetCommand(Context ctx, int ac, char *av[], void *arg);
146: static int PptpTunEQ(struct ghash *g, const void *item1, const void *item2);
147: static u_int32_t PptpTunHash(struct ghash *g, const void *item);
148:
149:
150: /*
151: * GLOBAL VARIABLES
152: */
153:
154: const struct phystype gPptpPhysType = {
155: .name = "pptp",
156: .descr = "Point-to-Point Tunneling Protocol",
157: .mtu = PPTP_MTU,
158: .mru = PPTP_MRU,
159: .tmpl = 1,
160: .tinit = PptpTInit,
161: .tshutdown = PptpTShutdown,
162: .init = PptpInit,
163: .inst = PptpInst,
164: .open = PptpOpen,
165: .close = PptpClose,
166: .update = PptpListenUpdate,
167: .shutdown = PptpShutdown,
168: .showstat = PptpStat,
169: .originate = PptpOriginated,
170: .issync = PptpIsSync,
171: .setaccm = PptpSetAccm,
172: .setcallingnum = PptpSetCallingNum,
173: .setcallednum = PptpSetCalledNum,
174: .selfname = PptpSelfName,
175: .peername = PptpPeerName,
176: .selfaddr = PptpSelfAddr,
177: .peeraddr = PptpPeerAddr,
178: .peerport = PptpPeerPort,
179: .peermacaddr = PptpPeerMacAddr,
180: .peeriface = PptpPeerIface,
181: .callingnum = PptpCallingNum,
182: .callednum = PptpCalledNum,
183: };
184:
185: const struct cmdtab PptpSetCmds[] = {
186: { "self {ip} [{port}]", "Set local IP address",
187: PptpSetCommand, NULL, 2, (void *) SET_SELFADDR },
188: { "peer {ip} [{port}]", "Set remote IP address",
189: PptpSetCommand, NULL, 2, (void *) SET_PEERADDR },
190: { "callingnum {number}", "Set calling PPTP telephone number",
191: PptpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
192: { "callednum {number}", "Set called PPTP telephone number",
193: PptpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
194: { "enable [opt ...]", "Enable option",
195: PptpSetCommand, NULL, 2, (void *) SET_ENABLE },
196: { "disable [opt ...]", "Disable option",
197: PptpSetCommand, NULL, 2, (void *) SET_DISABLE },
198: { NULL },
199: };
200:
201: /*
202: * INTERNAL VARIABLES
203: */
204:
205: static struct confinfo gConfList[] = {
206: { 0, PPTP_CONF_OUTCALL, "outcall" },
207: { 0, PPTP_CONF_DELAYED_ACK, "delayed-ack" },
208: { 0, PPTP_CONF_ALWAYS_ACK, "always-ack" },
209: { 0, PPTP_CONF_RESOLVE_ONCE, "resolve-once" },
210: #if NGM_PPTPGRE_COOKIE >= 1082548365
211: { 0, PPTP_CONF_WINDOWING, "windowing" },
212: #endif
213: { 0, 0, NULL },
214: };
215:
216: struct ghash *gPptpTuns;
217:
218: /*
219: * PptpTInit()
220: */
221:
222: static int
223: PptpTInit(void)
224: {
225: if ((gPptpTuns = ghash_create(NULL, 0, 0, MB_PHYS, PptpTunHash, PptpTunEQ, NULL, NULL))
226: == NULL)
227: return(-1);
228: return (PptpCtrlInit(PptpIncoming, PptpOutgoing));
229: }
230:
231: /*
232: * PptpTShutdown()
233: */
234:
235: static void
236: PptpTShutdown(void)
237: {
238: Log(LG_PHYS2, ("PPTP: Total shutdown"));
239: ghash_destroy(&gPptpTuns);
240: }
241:
242: /*
243: * PptpInit()
244: */
245:
246: static int
247: PptpInit(Link l)
248: {
249: PptpInfo pptp;
250:
251: /* Initialize this link */
252: pptp = (PptpInfo) (l->info = Malloc(MB_PHYS, sizeof(*pptp)));
253:
254: pptp->conf.self_addr.family = AF_INET;
255: pptp->conf.fqdn_peer_addr = NULL;
256: Enable(&pptp->conf.options, PPTP_CONF_OUTCALL);
257: Enable(&pptp->conf.options, PPTP_CONF_DELAYED_ACK);
258: Enable(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE);
259:
260: return(0);
261: }
262:
263: /*
264: * PptpInst()
265: */
266:
267: static int
268: PptpInst(Link l, Link lt)
269: {
270: PptpInfo pptp;
271: PptpInfo const pptpt = (PptpInfo) lt->info;
272:
273: /* Initialize this link */
274: pptp = (PptpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pptp)));
275: if (pptpt->conf.fqdn_peer_addr != NULL)
276: pptp->conf.fqdn_peer_addr =
277: Mstrdup(MB_PHYS, pptpt->conf.fqdn_peer_addr);
278: pptp->listener = NULL;
279:
280: return(0);
281: }
282:
283: /*
284: * PptpOpen()
285: */
286:
287: static void
288: PptpOpen(Link l)
289: {
290: PptpInfo const pptp = (PptpInfo) l->info;
291: struct sockaddr_dl hwa;
292:
293: /* Check state */
294: switch (l->state) {
295: case PHYS_STATE_DOWN:
296: if (PptpOriginate(l) < 0) {
297: Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
298: PhysDown(l, STR_ERROR, NULL);
299: return;
300: }
301: l->state = PHYS_STATE_CONNECTING;
302: break;
303:
304: case PHYS_STATE_CONNECTING:
305: if (pptp->originate) /* our call to peer is already in progress */
306: break;
307: if (pptp->outcall) {
308:
309: /* Hook up nodes */
310: Log(LG_PHYS, ("[%s] PPTP: attaching to peer's outgoing call", l->name));
311: if (PptpHookUp(l) < 0) {
312: PptpDoClose(l);
313: /* We should not set state=DOWN as PptpResult() will be called once more */
314: break;
315: }
316:
317: if (GetPeerEther(&pptp->peer_addr, &hwa)) {
318: if_indextoname(hwa.sdl_index, pptp->peer_iface);
319: memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
320: };
321:
322: (*pptp->cinfo.answer)(pptp->cinfo.cookie,
323: PPTP_OCR_RESL_OK, 0, 0, 64000 /*XXX*/ );
324:
325: /* Report UP if there was no error. */
326: if (l->state == PHYS_STATE_CONNECTING) {
327: l->state = PHYS_STATE_UP;
328: PhysUp(l);
329: }
330: return;
331: }
332: return; /* wait for peer's incoming pptp call to complete */
333:
334: case PHYS_STATE_UP:
335: PhysUp(l);
336: return;
337:
338: default:
339: assert(0);
340: }
341: }
342:
343: /*
344: * PptpOriginate()
345: *
346: * Initiate an "incoming" or an "outgoing" call to the remote site
347: */
348:
349: static int
350: PptpOriginate(Link l)
351: {
352: PptpInfo const pptp = (PptpInfo) l->info;
353: struct pptplinkinfo linfo;
354: const u_short port = pptp->conf.peer_port ?
355: pptp->conf.peer_port : PPTP_PORT;
356:
357: pptp->originate = TRUE;
358: pptp->outcall = Enabled(&pptp->conf.options, PPTP_CONF_OUTCALL);
359: memset(&linfo, 0, sizeof(linfo));
360: linfo.cookie = l;
361: linfo.result = PptpResult;
362: linfo.setLinkInfo = PptpSetLinkInfo;
363: linfo.cancel = PptpCancel;
364: strlcpy(pptp->callingnum, pptp->conf.callingnum, sizeof(pptp->callingnum));
365: strlcpy(pptp->callednum, pptp->conf.callednum, sizeof(pptp->callednum));
366: if ((!Enabled(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE)) &&
367: (pptp->conf.fqdn_peer_addr != NULL)) {
368: struct u_range rng;
369: if (ParseRange(pptp->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
370: pptp->conf.peer_addr = rng;
371: }
372: if (!pptp->outcall) {
373: int frameType = PPTP_FRAMECAP_SYNC;
374: if (l->rep && !RepIsSync(l))
375: frameType = PPTP_FRAMECAP_ASYNC;
376: PptpCtrlInCall(&pptp->cinfo, &linfo,
377: &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
378: PPTP_BEARCAP_ANY, frameType,
379: PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS,
380: pptp->callingnum, pptp->callednum, "");
381: } else {
382: PptpCtrlOutCall(&pptp->cinfo, &linfo,
383: &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
384: PPTP_BEARCAP_ANY, PPTP_FRAMECAP_ANY,
385: PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS,
386: pptp->callednum, "");
387: }
388: if (pptp->cinfo.cookie == NULL)
389: return(-1);
390: pptp->self_addr = pptp->conf.self_addr;
391: pptp->peer_addr = pptp->conf.peer_addr.addr;
392: pptp->peer_port = port;
393: return(0);
394: }
395:
396: /*
397: * PptpClose()
398: */
399:
400: static void
401: PptpClose(Link l)
402: {
403: PptpDoClose(l);
404: }
405:
406: /*
407: * PptpShutdown()
408: */
409:
410: static void
411: PptpShutdown(Link l)
412: {
413: PptpInfo const pptp = (PptpInfo) l->info;
414:
415:
416: if (pptp->conf.fqdn_peer_addr)
417: Freee(pptp->conf.fqdn_peer_addr);
418: if (pptp->listener) {
419: PptpCtrlUnListen(pptp->listener);
420: pptp->listener = NULL;
421: }
422: PptpUnhook(l);
423: Freee(l->info);
424: }
425:
426: /*
427: * PptpDoClose()
428: */
429:
430: static void
431: PptpDoClose(Link l)
432: {
433: PptpInfo const pptp = (PptpInfo) l->info;
434:
435: if (l->state != PHYS_STATE_DOWN) /* avoid double close */
436: (*pptp->cinfo.close)(pptp->cinfo.cookie, PPTP_CDN_RESL_ADMIN, 0, 0);
437: }
438:
439: /*
440: * PptpUnhook()
441: */
442:
443: static void
444: PptpUnhook(Link l)
445: {
446: PptpInfo const pptp = (PptpInfo) l->info;
447: char path[NG_PATHSIZ];
448: int csock = -1;
449:
450: if (pptp->tun == NULL)
451: return;
452:
453: /* Get a temporary netgraph socket node */
454: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
455: Perror("PPTP: NgMkSockNode");
456: return;
457: }
458:
459: pptp->tun->refs--;
460: snprintf(path, sizeof(path), "[%lx]:", (u_long)pptp->tun->node_id);
461: if (pptp->tun->refs == 0) {
462: /* Disconnect session hook. */
463: NgFuncShutdownNode(csock, l->name, path);
464: ghash_remove(gPptpTuns, pptp->tun);
465: Freee(pptp->tun);
466: #ifdef NG_PPTPGRE_HOOK_SESSION_F
467: } else {
468: char hook[NG_HOOKSIZ];
469: snprintf(hook, sizeof(hook), NG_PPTPGRE_HOOK_SESSION_F, pptp->cid);
470: NgFuncDisconnect(csock, l->name, path, hook);
471: #endif
472: }
473:
474: close(csock);
475:
476: pptp->tun = NULL;
477: }
478:
479: /*
480: * PptpOriginated()
481: */
482:
483: static int
484: PptpOriginated(Link l)
485: {
486: PptpInfo const pptp = (PptpInfo) l->info;
487:
488: return(pptp->originate ? LINK_ORIGINATE_LOCAL : LINK_ORIGINATE_REMOTE);
489: }
490:
491: /*
492: * PptpIsSync()
493: */
494:
495: static int
496: PptpIsSync(Link l)
497: {
498: PptpInfo const pptp = (PptpInfo) l->info;
499:
500: return (pptp->sync);
501: }
502:
503: static int
504: PptpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
505: {
506: PptpInfo const pptp = (PptpInfo) l->info;
507:
508: if (!pptp->cinfo.close || !pptp->cinfo.cookie)
509: return (-1);
510:
511: (*pptp->cinfo.setLinkInfo)(pptp->cinfo.cookie, xmit, recv);
512: return (0);
513: }
514:
515: static int
516: PptpSetCallingNum(Link l, void *buf)
517: {
518: PptpInfo const pptp = (PptpInfo) l->info;
519:
520: strlcpy(pptp->conf.callingnum, buf, sizeof(pptp->conf.callingnum));
521: return(0);
522: }
523:
524: static int
525: PptpSetCalledNum(Link l, void *buf)
526: {
527: PptpInfo const pptp = (PptpInfo) l->info;
528:
529: strlcpy(pptp->conf.callednum, buf, sizeof(pptp->conf.callednum));
530: return(0);
531: }
532:
533: static int
534: PptpSelfName(Link l, void *buf, size_t buf_len)
535: {
536: PptpInfo const pptp = (PptpInfo) l->info;
537:
538: if (pptp->cinfo.cookie)
539: return(PptpCtrlGetSelfName(&pptp->cinfo, buf, buf_len));
540: ((char*)buf)[0]=0;
541: return (0);
542: }
543:
544: static int
545: PptpPeerName(Link l, void *buf, size_t buf_len)
546: {
547: PptpInfo const pptp = (PptpInfo) l->info;
548:
549: if (pptp->cinfo.cookie)
550: return(PptpCtrlGetPeerName(&pptp->cinfo, buf, buf_len));
551: ((char*)buf)[0]=0;
552: return (0);
553: }
554:
555: static int
556: PptpSelfAddr(Link l, void *buf, size_t buf_len)
557: {
558: PptpInfo const pptp = (PptpInfo) l->info;
559:
560: if (u_addrtoa(&pptp->self_addr, buf, buf_len))
561: return(0);
562: else
563: return(-1);
564: }
565:
566: static int
567: PptpPeerAddr(Link l, void *buf, size_t buf_len)
568: {
569: PptpInfo const pptp = (PptpInfo) l->info;
570:
571: if (u_addrtoa(&pptp->peer_addr, buf, buf_len))
572: return(0);
573: else
574: return(-1);
575: }
576:
577: static int
578: PptpPeerPort(Link l, void *buf, size_t buf_len)
579: {
580: PptpInfo const pptp = (PptpInfo) l->info;
581:
582: if (snprintf(buf, buf_len, "%d", pptp->peer_port))
583: return(0);
584: else
585: return(-1);
586: }
587:
588: static int
589: PptpPeerMacAddr(Link l, void *buf, size_t buf_len)
590: {
591: PptpInfo const pptp = (PptpInfo) l->info;
592:
593: if (pptp->peer_iface[0]) {
594: snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x",
595: pptp->peer_mac_addr[0], pptp->peer_mac_addr[1],
596: pptp->peer_mac_addr[2], pptp->peer_mac_addr[3],
597: pptp->peer_mac_addr[4], pptp->peer_mac_addr[5]);
598: return (0);
599: }
600: ((char*)buf)[0]=0;
601: return(0);
602: }
603:
604: static int
605: PptpPeerIface(Link l, void *buf, size_t buf_len)
606: {
607: PptpInfo const pptp = (PptpInfo) l->info;
608:
609: if (pptp->peer_iface[0]) {
610: strlcpy(buf, pptp->peer_iface, buf_len);
611: return (0);
612: }
613: ((char*)buf)[0]=0;
614: return(0);
615: }
616:
617: static int
618: PptpCallingNum(Link l, void *buf, size_t buf_len)
619: {
620: PptpInfo const pptp = (PptpInfo) l->info;
621:
622: strlcpy((char*)buf, pptp->callingnum, buf_len);
623: return(0);
624: }
625:
626: static int
627: PptpCalledNum(Link l, void *buf, size_t buf_len)
628: {
629: PptpInfo const pptp = (PptpInfo) l->info;
630:
631: strlcpy((char*)buf, pptp->callednum, buf_len);
632: return(0);
633: }
634:
635: /*
636: * PptpStat()
637: */
638:
639: void
640: PptpStat(Context ctx)
641: {
642: PptpInfo const pptp = (PptpInfo) ctx->lnk->info;
643: char buf[32];
644:
645: Printf("PPTP configuration:\r\n");
646: Printf("\tSelf addr : %s",
647: u_addrtoa(&pptp->conf.self_addr, buf, sizeof(buf)));
648: if (pptp->conf.self_port)
649: Printf(", port %u", pptp->conf.self_port);
650: Printf("\r\n");
651: Printf("\tPeer FQDN : %s\r\n", pptp->conf.fqdn_peer_addr);
652: Printf("\tPeer range : %s",
653: u_rangetoa(&pptp->conf.peer_addr, buf, sizeof(buf)));
654: if (pptp->conf.peer_port)
655: Printf(", port %u", pptp->conf.peer_port);
656: Printf("\r\n");
657: Printf("\tCalling number: %s\r\n", pptp->conf.callingnum);
658: Printf("\tCalled number: %s\r\n", pptp->conf.callednum);
659: Printf("PPTP options:\r\n");
660: OptStat(ctx, &pptp->conf.options, gConfList);
661: Printf("PPTP status:\r\n");
662: if (ctx->lnk->state != PHYS_STATE_DOWN) {
663: Printf("\tIncoming : %s\r\n", (pptp->originate?"NO":"YES"));
664: Printf("\tCurrent self : %s",
665: u_addrtoa(&pptp->self_addr, buf, sizeof(buf)));
666: PptpSelfName(ctx->lnk, buf, sizeof(buf));
667: Printf(" (%s)\r\n", buf);
668: Printf("\tCurrent peer : %s, port %u",
669: u_addrtoa(&pptp->peer_addr, buf, sizeof(buf)), pptp->peer_port);
670: PptpPeerName(ctx->lnk, buf, sizeof(buf));
671: Printf(" (%s)\r\n", buf);
672: if (pptp->peer_iface[0]) {
673: Printf("\tCurrent peer : %02x:%02x:%02x:%02x:%02x:%02x at %s\r\n",
674: pptp->peer_mac_addr[0], pptp->peer_mac_addr[1],
675: pptp->peer_mac_addr[2], pptp->peer_mac_addr[3],
676: pptp->peer_mac_addr[4], pptp->peer_mac_addr[5],
677: pptp->peer_iface);
678: }
679: Printf("\tFraming : %s\r\n", (pptp->sync?"Sync":"Async"));
680: Printf("\tCalling number: %s\r\n", pptp->callingnum);
681: Printf("\tCalled number: %s\r\n", pptp->callednum);
682: }
683: }
684:
685: /*
686: * PptpResult()
687: *
688: * The control code calls this function to report a PPTP link
689: * being connected, disconnected, or failing to connect.
690: */
691:
692: static void
693: PptpResult(void *cookie, const char *errmsg, int frameType)
694: {
695: PptpInfo pptp;
696: Link l;
697: struct sockaddr_dl hwa;
698:
699: /* It this fake call? */
700: if (!cookie)
701: return;
702:
703: l = (Link)cookie;
704: pptp = (PptpInfo) l->info;
705:
706: switch (l->state) {
707: case PHYS_STATE_CONNECTING:
708: if (!errmsg) {
709:
710: /* Hook up nodes */
711: Log(LG_PHYS, ("[%s] PPTP call successful", l->name));
712: if (PptpHookUp(l) < 0) {
713: PptpDoClose(l);
714: /* We should not set state=DOWN as PptpResult() will be called once more */
715: break;
716: }
717:
718: if (pptp->originate && !pptp->outcall)
719: (*pptp->cinfo.connected)(pptp->cinfo.cookie, 64000 /*XXX*/ );
720:
721: /* Report UP if there was no error. */
722: if (l->state == PHYS_STATE_CONNECTING) {
723: if (GetPeerEther(&pptp->peer_addr, &hwa)) {
724: if_indextoname(hwa.sdl_index, pptp->peer_iface);
725: memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
726: };
727:
728: /* OK */
729: l->state = PHYS_STATE_UP;
730: pptp->sync = (frameType&PPTP_FRAMECAP_ASYNC)?0:1;
731: PhysUp(l);
732: }
733: } else {
734: Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
735: PptpUnhook(l); /* For the (*connected)() error. */
736: l->state = PHYS_STATE_DOWN;
737: u_addrclear(&pptp->self_addr);
738: u_addrclear(&pptp->peer_addr);
739: pptp->peer_port = 0;
740: pptp->callingnum[0]=0;
741: pptp->callednum[0]=0;
742: pptp->peer_iface[0] = 0;
743: PhysDown(l, STR_CON_FAILED, errmsg);
744: }
745: break;
746: case PHYS_STATE_UP:
747: assert(errmsg);
748: Log(LG_PHYS, ("[%s] PPTP call terminated", l->name));
749: PptpUnhook(l);
750: l->state = PHYS_STATE_DOWN;
751: u_addrclear(&pptp->self_addr);
752: u_addrclear(&pptp->peer_addr);
753: pptp->peer_port = 0;
754: pptp->callingnum[0]=0;
755: pptp->callednum[0]=0;
756: pptp->peer_iface[0] = 0;
757: PhysDown(l, STR_DROPPED, NULL);
758: break;
759: case PHYS_STATE_DOWN:
760: return;
761: default:
762: assert(0);
763: }
764: }
765:
766: /*
767: * PptpSetLinkInfo()
768: *
769: * Received LinkInfo from peer;
770: */
771:
772: void
773: PptpSetLinkInfo(void *cookie, u_int32_t sa, u_int32_t ra)
774: {
775: Link l;
776:
777: /* It this fake call? */
778: if (!cookie)
779: return;
780:
781: l = (Link)cookie;
782:
783: if (l->rep != NULL)
784: RepSetAccm(l, sa, ra);
785: }
786:
787: static int
788: PptpTunEQ(struct ghash *g, const void *item1, const void *item2)
789: {
790: const struct pptptun *tun1 = item1;
791: const struct pptptun *tun2 = item2;
792: if (u_addrcompare(&tun1->self_addr, &tun2->self_addr) == 0 &&
793: u_addrcompare(&tun1->peer_addr, &tun2->peer_addr) == 0)
794: return (1);
795: return (0);
796: }
797:
798: static u_int32_t
799: PptpTunHash(struct ghash *g, const void *item)
800: {
801: const struct pptptun *tun = item;
802: return (u_addrtoid(&tun->self_addr) + u_addrtoid(&tun->peer_addr));
803: }
804:
805: /*
806: * PptpHookUp()
807: *
808: * Connect the PPTP/GRE node to the PPP node
809: */
810:
811: static int
812: PptpHookUp(Link l)
813: {
814: const PptpInfo pi = (PptpInfo)l->info;
815: char ksockpath[NG_PATHSIZ];
816: char pptppath[NG_PATHSIZ];
817: struct ngm_mkpeer mkp;
818: struct ng_pptpgre_conf gc;
819: struct sockaddr_storage self_addr, peer_addr;
820: struct u_addr u_self_addr, u_peer_addr;
821: union {
822: u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
823: struct ng_ksocket_sockopt ksso;
824: } u;
825: struct ng_ksocket_sockopt *const ksso = &u.ksso;
826: int csock = -1;
827: char path[NG_PATHSIZ];
828: char hook[NG_HOOKSIZ];
829: PptpTun tun = NULL;
830:
831: /* Get session info */
832: memset(&gc, 0, sizeof(gc));
833: PptpCtrlGetSessionInfo(&pi->cinfo, &u_self_addr,
834: &u_peer_addr, &gc.cid, &gc.peerCid, &gc.recvWin, &gc.peerPpd);
835: pi->cid = gc.cid;
836:
837: u_addrtosockaddr(&u_self_addr, 0, &self_addr);
838: u_addrtosockaddr(&u_peer_addr, 0, &peer_addr);
839:
840: if (!PhysGetUpperHook(l, path, hook)) {
841: Log(LG_PHYS, ("[%s] PPTP: can't get upper hook", l->name));
842: return(-1);
843: }
844:
845: /* Get a temporary netgraph socket node */
846: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
847: Perror("PPTP: NgMkSockNode");
848: return(-1);
849: }
850:
851: #ifdef NG_PPTPGRE_HOOK_SESSION_F
852: {
853: struct pptptun tmptun;
854: tmptun.self_addr = u_self_addr;
855: tmptun.peer_addr = u_peer_addr;
856: tun = ghash_get(gPptpTuns, &tmptun);
857: }
858: #endif
859:
860: snprintf(pptppath, sizeof(pptppath), "%s.%s", path, hook);
861: if (tun == NULL) {
862: tun = (PptpTun)Malloc(MB_PHYS, sizeof(*tun));
863: tun->self_addr = u_self_addr;
864: tun->peer_addr = u_peer_addr;
865: if (ghash_put(gPptpTuns, tun) == -1) {
866: Perror("[%s] PPTP: ghash_put", l->name);
867: Freee(tun);
868: close(csock);
869: return(-1);
870: }
871:
872: /* Attach PPTP/GRE node to PPP node */
873: strcpy(mkp.type, NG_PPTPGRE_NODE_TYPE);
874: strlcpy(mkp.ourhook, hook, sizeof(mkp.ourhook));
875: #ifdef NG_PPTPGRE_HOOK_SESSION_F
876: snprintf(mkp.peerhook, sizeof(mkp.peerhook), NG_PPTPGRE_HOOK_SESSION_F, pi->cid);
877: #else
878: strcpy(mkp.peerhook, NG_PPTPGRE_HOOK_UPPER);
879: #endif
880: if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
881: NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
882: Perror("[%s] PPTP: can't attach %s node", l->name, NG_PPTPGRE_NODE_TYPE);
883: ghash_remove(gPptpTuns, tun);
884: Freee(tun);
885: close(csock);
886: return(-1);
887: }
888:
889: /* Get pptpgre node ID */
890: if ((tun->node_id = NgGetNodeID(csock, pptppath)) == 0) {
891: Perror("[%s] Cannot get %s node id", l->name, NG_PPTPGRE_NODE_TYPE);
892: ghash_remove(gPptpTuns, tun);
893: Freee(tun);
894: close(csock);
895: return(-1);
896: };
897: tun->refs++;
898: pi->tun = tun;
899:
900: /* Attach ksocket node to PPTP/GRE node */
901: strcpy(mkp.type, NG_KSOCKET_NODE_TYPE);
902: strcpy(mkp.ourhook, NG_PPTPGRE_HOOK_LOWER);
903: if (u_self_addr.family==AF_INET6) {
904: //ng_ksocket doesn't support inet6 name
905: snprintf(mkp.peerhook, sizeof(mkp.peerhook), "%d/%d/%d", PF_INET6, SOCK_RAW, IPPROTO_GRE);
906: } else {
907: snprintf(mkp.peerhook, sizeof(mkp.peerhook), "inet/raw/gre");
908: }
909: if (NgSendMsg(csock, pptppath, NGM_GENERIC_COOKIE,
910: NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
911: Perror("[%s] PPTP: can't attach %s node", l->name, NG_KSOCKET_NODE_TYPE);
912: close(csock);
913: return(-1);
914: }
915: snprintf(ksockpath, sizeof(ksockpath),
916: "%s.%s", pptppath, NG_PPTPGRE_HOOK_LOWER);
917:
918: /* increase recvspace to avoid packet loss due to very small GRE recv buffer. */
919: ksso->level=SOL_SOCKET;
920: ksso->name=SO_RCVBUF;
921: ((int *)(ksso->value))[0]=48*1024;
922: if (NgSendMsg(csock, ksockpath, NGM_KSOCKET_COOKIE,
923: NGM_KSOCKET_SETOPT, &u, sizeof(u)) < 0) {
924: Perror("[%s] PPTP: can't setsockopt %s node",
925: l->name, NG_KSOCKET_NODE_TYPE);
926: }
927:
928: /* Bind ksocket socket to local IP address */
929: if (NgSendMsg(csock, ksockpath, NGM_KSOCKET_COOKIE,
930: NGM_KSOCKET_BIND, &self_addr, self_addr.ss_len) < 0) {
931: Perror("[%s] PPTP: can't bind() %s node", l->name, NG_KSOCKET_NODE_TYPE);
932: close(csock);
933: return(-1);
934: }
935:
936: /* Connect ksocket socket to remote IP address */
937: if (NgSendMsg(csock, ksockpath, NGM_KSOCKET_COOKIE,
938: NGM_KSOCKET_CONNECT, &peer_addr, peer_addr.ss_len) < 0 &&
939: errno != EINPROGRESS) { /* happens in -current (weird) */
940: Perror("[%s] PPTP: can't connect() %s node",
941: l->name, NG_KSOCKET_NODE_TYPE);
942: close(csock);
943: return(-1);
944: }
945: #ifdef NG_PPTPGRE_HOOK_SESSION_F
946: } else {
947: struct ngm_connect cn;
948: snprintf(cn.path, sizeof(cn.path), "[%x]:", tun->node_id);
949: strlcpy(cn.ourhook, hook, sizeof(mkp.ourhook));
950: snprintf(cn.peerhook, sizeof(mkp.peerhook), NG_PPTPGRE_HOOK_SESSION_F, pi->cid);
951: if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
952: NGM_CONNECT, &cn, sizeof(cn)) < 0) {
953: Perror("[%s] PPTP: can't connect to %s node",
954: l->name, NG_PPTPGRE_NODE_TYPE);
955: close(csock);
956: return(-1);
957: }
958: tun->refs++;
959: pi->tun = tun;
960: #endif
961: }
962:
963: /* Configure PPTP/GRE node */
964: gc.enabled = 1;
965: gc.enableDelayedAck = Enabled(&pi->conf.options, PPTP_CONF_DELAYED_ACK);
966: gc.enableAlwaysAck = Enabled(&pi->conf.options, PPTP_CONF_ALWAYS_ACK);
967: #if NGM_PPTPGRE_COOKIE >= 1082548365
968: gc.enableWindowing = Enabled(&pi->conf.options, PPTP_CONF_WINDOWING);
969: #endif
970:
971: if (NgSendMsg(csock, pptppath, NGM_PPTPGRE_COOKIE,
972: NGM_PPTPGRE_SET_CONFIG, &gc, sizeof(gc)) < 0) {
973: Perror("[%s] PPTP: can't config %s node", l->name, NG_PPTPGRE_NODE_TYPE);
974: close(csock);
975: return(-1);
976: }
977:
978: close(csock);
979:
980: return(0);
981: }
982:
983: /*
984: * PptpIncoming()
985: *
986: * The control code calls this function to report that some
987: * remote PPTP client has asked us if we will accept an incoming
988: * call relayed over PPTP.
989: */
990:
991: static struct pptplinkinfo
992: PptpIncoming(struct pptpctrlinfo *cinfo,
993: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
994: const char *callingNum,
995: const char *calledNum,
996: const char *subAddress)
997: {
998: return(PptpPeerCall(cinfo, self, peer, port, TRUE, callingNum, calledNum, subAddress));
999: }
1000:
1001: /*
1002: * PptpOutgoing()
1003: *
1004: * The control code calls this function to report that some
1005: * remote PPTP client has asked us if we will dial out to some
1006: * phone number. We don't actually do this, but some clients
1007: * initiate their connections as outgoing calls for some reason.
1008: */
1009:
1010: static struct pptplinkinfo
1011: PptpOutgoing(struct pptpctrlinfo *cinfo,
1012: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
1013: int frameType, int minBps, int maxBps,
1014: const char *calledNum, const char *subAddress)
1015: {
1016: return(PptpPeerCall(cinfo, self, peer, port, FALSE, "", calledNum, subAddress));
1017: }
1018:
1019: /*
1020: * PptpPeerCall()
1021: *
1022: * Peer has initiated a call (either incoming or outgoing; either
1023: * way it's the same to us). If we have an available link that may
1024: * accept calls from the peer's IP addresss and port, then say yes.
1025: */
1026:
1027: static struct pptplinkinfo
1028: PptpPeerCall(struct pptpctrlinfo *cinfo,
1029: struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
1030: const char *callingNum,
1031: const char *calledNum,
1032: const char *subAddress)
1033: {
1034: struct pptplinkinfo linfo;
1035: Link l = NULL;
1036: PptpInfo pi = NULL;
1037: int k;
1038:
1039: memset(&linfo, 0, sizeof(linfo));
1040:
1041: linfo.cookie = NULL;
1042: linfo.result = PptpResult;
1043: linfo.setLinkInfo = PptpSetLinkInfo;
1044: linfo.cancel = PptpCancel;
1045:
1046: if (gShutdownInProgress) {
1047: Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
1048: return(linfo);
1049: }
1050:
1051: if (OVERLOAD()) {
1052: Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
1053: return(linfo);
1054: }
1055:
1056: /* Find a suitable link; prefer the link best matching peer's IP address */
1057: for (k = 0; k < gNumLinks; k++) {
1058: Link l2;
1059: PptpInfo pi2;
1060:
1061: if (!gLinks[k] || gLinks[k]->type != &gPptpPhysType)
1062: continue;
1063:
1064: l2 = gLinks[k];
1065: pi2 = (PptpInfo)l2->info;
1066:
1067: /* See if link is feasible */
1068: if ((!PhysIsBusy(l2)) &&
1069: Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
1070: (u_addrempty(&pi2->conf.self_addr) || (u_addrcompare(&pi2->conf.self_addr, self) == 0)) &&
1071: IpAddrInRange(&pi2->conf.peer_addr, peer) &&
1072: (!pi2->conf.peer_port || pi2->conf.peer_port == port)) {
1073:
1074: /* Link is feasible; now see if it's preferable */
1075: if (!pi || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
1076: l = l2;
1077: pi = pi2;
1078: if (u_rangehost(&pi->conf.peer_addr)) {
1079: break; /* Nothing could be better */
1080: }
1081: }
1082: }
1083: }
1084:
1085: if (l != NULL && l->tmpl)
1086: l = LinkInst(l, NULL, 0, 0);
1087:
1088: /* If no link is suitable, can't take the call */
1089: if (l == NULL) {
1090: Log(LG_PHYS, ("No free PPTP link with requested parameters "
1091: "was found"));
1092: return(linfo);
1093: }
1094: pi = (PptpInfo)l->info;
1095:
1096: Log(LG_PHYS, ("[%s] Accepting PPTP connection", l->name));
1097:
1098: /* Got one */
1099: linfo.cookie = l;
1100: l->state = PHYS_STATE_CONNECTING;
1101: pi->cinfo = *cinfo;
1102: pi->originate = FALSE;
1103: pi->outcall = !incoming;
1104: pi->sync = 1;
1105: pi->self_addr = *self;
1106: pi->peer_addr = *peer;
1107: pi->peer_port = port;
1108: strlcpy(pi->callingnum, callingNum, sizeof(pi->callingnum));
1109: strlcpy(pi->callednum, calledNum, sizeof(pi->callednum));
1110:
1111: PhysIncoming(l);
1112: return(linfo);
1113: }
1114:
1115: /*
1116: * PptpCancel()
1117: *
1118: * The control code calls this function to cancel a
1119: * local outgoing call in progress.
1120: */
1121:
1122: static void
1123: PptpCancel(void *cookie)
1124: {
1125: PptpInfo pi;
1126: Link l;
1127:
1128: /* It this fake call? */
1129: if (!cookie)
1130: return;
1131:
1132: l = (Link)cookie;
1133: pi = (PptpInfo) l->info;
1134:
1135: Log(LG_PHYS, ("[%s] PPTP call cancelled in state %s",
1136: l->name, gPhysStateNames[l->state]));
1137: if (l->state == PHYS_STATE_DOWN)
1138: return;
1139: l->state = PHYS_STATE_DOWN;
1140: u_addrclear(&pi->peer_addr);
1141: pi->peer_port = 0;
1142: pi->callingnum[0]=0;
1143: pi->callednum[0]=0;
1144: pi->peer_iface[0] = 0;
1145: PhysDown(l, STR_CON_FAILED0, NULL);
1146: }
1147:
1148: /*
1149: * PptpListenUpdate()
1150: */
1151:
1152: static void
1153: PptpListenUpdate(Link l)
1154: {
1155: PptpInfo pi = (PptpInfo) l->info;
1156:
1157: if (pi->listener == NULL) {
1158: if (Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
1159: /* Set up listening for incoming connections */
1160: if ((pi->listener =
1161: PptpCtrlListen(&pi->conf.self_addr, pi->conf.self_port))
1162: == NULL) {
1163: Log(LG_ERR, ("PPTP: Error, can't listen for connection!"));
1164: }
1165: }
1166: } else {
1167: if (!Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
1168: PptpCtrlUnListen(pi->listener);
1169: pi->listener = NULL;
1170: }
1171: }
1172: }
1173:
1174: /*
1175: * PptpSetCommand()
1176: */
1177:
1178: static int
1179: PptpSetCommand(Context ctx, int ac, char *av[], void *arg)
1180: {
1181: PptpInfo const pi = (PptpInfo) ctx->lnk->info;
1182: char **fqdn_peer_addr = &pi->conf.fqdn_peer_addr;
1183: struct u_range rng;
1184: int port;
1185:
1186: switch ((intptr_t)arg) {
1187: case SET_SELFADDR:
1188: case SET_PEERADDR:
1189: if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
1190: if (*fqdn_peer_addr)
1191: Freee(*fqdn_peer_addr);
1192: *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
1193: }
1194: if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
1195: return(-1);
1196: if (ac > 1) {
1197: if ((port = atoi(av[1])) < 0 || port > 0xffff)
1198: return(-1);
1199: } else {
1200: port = 0;
1201: }
1202: if ((intptr_t)arg == SET_SELFADDR) {
1203: pi->conf.self_addr = rng.addr;
1204: pi->conf.self_port = port;
1205: } else {
1206: pi->conf.peer_addr = rng;
1207: pi->conf.peer_port = port;
1208: }
1209: break;
1210: case SET_CALLINGNUM:
1211: if (ac != 1)
1212: return(-1);
1213: strlcpy(pi->conf.callingnum, av[0], sizeof(pi->conf.callingnum));
1214: break;
1215: case SET_CALLEDNUM:
1216: if (ac != 1)
1217: return(-1);
1218: strlcpy(pi->conf.callednum, av[0], sizeof(pi->conf.callednum));
1219: break;
1220: case SET_ENABLE:
1221: EnableCommand(ac, av, &pi->conf.options, gConfList);
1222: PptpListenUpdate(ctx->lnk);
1223: break;
1224: case SET_DISABLE:
1225: DisableCommand(ac, av, &pi->conf.options, gConfList);
1226: PptpListenUpdate(ctx->lnk);
1227: break;
1228: default:
1229: assert(0);
1230: }
1231: return(0);
1232: }
1233:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>