File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / pptp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (4 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

    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 <net/ethernet.h>
   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,
  130: 				  const char *callingNum,
  131: 				  const char *calledNum);
  132: 
  133:   static struct pptplinkinfo	PptpOutgoing(struct pptpctrlinfo *cinfo,
  134: 				  struct u_addr *self, struct u_addr *peer, in_port_t port,
  135: 				  const char *calledNum);
  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,
  140: 				  const char *calledNum);
  141: 
  142:   static int	PptpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
  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 },
  195:     { NULL, NULL, NULL, NULL, 0, NULL },
  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: 
  213: static struct ghash    *gPptpTuns;
  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: 
  590:     if (buf_len >= 18 && pptp->peer_iface[0]) {
  591: 	ether_ntoa_r((struct ether_addr *)pptp->peer_mac_addr, buf);
  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]) {
  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);
  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;
  783: 
  784:     (void)g;
  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;
  795: 
  796:     (void)g;
  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 *)(void *)(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,
  989: 	const char *callingNum,
  990: 	const char *calledNum)
  991: {
  992:     return(PptpPeerCall(cinfo, self, peer, port, TRUE, callingNum, calledNum));
  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,
 1006: 	struct u_addr *self, struct u_addr *peer, in_port_t port,
 1007: 	const char *calledNum)
 1008: {
 1009:     return(PptpPeerCall(cinfo, self, peer, port, FALSE, "", calledNum));
 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,
 1024: 	const char *calledNum)
 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
 1171: PptpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
 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>