Annotation of embedaddon/mpd/src/pptp.c, revision 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>