File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / pptp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 08:44:29 2013 UTC (11 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, v5_7p0, v5_7, HEAD
5.7

    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, 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]) {
  595: 	ether_ntoa_r((struct ether_addr *)pptp->peer_mac_addr, buf);
  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]) {
  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);
  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>