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