Annotation of embedaddon/mpd/src/pptp.c, revision 1.1.1.2
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,
129: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
130: const char *callingNum,
131: const char *calledNum,
132: const char *subAddress);
133:
134: static struct pptplinkinfo PptpOutgoing(struct pptpctrlinfo *cinfo,
135: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
136: int frameType, int minBps, int maxBps,
137: const char *calledNum,
138: const char *subAddress);
139:
140: static struct pptplinkinfo PptpPeerCall(struct pptpctrlinfo *cinfo,
141: struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
142: const char *callingNum,
143: const char *calledNum,
144: const char *subAddress);
145:
146: static int PptpSetCommand(Context ctx, int ac, char *av[], void *arg);
147: static int PptpTunEQ(struct ghash *g, const void *item1, const void *item2);
148: static u_int32_t PptpTunHash(struct ghash *g, const void *item);
149:
150:
151: /*
152: * GLOBAL VARIABLES
153: */
154:
155: const struct phystype gPptpPhysType = {
156: .name = "pptp",
157: .descr = "Point-to-Point Tunneling Protocol",
158: .mtu = PPTP_MTU,
159: .mru = PPTP_MRU,
160: .tmpl = 1,
161: .tinit = PptpTInit,
162: .tshutdown = PptpTShutdown,
163: .init = PptpInit,
164: .inst = PptpInst,
165: .open = PptpOpen,
166: .close = PptpClose,
167: .update = PptpListenUpdate,
168: .shutdown = PptpShutdown,
169: .showstat = PptpStat,
170: .originate = PptpOriginated,
171: .issync = PptpIsSync,
172: .setaccm = PptpSetAccm,
173: .setcallingnum = PptpSetCallingNum,
174: .setcallednum = PptpSetCalledNum,
175: .selfname = PptpSelfName,
176: .peername = PptpPeerName,
177: .selfaddr = PptpSelfAddr,
178: .peeraddr = PptpPeerAddr,
179: .peerport = PptpPeerPort,
180: .peermacaddr = PptpPeerMacAddr,
181: .peeriface = PptpPeerIface,
182: .callingnum = PptpCallingNum,
183: .callednum = PptpCalledNum,
184: };
185:
186: const struct cmdtab PptpSetCmds[] = {
187: { "self {ip} [{port}]", "Set local IP address",
188: PptpSetCommand, NULL, 2, (void *) SET_SELFADDR },
189: { "peer {ip} [{port}]", "Set remote IP address",
190: PptpSetCommand, NULL, 2, (void *) SET_PEERADDR },
191: { "callingnum {number}", "Set calling PPTP telephone number",
192: PptpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
193: { "callednum {number}", "Set called PPTP telephone number",
194: PptpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
195: { "enable [opt ...]", "Enable option",
196: PptpSetCommand, NULL, 2, (void *) SET_ENABLE },
197: { "disable [opt ...]", "Disable option",
198: PptpSetCommand, NULL, 2, (void *) SET_DISABLE },
199: { NULL },
200: };
201:
202: /*
203: * INTERNAL VARIABLES
204: */
205:
206: static struct confinfo gConfList[] = {
207: { 0, PPTP_CONF_OUTCALL, "outcall" },
208: { 0, PPTP_CONF_DELAYED_ACK, "delayed-ack" },
209: { 0, PPTP_CONF_ALWAYS_ACK, "always-ack" },
210: { 0, PPTP_CONF_RESOLVE_ONCE, "resolve-once" },
211: #if NGM_PPTPGRE_COOKIE >= 1082548365
212: { 0, PPTP_CONF_WINDOWING, "windowing" },
213: #endif
214: { 0, 0, NULL },
215: };
216:
217: struct ghash *gPptpTuns;
218:
219: /*
220: * PptpTInit()
221: */
222:
223: static int
224: PptpTInit(void)
225: {
226: if ((gPptpTuns = ghash_create(NULL, 0, 0, MB_PHYS, PptpTunHash, PptpTunEQ, NULL, NULL))
227: == NULL)
228: return(-1);
229: return (PptpCtrlInit(PptpIncoming, PptpOutgoing));
230: }
231:
232: /*
233: * PptpTShutdown()
234: */
235:
236: static void
237: PptpTShutdown(void)
238: {
239: Log(LG_PHYS2, ("PPTP: Total shutdown"));
240: ghash_destroy(&gPptpTuns);
241: }
242:
243: /*
244: * PptpInit()
245: */
246:
247: static int
248: PptpInit(Link l)
249: {
250: PptpInfo pptp;
251:
252: /* Initialize this link */
253: pptp = (PptpInfo) (l->info = Malloc(MB_PHYS, sizeof(*pptp)));
254:
255: pptp->conf.self_addr.family = AF_INET;
256: pptp->conf.fqdn_peer_addr = NULL;
257: Enable(&pptp->conf.options, PPTP_CONF_OUTCALL);
258: Enable(&pptp->conf.options, PPTP_CONF_DELAYED_ACK);
259: Enable(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE);
260:
261: return(0);
262: }
263:
264: /*
265: * PptpInst()
266: */
267:
268: static int
269: PptpInst(Link l, Link lt)
270: {
271: PptpInfo pptp;
272: PptpInfo const pptpt = (PptpInfo) lt->info;
273:
274: /* Initialize this link */
275: pptp = (PptpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pptp)));
276: if (pptpt->conf.fqdn_peer_addr != NULL)
277: pptp->conf.fqdn_peer_addr =
278: Mstrdup(MB_PHYS, pptpt->conf.fqdn_peer_addr);
279: pptp->listener = NULL;
280:
281: return(0);
282: }
283:
284: /*
285: * PptpOpen()
286: */
287:
288: static void
289: PptpOpen(Link l)
290: {
291: PptpInfo const pptp = (PptpInfo) l->info;
292: struct sockaddr_dl hwa;
293:
294: /* Check state */
295: switch (l->state) {
296: case PHYS_STATE_DOWN:
297: if (PptpOriginate(l) < 0) {
298: Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
299: PhysDown(l, STR_ERROR, NULL);
300: return;
301: }
302: l->state = PHYS_STATE_CONNECTING;
303: break;
304:
305: case PHYS_STATE_CONNECTING:
306: if (pptp->originate) /* our call to peer is already in progress */
307: break;
308: if (pptp->outcall) {
309:
310: /* Hook up nodes */
311: Log(LG_PHYS, ("[%s] PPTP: attaching to peer's outgoing call", l->name));
312: if (PptpHookUp(l) < 0) {
313: PptpDoClose(l);
314: /* We should not set state=DOWN as PptpResult() will be called once more */
315: break;
316: }
317:
318: if (GetPeerEther(&pptp->peer_addr, &hwa)) {
319: if_indextoname(hwa.sdl_index, pptp->peer_iface);
320: memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
321: };
322:
323: (*pptp->cinfo.answer)(pptp->cinfo.cookie,
324: PPTP_OCR_RESL_OK, 0, 0, 64000 /*XXX*/ );
325:
326: /* Report UP if there was no error. */
327: if (l->state == PHYS_STATE_CONNECTING) {
328: l->state = PHYS_STATE_UP;
329: PhysUp(l);
330: }
331: return;
332: }
333: return; /* wait for peer's incoming pptp call to complete */
334:
335: case PHYS_STATE_UP:
336: PhysUp(l);
337: return;
338:
339: default:
340: assert(0);
341: }
342: }
343:
344: /*
345: * PptpOriginate()
346: *
347: * Initiate an "incoming" or an "outgoing" call to the remote site
348: */
349:
350: static int
351: PptpOriginate(Link l)
352: {
353: PptpInfo const pptp = (PptpInfo) l->info;
354: struct pptplinkinfo linfo;
355: const u_short port = pptp->conf.peer_port ?
356: pptp->conf.peer_port : PPTP_PORT;
357:
358: pptp->originate = TRUE;
359: pptp->outcall = Enabled(&pptp->conf.options, PPTP_CONF_OUTCALL);
360: memset(&linfo, 0, sizeof(linfo));
361: linfo.cookie = l;
362: linfo.result = PptpResult;
363: linfo.setLinkInfo = PptpSetLinkInfo;
364: linfo.cancel = PptpCancel;
365: strlcpy(pptp->callingnum, pptp->conf.callingnum, sizeof(pptp->callingnum));
366: strlcpy(pptp->callednum, pptp->conf.callednum, sizeof(pptp->callednum));
367: if ((!Enabled(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE)) &&
368: (pptp->conf.fqdn_peer_addr != NULL)) {
369: struct u_range rng;
370: if (ParseRange(pptp->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
371: pptp->conf.peer_addr = rng;
372: }
373: if (!pptp->outcall) {
374: int frameType = PPTP_FRAMECAP_SYNC;
375: if (l->rep && !RepIsSync(l))
376: frameType = PPTP_FRAMECAP_ASYNC;
377: PptpCtrlInCall(&pptp->cinfo, &linfo,
378: &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
379: PPTP_BEARCAP_ANY, frameType,
380: PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS,
381: pptp->callingnum, pptp->callednum, "");
382: } else {
383: PptpCtrlOutCall(&pptp->cinfo, &linfo,
384: &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
385: PPTP_BEARCAP_ANY, PPTP_FRAMECAP_ANY,
386: PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS,
387: pptp->callednum, "");
388: }
389: if (pptp->cinfo.cookie == NULL)
390: return(-1);
391: pptp->self_addr = pptp->conf.self_addr;
392: pptp->peer_addr = pptp->conf.peer_addr.addr;
393: pptp->peer_port = port;
394: return(0);
395: }
396:
397: /*
398: * PptpClose()
399: */
400:
401: static void
402: PptpClose(Link l)
403: {
404: PptpDoClose(l);
405: }
406:
407: /*
408: * PptpShutdown()
409: */
410:
411: static void
412: PptpShutdown(Link l)
413: {
414: PptpInfo const pptp = (PptpInfo) l->info;
415:
416:
417: if (pptp->conf.fqdn_peer_addr)
418: Freee(pptp->conf.fqdn_peer_addr);
419: if (pptp->listener) {
420: PptpCtrlUnListen(pptp->listener);
421: pptp->listener = NULL;
422: }
423: PptpUnhook(l);
424: Freee(l->info);
425: }
426:
427: /*
428: * PptpDoClose()
429: */
430:
431: static void
432: PptpDoClose(Link l)
433: {
434: PptpInfo const pptp = (PptpInfo) l->info;
435:
436: if (l->state != PHYS_STATE_DOWN) /* avoid double close */
437: (*pptp->cinfo.close)(pptp->cinfo.cookie, PPTP_CDN_RESL_ADMIN, 0, 0);
438: }
439:
440: /*
441: * PptpUnhook()
442: */
443:
444: static void
445: PptpUnhook(Link l)
446: {
447: PptpInfo const pptp = (PptpInfo) l->info;
448: char path[NG_PATHSIZ];
449: int csock = -1;
450:
451: if (pptp->tun == NULL)
452: return;
453:
454: /* Get a temporary netgraph socket node */
455: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
456: Perror("PPTP: NgMkSockNode");
457: return;
458: }
459:
460: pptp->tun->refs--;
461: snprintf(path, sizeof(path), "[%lx]:", (u_long)pptp->tun->node_id);
462: if (pptp->tun->refs == 0) {
463: /* Disconnect session hook. */
464: NgFuncShutdownNode(csock, l->name, path);
465: ghash_remove(gPptpTuns, pptp->tun);
466: Freee(pptp->tun);
467: #ifdef NG_PPTPGRE_HOOK_SESSION_F
468: } else {
469: char hook[NG_HOOKSIZ];
470: snprintf(hook, sizeof(hook), NG_PPTPGRE_HOOK_SESSION_F, pptp->cid);
471: NgFuncDisconnect(csock, l->name, path, hook);
472: #endif
473: }
474:
475: close(csock);
476:
477: pptp->tun = NULL;
478: }
479:
480: /*
481: * PptpOriginated()
482: */
483:
484: static int
485: PptpOriginated(Link l)
486: {
487: PptpInfo const pptp = (PptpInfo) l->info;
488:
489: return(pptp->originate ? LINK_ORIGINATE_LOCAL : LINK_ORIGINATE_REMOTE);
490: }
491:
492: /*
493: * PptpIsSync()
494: */
495:
496: static int
497: PptpIsSync(Link l)
498: {
499: PptpInfo const pptp = (PptpInfo) l->info;
500:
501: return (pptp->sync);
502: }
503:
504: static int
505: PptpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
506: {
507: PptpInfo const pptp = (PptpInfo) l->info;
508:
509: if (!pptp->cinfo.close || !pptp->cinfo.cookie)
510: return (-1);
511:
512: (*pptp->cinfo.setLinkInfo)(pptp->cinfo.cookie, xmit, recv);
513: return (0);
514: }
515:
516: static int
517: PptpSetCallingNum(Link l, void *buf)
518: {
519: PptpInfo const pptp = (PptpInfo) l->info;
520:
521: strlcpy(pptp->conf.callingnum, buf, sizeof(pptp->conf.callingnum));
522: return(0);
523: }
524:
525: static int
526: PptpSetCalledNum(Link l, void *buf)
527: {
528: PptpInfo const pptp = (PptpInfo) l->info;
529:
530: strlcpy(pptp->conf.callednum, buf, sizeof(pptp->conf.callednum));
531: return(0);
532: }
533:
534: static int
535: PptpSelfName(Link l, void *buf, size_t buf_len)
536: {
537: PptpInfo const pptp = (PptpInfo) l->info;
538:
539: if (pptp->cinfo.cookie)
540: return(PptpCtrlGetSelfName(&pptp->cinfo, buf, buf_len));
541: ((char*)buf)[0]=0;
542: return (0);
543: }
544:
545: static int
546: PptpPeerName(Link l, void *buf, size_t buf_len)
547: {
548: PptpInfo const pptp = (PptpInfo) l->info;
549:
550: if (pptp->cinfo.cookie)
551: return(PptpCtrlGetPeerName(&pptp->cinfo, buf, buf_len));
552: ((char*)buf)[0]=0;
553: return (0);
554: }
555:
556: static int
557: PptpSelfAddr(Link l, void *buf, size_t buf_len)
558: {
559: PptpInfo const pptp = (PptpInfo) l->info;
560:
561: if (u_addrtoa(&pptp->self_addr, buf, buf_len))
562: return(0);
563: else
564: return(-1);
565: }
566:
567: static int
568: PptpPeerAddr(Link l, void *buf, size_t buf_len)
569: {
570: PptpInfo const pptp = (PptpInfo) l->info;
571:
572: if (u_addrtoa(&pptp->peer_addr, buf, buf_len))
573: return(0);
574: else
575: return(-1);
576: }
577:
578: static int
579: PptpPeerPort(Link l, void *buf, size_t buf_len)
580: {
581: PptpInfo const pptp = (PptpInfo) l->info;
582:
583: if (snprintf(buf, buf_len, "%d", pptp->peer_port))
584: return(0);
585: else
586: return(-1);
587: }
588:
589: static int
590: PptpPeerMacAddr(Link l, void *buf, size_t buf_len)
591: {
592: PptpInfo const pptp = (PptpInfo) l->info;
593:
594: if (pptp->peer_iface[0]) {
1.1.1.2 ! misho 595: ether_ntoa_r((struct ether_addr *)pptp->peer_mac_addr, buf);
1.1 misho 596: return (0);
597: }
598: ((char*)buf)[0]=0;
599: return(0);
600: }
601:
602: static int
603: PptpPeerIface(Link l, void *buf, size_t buf_len)
604: {
605: PptpInfo const pptp = (PptpInfo) l->info;
606:
607: if (pptp->peer_iface[0]) {
608: strlcpy(buf, pptp->peer_iface, buf_len);
609: return (0);
610: }
611: ((char*)buf)[0]=0;
612: return(0);
613: }
614:
615: static int
616: PptpCallingNum(Link l, void *buf, size_t buf_len)
617: {
618: PptpInfo const pptp = (PptpInfo) l->info;
619:
620: strlcpy((char*)buf, pptp->callingnum, buf_len);
621: return(0);
622: }
623:
624: static int
625: PptpCalledNum(Link l, void *buf, size_t buf_len)
626: {
627: PptpInfo const pptp = (PptpInfo) l->info;
628:
629: strlcpy((char*)buf, pptp->callednum, buf_len);
630: return(0);
631: }
632:
633: /*
634: * PptpStat()
635: */
636:
637: void
638: PptpStat(Context ctx)
639: {
640: PptpInfo const pptp = (PptpInfo) ctx->lnk->info;
641: char buf[32];
642:
643: Printf("PPTP configuration:\r\n");
644: Printf("\tSelf addr : %s",
645: u_addrtoa(&pptp->conf.self_addr, buf, sizeof(buf)));
646: if (pptp->conf.self_port)
647: Printf(", port %u", pptp->conf.self_port);
648: Printf("\r\n");
649: Printf("\tPeer FQDN : %s\r\n", pptp->conf.fqdn_peer_addr);
650: Printf("\tPeer range : %s",
651: u_rangetoa(&pptp->conf.peer_addr, buf, sizeof(buf)));
652: if (pptp->conf.peer_port)
653: Printf(", port %u", pptp->conf.peer_port);
654: Printf("\r\n");
655: Printf("\tCalling number: %s\r\n", pptp->conf.callingnum);
656: Printf("\tCalled number: %s\r\n", pptp->conf.callednum);
657: Printf("PPTP options:\r\n");
658: OptStat(ctx, &pptp->conf.options, gConfList);
659: Printf("PPTP status:\r\n");
660: if (ctx->lnk->state != PHYS_STATE_DOWN) {
661: Printf("\tIncoming : %s\r\n", (pptp->originate?"NO":"YES"));
662: Printf("\tCurrent self : %s",
663: u_addrtoa(&pptp->self_addr, buf, sizeof(buf)));
664: PptpSelfName(ctx->lnk, buf, sizeof(buf));
665: Printf(" (%s)\r\n", buf);
666: Printf("\tCurrent peer : %s, port %u",
667: u_addrtoa(&pptp->peer_addr, buf, sizeof(buf)), pptp->peer_port);
668: PptpPeerName(ctx->lnk, buf, sizeof(buf));
669: Printf(" (%s)\r\n", buf);
670: if (pptp->peer_iface[0]) {
1.1.1.2 ! misho 671: ether_ntoa_r((struct ether_addr *)pptp->peer_mac_addr, buf);
! 672: Printf("\tCurrent peer : %s at %s\r\n", buf, pptp->peer_iface);
1.1 misho 673: }
674: Printf("\tFraming : %s\r\n", (pptp->sync?"Sync":"Async"));
675: Printf("\tCalling number: %s\r\n", pptp->callingnum);
676: Printf("\tCalled number: %s\r\n", pptp->callednum);
677: }
678: }
679:
680: /*
681: * PptpResult()
682: *
683: * The control code calls this function to report a PPTP link
684: * being connected, disconnected, or failing to connect.
685: */
686:
687: static void
688: PptpResult(void *cookie, const char *errmsg, int frameType)
689: {
690: PptpInfo pptp;
691: Link l;
692: struct sockaddr_dl hwa;
693:
694: /* It this fake call? */
695: if (!cookie)
696: return;
697:
698: l = (Link)cookie;
699: pptp = (PptpInfo) l->info;
700:
701: switch (l->state) {
702: case PHYS_STATE_CONNECTING:
703: if (!errmsg) {
704:
705: /* Hook up nodes */
706: Log(LG_PHYS, ("[%s] PPTP call successful", l->name));
707: if (PptpHookUp(l) < 0) {
708: PptpDoClose(l);
709: /* We should not set state=DOWN as PptpResult() will be called once more */
710: break;
711: }
712:
713: if (pptp->originate && !pptp->outcall)
714: (*pptp->cinfo.connected)(pptp->cinfo.cookie, 64000 /*XXX*/ );
715:
716: /* Report UP if there was no error. */
717: if (l->state == PHYS_STATE_CONNECTING) {
718: if (GetPeerEther(&pptp->peer_addr, &hwa)) {
719: if_indextoname(hwa.sdl_index, pptp->peer_iface);
720: memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
721: };
722:
723: /* OK */
724: l->state = PHYS_STATE_UP;
725: pptp->sync = (frameType&PPTP_FRAMECAP_ASYNC)?0:1;
726: PhysUp(l);
727: }
728: } else {
729: Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
730: PptpUnhook(l); /* For the (*connected)() error. */
731: l->state = PHYS_STATE_DOWN;
732: u_addrclear(&pptp->self_addr);
733: u_addrclear(&pptp->peer_addr);
734: pptp->peer_port = 0;
735: pptp->callingnum[0]=0;
736: pptp->callednum[0]=0;
737: pptp->peer_iface[0] = 0;
738: PhysDown(l, STR_CON_FAILED, errmsg);
739: }
740: break;
741: case PHYS_STATE_UP:
742: assert(errmsg);
743: Log(LG_PHYS, ("[%s] PPTP call terminated", l->name));
744: PptpUnhook(l);
745: l->state = PHYS_STATE_DOWN;
746: u_addrclear(&pptp->self_addr);
747: u_addrclear(&pptp->peer_addr);
748: pptp->peer_port = 0;
749: pptp->callingnum[0]=0;
750: pptp->callednum[0]=0;
751: pptp->peer_iface[0] = 0;
752: PhysDown(l, STR_DROPPED, NULL);
753: break;
754: case PHYS_STATE_DOWN:
755: return;
756: default:
757: assert(0);
758: }
759: }
760:
761: /*
762: * PptpSetLinkInfo()
763: *
764: * Received LinkInfo from peer;
765: */
766:
767: void
768: PptpSetLinkInfo(void *cookie, u_int32_t sa, u_int32_t ra)
769: {
770: Link l;
771:
772: /* It this fake call? */
773: if (!cookie)
774: return;
775:
776: l = (Link)cookie;
777:
778: if (l->rep != NULL)
779: RepSetAccm(l, sa, ra);
780: }
781:
782: static int
783: PptpTunEQ(struct ghash *g, const void *item1, const void *item2)
784: {
785: const struct pptptun *tun1 = item1;
786: const struct pptptun *tun2 = item2;
787: if (u_addrcompare(&tun1->self_addr, &tun2->self_addr) == 0 &&
788: u_addrcompare(&tun1->peer_addr, &tun2->peer_addr) == 0)
789: return (1);
790: return (0);
791: }
792:
793: static u_int32_t
794: PptpTunHash(struct ghash *g, const void *item)
795: {
796: const struct pptptun *tun = item;
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;
916: ((int *)(ksso->value))[0]=48*1024;
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,
988: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
989: const char *callingNum,
990: const char *calledNum,
991: const char *subAddress)
992: {
993: return(PptpPeerCall(cinfo, self, peer, port, TRUE, callingNum, calledNum, subAddress));
994: }
995:
996: /*
997: * PptpOutgoing()
998: *
999: * The control code calls this function to report that some
1000: * remote PPTP client has asked us if we will dial out to some
1001: * phone number. We don't actually do this, but some clients
1002: * initiate their connections as outgoing calls for some reason.
1003: */
1004:
1005: static struct pptplinkinfo
1006: PptpOutgoing(struct pptpctrlinfo *cinfo,
1007: struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
1008: int frameType, int minBps, int maxBps,
1009: const char *calledNum, const char *subAddress)
1010: {
1011: return(PptpPeerCall(cinfo, self, peer, port, FALSE, "", calledNum, subAddress));
1012: }
1013:
1014: /*
1015: * PptpPeerCall()
1016: *
1017: * Peer has initiated a call (either incoming or outgoing; either
1018: * way it's the same to us). If we have an available link that may
1019: * accept calls from the peer's IP addresss and port, then say yes.
1020: */
1021:
1022: static struct pptplinkinfo
1023: PptpPeerCall(struct pptpctrlinfo *cinfo,
1024: struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
1025: const char *callingNum,
1026: const char *calledNum,
1027: const char *subAddress)
1028: {
1029: struct pptplinkinfo linfo;
1030: Link l = NULL;
1031: PptpInfo pi = NULL;
1032: int k;
1033:
1034: memset(&linfo, 0, sizeof(linfo));
1035:
1036: linfo.cookie = NULL;
1037: linfo.result = PptpResult;
1038: linfo.setLinkInfo = PptpSetLinkInfo;
1039: linfo.cancel = PptpCancel;
1040:
1041: if (gShutdownInProgress) {
1042: Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
1043: return(linfo);
1044: }
1045:
1046: if (OVERLOAD()) {
1047: Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
1048: return(linfo);
1049: }
1050:
1051: /* Find a suitable link; prefer the link best matching peer's IP address */
1052: for (k = 0; k < gNumLinks; k++) {
1053: Link l2;
1054: PptpInfo pi2;
1055:
1056: if (!gLinks[k] || gLinks[k]->type != &gPptpPhysType)
1057: continue;
1058:
1059: l2 = gLinks[k];
1060: pi2 = (PptpInfo)l2->info;
1061:
1062: /* See if link is feasible */
1063: if ((!PhysIsBusy(l2)) &&
1064: Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
1065: (u_addrempty(&pi2->conf.self_addr) || (u_addrcompare(&pi2->conf.self_addr, self) == 0)) &&
1066: IpAddrInRange(&pi2->conf.peer_addr, peer) &&
1067: (!pi2->conf.peer_port || pi2->conf.peer_port == port)) {
1068:
1069: /* Link is feasible; now see if it's preferable */
1070: if (!pi || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
1071: l = l2;
1072: pi = pi2;
1073: if (u_rangehost(&pi->conf.peer_addr)) {
1074: break; /* Nothing could be better */
1075: }
1076: }
1077: }
1078: }
1079:
1080: if (l != NULL && l->tmpl)
1081: l = LinkInst(l, NULL, 0, 0);
1082:
1083: /* If no link is suitable, can't take the call */
1084: if (l == NULL) {
1085: Log(LG_PHYS, ("No free PPTP link with requested parameters "
1086: "was found"));
1087: return(linfo);
1088: }
1089: pi = (PptpInfo)l->info;
1090:
1091: Log(LG_PHYS, ("[%s] Accepting PPTP connection", l->name));
1092:
1093: /* Got one */
1094: linfo.cookie = l;
1095: l->state = PHYS_STATE_CONNECTING;
1096: pi->cinfo = *cinfo;
1097: pi->originate = FALSE;
1098: pi->outcall = !incoming;
1099: pi->sync = 1;
1100: pi->self_addr = *self;
1101: pi->peer_addr = *peer;
1102: pi->peer_port = port;
1103: strlcpy(pi->callingnum, callingNum, sizeof(pi->callingnum));
1104: strlcpy(pi->callednum, calledNum, sizeof(pi->callednum));
1105:
1106: PhysIncoming(l);
1107: return(linfo);
1108: }
1109:
1110: /*
1111: * PptpCancel()
1112: *
1113: * The control code calls this function to cancel a
1114: * local outgoing call in progress.
1115: */
1116:
1117: static void
1118: PptpCancel(void *cookie)
1119: {
1120: PptpInfo pi;
1121: Link l;
1122:
1123: /* It this fake call? */
1124: if (!cookie)
1125: return;
1126:
1127: l = (Link)cookie;
1128: pi = (PptpInfo) l->info;
1129:
1130: Log(LG_PHYS, ("[%s] PPTP call cancelled in state %s",
1131: l->name, gPhysStateNames[l->state]));
1132: if (l->state == PHYS_STATE_DOWN)
1133: return;
1134: l->state = PHYS_STATE_DOWN;
1135: u_addrclear(&pi->peer_addr);
1136: pi->peer_port = 0;
1137: pi->callingnum[0]=0;
1138: pi->callednum[0]=0;
1139: pi->peer_iface[0] = 0;
1140: PhysDown(l, STR_CON_FAILED0, NULL);
1141: }
1142:
1143: /*
1144: * PptpListenUpdate()
1145: */
1146:
1147: static void
1148: PptpListenUpdate(Link l)
1149: {
1150: PptpInfo pi = (PptpInfo) l->info;
1151:
1152: if (pi->listener == NULL) {
1153: if (Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
1154: /* Set up listening for incoming connections */
1155: if ((pi->listener =
1156: PptpCtrlListen(&pi->conf.self_addr, pi->conf.self_port))
1157: == NULL) {
1158: Log(LG_ERR, ("PPTP: Error, can't listen for connection!"));
1159: }
1160: }
1161: } else {
1162: if (!Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
1163: PptpCtrlUnListen(pi->listener);
1164: pi->listener = NULL;
1165: }
1166: }
1167: }
1168:
1169: /*
1170: * PptpSetCommand()
1171: */
1172:
1173: static int
1174: PptpSetCommand(Context ctx, int ac, char *av[], void *arg)
1175: {
1176: PptpInfo const pi = (PptpInfo) ctx->lnk->info;
1177: char **fqdn_peer_addr = &pi->conf.fqdn_peer_addr;
1178: struct u_range rng;
1179: int port;
1180:
1181: switch ((intptr_t)arg) {
1182: case SET_SELFADDR:
1183: case SET_PEERADDR:
1184: if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
1185: if (*fqdn_peer_addr)
1186: Freee(*fqdn_peer_addr);
1187: *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
1188: }
1189: if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
1190: return(-1);
1191: if (ac > 1) {
1192: if ((port = atoi(av[1])) < 0 || port > 0xffff)
1193: return(-1);
1194: } else {
1195: port = 0;
1196: }
1197: if ((intptr_t)arg == SET_SELFADDR) {
1198: pi->conf.self_addr = rng.addr;
1199: pi->conf.self_port = port;
1200: } else {
1201: pi->conf.peer_addr = rng;
1202: pi->conf.peer_port = port;
1203: }
1204: break;
1205: case SET_CALLINGNUM:
1206: if (ac != 1)
1207: return(-1);
1208: strlcpy(pi->conf.callingnum, av[0], sizeof(pi->conf.callingnum));
1209: break;
1210: case SET_CALLEDNUM:
1211: if (ac != 1)
1212: return(-1);
1213: strlcpy(pi->conf.callednum, av[0], sizeof(pi->conf.callednum));
1214: break;
1215: case SET_ENABLE:
1216: EnableCommand(ac, av, &pi->conf.options, gConfList);
1217: PptpListenUpdate(ctx->lnk);
1218: break;
1219: case SET_DISABLE:
1220: DisableCommand(ac, av, &pi->conf.options, gConfList);
1221: PptpListenUpdate(ctx->lnk);
1222: break;
1223: default:
1224: assert(0);
1225: }
1226: return(0);
1227: }
1228:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>