1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/* -----------------------------------------------------------------------------
25 *
26 *  Theory of operation :
27 *
28 *  plugin to add PPTP client support to pppd.
29 *
30----------------------------------------------------------------------------- */
31
32
33/* -----------------------------------------------------------------------------
34  Includes
35----------------------------------------------------------------------------- */
36
37#include <stdio.h>
38#include <ctype.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42#include <signal.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <syslog.h>
46#include <netdb.h>
47#include <pwd.h>
48#include <setjmp.h>
49#include <sys/param.h>
50#include <sys/types.h>
51#include <sys/wait.h>
52#include <sys/time.h>
53#include <sys/resource.h>
54#include <sys/socket.h>
55#include <sys/stat.h>
56#include <sys/socket.h>
57#include <sys/sysctl.h>
58#include <netinet/in.h>
59#include <arpa/inet.h>
60#include <syslog.h>
61#include <sys/ioctl.h>
62#include <net/if.h>
63#include <net/if_media.h>
64#include <net/route.h>
65#include <pthread.h>
66#include <sys/kern_event.h>
67#include <netinet/in_var.h>
68#include <netinet/tcp.h>
69#include <net/if_dl.h>
70#include <ifaddrs.h>
71
72#include <CoreFoundation/CFNumber.h>
73#include <CoreFoundation/CFBundle.h>
74#include <SystemConfiguration/SystemConfiguration.h>
75
76#define APPLE 1
77
78#include "../../../Controller/ppp_msg.h"
79#include "../../../Family/ppp_defs.h"
80#include "../../../Family/if_ppp.h"
81#include "../../../Family/ppp_domain.h"
82#include "../PPTP-extension/PPTP.h"
83#include "../../../Helpers/pppd/pppd.h"
84#include "../../../Helpers/pppd/fsm.h"
85#include "../../../Helpers/pppd/lcp.h"
86#include "pptp.h"
87
88#if TARGET_OS_EMBEDDED
89#include <CoreTelephony/CTServerConnectionPriv.h>
90#endif
91
92/* -----------------------------------------------------------------------------
93 Definitions
94----------------------------------------------------------------------------- */
95
96#define MODE_CONNECT	"connect"
97#define MODE_LISTEN	"listen"
98#define MODE_ANSWER	"answer"
99
100#define PPTP_MIN_HDR_SIZE 44		/* IPHdr(20) + GRE(16) + PPP/MPPE(8) */
101
102#define	PPTP_RETRY_CONNECT_CODE			1
103
104#define PPTP_DEFAULT_WAIT_IF_TIMEOUT      20 /* seconds */
105
106#define MAX_CONNECT_RETRIES 10
107
108/* -----------------------------------------------------------------------------
109 Forward declarations
110----------------------------------------------------------------------------- */
111
112void pptp_process_extra_options();
113void pptp_check_options();
114int  pptp_pre_start_link_check();
115int pptp_connect(int *errorcode);
116void pptp_disconnect();
117void pptp_close();
118void pptp_cleanup();
119int pptp_establish_ppp(int);
120void pptp_wait_input();
121void pptp_disestablish_ppp(int);
122void pptp_link_down(void *arg, uintptr_t p);
123
124static void pptp_echo_check();
125static void pptp_stop_echo_check();
126static void pptp_echo_timeout(void *arg);
127static void pptp_send_echo_request();
128static void pptp_link_failure();
129static void closeall();
130static u_long load_kext(char *kext, int byBundleID);
131static boolean_t host_gateway(int cmd, struct in_addr host, struct in_addr gateway, char *ifname, int isnet);
132static int pptp_set_peer_route();
133static int pptp_clean_peer_route();
134static void pptp_ip_up(void *arg, uintptr_t p);
135u_int32_t pptp_get_if_baudrate(char *if_name);
136u_int32_t pptp_get_if_media(char *if_name);
137u_int32_t pptp_get_if_mtu(char *if_name);
138static void pptp_start_wait_interface ();
139static void pptp_stop_wait_interface ();
140static void pptp_wait_interface_timeout (void *arg);
141static void enable_keepalive (int fd);
142
143
144/* -----------------------------------------------------------------------------
145 PPP globals
146----------------------------------------------------------------------------- */
147
148int     interface_media = 0;
149
150static int 	ctrlsockfd = -1;		/* control socket (TCP) file descriptor */
151static int 	datasockfd = -1;		/* data socket (GRE) file descriptor */
152static int 	eventsockfd = -1;		/* event socket to detect interface change */
153static CFBundleRef 	bundle = 0;		/* our bundle ref */
154
155/* option variables */
156static char 	*mode = MODE_CONNECT;		/* connect mode by default */
157static bool 	noload = 0;			/* don't load the kernel extension */
158
159static u_int16_t our_call_id = 0;		/* pptp call id */
160static u_int16_t peer_call_id = 0;		/* pptp peer's calld id */
161static u_int16_t our_window = PPTP_RECEIVE_WINDOW;/* our receive window size */
162static u_int16_t peer_ppd = 0;			/* peer packet processing delay */
163static u_int16_t our_ppd = 0;			/* our packet processing delay */
164static u_int16_t peer_window = 0;		/* peer's receive window size */
165static u_int16_t maxtimeout = 64;		/* Maximum adaptative timeout (in seconds) */
166static struct in_addr peeraddress;		/* the other side IP address */
167static int            num_alt_peer_address = 0;
168static struct in_addr alt_peer_address[MAX_CONNECT_RETRIES];		/* the other side IP address */
169static struct sockaddr_in ouraddress;		/* our side IP address */
170static struct in_addr ip_zeros = { 0 };
171static u_int8_t routeraddress[16];
172static u_int8_t interface[17];
173static pthread_t resolverthread = 0;
174static int 	resolverfds[2];
175#if TARGET_OS_EMBEDDED
176static pthread_t edgethread = 0;
177static int 	edgefds[2];
178#endif
179static bool	linkdown = 0; 			/* flag set when we receive link down event */
180static int 	peer_route_set = 0;		/* has a route to the peer been set ? */
181static int	transport_up = 1;
182static int	wait_interface_timer_running = 0;
183
184/*
185Fast echo request procedure is run when a networking change is detected
186Echos are sent every 5 seconds for 30 seconds, or until a reply is received
187If the network is detected dead, the the tunnel is disconnected.
188Echos are not sent during normal operation.
189*/
190static int	echo_interval = 5; 		/* Interval between echo-requests */
191static int	echo_fails = 6;		/* Tolerance to unanswered echo-requests */
192static int	echo_timer_running = 0;
193static int 	echos_pending = 0;
194static int	echo_identifier = 0;
195static int	echo_active = 0;
196static int	tcp_keepalive = 0;
197static int	wait_if_timeout = PPTP_DEFAULT_WAIT_IF_TIMEOUT;
198static int	scaled_wait_if_timeout = PPTP_DEFAULT_WAIT_IF_TIMEOUT;
199
200extern int 		kill_link;
201extern CFStringRef	serviceidRef;		/* from pppd/sys_MacOSX.c */
202extern SCDynamicStoreRef cfgCache;		/* from pppd/sys_MacOSX.c */
203
204/* option descriptors */
205option_t pptp_options[] = {
206    { "nopptpload", o_bool, &noload,
207      "Don't try to load the PPTP kernel extension", 1 },
208    { "pptpmode", o_string, &mode,
209      "Configure configuration mode [connect, listen, answer]" },
210    { "pptpmaxtimeout", o_int, &maxtimeout,
211      "Maximum adaptative timeout" },
212    { "pptp-fast-echo-interval", o_int, &echo_interval,
213      "Fast echo interval to reassert link" },
214    { "pptp-fast-echo-failure", o_int, &echo_fails,
215      "Fast echo failure to reassert link" },
216    { "pptp-tcp-keepalive", o_int, &tcp_keepalive,
217      "TCP keepalive interval" },
218    { "pptpwaitiftimeout", o_int, &wait_if_timeout,
219      "How long do we wait for our transport interface to come back after interface events" },
220    { NULL }
221};
222
223
224void pptp_init_session __P((char *, u_int32_t, struct in_addr *, link_failure_func));
225
226static ppp_session_t pptp_session = PPP_SESSION_INITIALIZER();
227
228/* -----------------------------------------------------------------------------
229plugin entry point, called by pppd
230----------------------------------------------------------------------------- */
231int start(CFBundleRef ref)
232{
233
234    bundle = ref;
235    CFRetain(bundle);
236
237    // hookup our socket handlers
238    bzero(the_channel, sizeof(struct channel));
239    the_channel->options = pptp_options;
240    the_channel->process_extra_options = pptp_process_extra_options;
241    the_channel->wait_input = pptp_wait_input;
242    the_channel->check_options = pptp_check_options;
243    the_channel->pre_start_link_check = pptp_pre_start_link_check;
244    the_channel->connect = pptp_connect;
245    the_channel->disconnect = pptp_disconnect;
246    the_channel->cleanup = pptp_cleanup;
247    the_channel->close = pptp_close;
248    the_channel->establish_ppp = pptp_establish_ppp;
249    the_channel->disestablish_ppp = pptp_disestablish_ppp;
250    // use the default config functions
251    the_channel->send_config = generic_send_config;
252    the_channel->recv_config = generic_recv_config;
253
254    add_notifier(&link_down_notifier, pptp_link_down, 0);
255    add_notifier(&ip_up_notify, pptp_ip_up, 0);
256
257    return 0;
258}
259
260/* -----------------------------------------------------------------------------
261----------------------------------------------------------------------------- */
262void pptp_process_extra_options()
263{
264    if (!strcmp(mode, MODE_ANSWER)) {
265        // make sure we get a file descriptor > 2 so that pppd can detach and close 0,1,2
266        ctrlsockfd = dup(0);
267    }
268}
269
270/* -----------------------------------------------------------------------------
271do consistency checks on the options we were given
272----------------------------------------------------------------------------- */
273void pptp_check_options()
274{
275    if (strcmp(mode, MODE_CONNECT)
276        && strcmp(mode, MODE_LISTEN)
277        && strcmp(mode, MODE_ANSWER)) {
278        error("PPTP incorrect mode : '%s'", mode ? mode : "");
279        mode = MODE_CONNECT;
280    }
281
282	/*
283		reuse pppd redial functionality to retry connection
284		retry every 3 seconds for the duration of the extra time
285		do not report busy state
286	 */
287	if (extraconnecttime) {
288		busycode = PPTP_RETRY_CONNECT_CODE;
289		redialtimer = 3 ;
290		redialcount = extraconnecttime / redialtimer;
291		hasbusystate = 0;
292	}
293
294}
295
296/* -----------------------------------------------------------------------------
297----------------------------------------------------------------------------- */
298void pptp_link_down(void *arg, uintptr_t p)
299{
300    linkdown = 1;
301}
302
303/* -----------------------------------------------------------------------------
304----------------------------------------------------------------------------- */
305static void pptp_start_wait_interface ()
306{
307    int timeout_scale_factor = 0;
308
309    if (!wait_underlying_interface_up && lcp_echo_interval) {
310        wait_underlying_interface_up = 1;
311    }
312    // the interface timer takes priority over the mapping timer
313    ppp_block_public_nat_port_mapping_timer();
314
315    if (wait_interface_timer_running != 0)
316        return;
317
318#if !TARGET_OS_EMBEDDED
319    // increase the timeout if we're waiting for a wireless interface
320    if (IFM_TYPE(interface_media) == IFM_IEEE80211) {
321        timeout_scale_factor = 2;
322    }
323#endif /* !iPhone */
324    scaled_wait_if_timeout = (wait_if_timeout << timeout_scale_factor);
325    notice("starting wait-interface timer for pptp: %d secs", scaled_wait_if_timeout);
326    TIMEOUT (pptp_wait_interface_timeout, 0, scaled_wait_if_timeout);
327    wait_interface_timer_running = 1;
328}
329
330/* -----------------------------------------------------------------------------
331----------------------------------------------------------------------------- */
332static void pptp_stop_wait_interface ()
333{
334    ppp_variable_echo_start();
335
336    if (wait_interface_timer_running) {
337        UNTIMEOUT (pptp_wait_interface_timeout, 0);
338        wait_interface_timer_running = 0;
339    }
340    ppp_unblock_public_nat_port_mapping_timer();
341}
342
343/* -----------------------------------------------------------------------------
344----------------------------------------------------------------------------- */
345static void pptp_wait_interface_timeout (void *arg)
346{
347    if (wait_interface_timer_running != 0) {
348        wait_interface_timer_running = 0;
349		log_vpn_interface_address_event(__FUNCTION__, NULL, scaled_wait_if_timeout, interface, &ouraddress.sin_addr);
350		// our transport interface didn't come back, take down the connection
351		pptp_link_failure();
352    }
353}
354
355/* -----------------------------------------------------------------------------
356called back everytime we go out of select, and data needs to be read
357the hook is called and has a chance to get data out of its file descriptor
358in the case of PPTP, we get control data on the socket
359or get awaken when connection is closed
360----------------------------------------------------------------------------- */
361void pptp_wait_input()
362{
363    int err, found;
364    struct ifaddrs *ifap = NULL;
365
366#if 0
367    // Code removed. See radar 9129161
368    if (linkdown && !hungup) {
369        notice("PPTP linkdown");
370        pptp_link_failure();
371        return;
372    }
373#endif
374
375    if (eventsockfd != -1 && is_ready_fd(eventsockfd)) {
376
377		char                 	buf[256] __attribute__ ((aligned(4)));		// Wcast-align fix - force alignment
378		char                 	ev_if[32];
379        struct kern_event_msg	*ev_msg;
380        struct kev_in_data     	*inetdata;
381
382        if (recv(eventsockfd, &buf, sizeof(buf), 0) != -1) {
383            ev_msg = ALIGNED_CAST(struct kern_event_msg *) &buf;
384            inetdata = (struct kev_in_data *) &ev_msg->event_data[0];
385			log_vpn_interface_address_event(__FUNCTION__, ev_msg, wait_if_timeout, interface, &ouraddress.sin_addr);
386            switch (ev_msg->event_code) {
387                case KEV_INET_NEW_ADDR:
388                case KEV_INET_CHANGED_ADDR:
389                case KEV_INET_ADDR_DELETED:
390                    snprintf(ev_if, sizeof(ev_if), "%s%d", inetdata->link_data.if_name, inetdata->link_data.if_unit);
391                    // check if changes occured on the interface we are using
392                    if (!strncmp(ev_if, (char*)interface, sizeof(interface))) {
393                        if (inetdata->link_data.if_family == APPLE_IF_FAM_PPP
394                            || echo_interval == 0
395                            || echo_fails == 0) {
396                            // disconnect immediatly
397                            pptp_link_failure();
398                        }
399                        else {
400
401                            /* check if address still exist */
402                            found = 0;
403                            if (getifaddrs(&ifap) == 0) {
404                                struct ifaddrs *ifa;
405                                for (ifa = ifap; ifa && !found ; ifa = ifa->ifa_next) {
406                                    found = (ifa->ifa_name
407                                            && ifa->ifa_addr
408                                            && !strncmp(ifa->ifa_name, (char*)interface, sizeof(interface))
409                                            && ifa->ifa_addr->sa_family == AF_INET
410                                            && (ALIGNED_CAST(struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == ouraddress.sin_addr.s_addr);
411                                }
412                                freeifaddrs(ifap);
413                            }
414
415							if (found) {
416
417								// no meaningful change, or address came back. Cancel timer if it was on.
418								if (transport_up == 0) {
419
420									/*
421										Our transport interface comes back with the same address.
422										Stop waiting for interface.
423										A smarter algorithm should be implemented here.
424									*/
425									transport_up = 1;
426									if (phase == PHASE_WAITING)
427										new_phase(PHASE_RUNNING);
428									pptp_stop_wait_interface();
429
430									// give time to check for connectivity
431									/* Clear the parameters for generating echo frames */
432									echos_pending      = 0;
433									echo_active = 1;
434
435									/* If a timeout interval is specified then start the timer */
436									if (echo_interval != 0)
437										pptp_echo_check();
438								}
439							}
440							else {
441								// quick exit if there has been an unrecoverable change in interface/service
442								if (check_vpn_interface_or_service_unrecoverable(cfgCache,
443														 __FUNCTION__,
444														 ev_msg,
445														 (char*)interface)) {
446									error("PPTP: the underlying interface/service has changed unrecoverably\n");
447									transport_up = 0;
448									pptp_link_failure();
449									break;
450								}
451
452								if (transport_up == 1) {
453									transport_up = 0;
454									if (phase == PHASE_RUNNING)
455										new_phase(PHASE_WAITING);
456									pptp_start_wait_interface();
457								} else {
458								        // transport is still down: check if there was a valid address change
459								        if (check_vpn_interface_address_change(wait_interface_timer_running /* && !transport_up */,
460													       ev_msg,
461													       (char*)interface,
462														   interface_media,
463													       &ouraddress.sin_addr)) {
464									        error("PPTP: the underlying interface %s address changed\n",
465										      interface);
466										// disconnect immediately
467										pptp_link_failure();
468									}
469								}
470                            }
471
472                        }
473                    } else {
474		            /* if transport is still down: ignore deletes, and check if this alternative interface has a valid address */
475		            if (check_vpn_interface_alternate((!transport_up && wait_interface_timer_running),
476							      ev_msg,
477							      (char*)interface)) {
478			            error("PPTP: an alternative interface %s was detected while the underlying interface %s was down\n",
479					  ev_if, interface);
480				    // disconnect immediately
481				    pptp_link_failure();
482			    }
483                    }
484                    break;
485            }
486        }
487    }
488
489    if (ctrlsockfd != -1 && is_ready_fd(ctrlsockfd)) {
490
491       err = pptp_data_in(ctrlsockfd);
492       if (err < 0) {
493            // looks like we have been disconnected...
494            // the status is updated only if link is not already down
495            if (linkdown == 0) {
496                notice("PPTP hangup");
497                status = EXIT_HANGUP;
498            }
499            remove_fd(ctrlsockfd);
500            remove_fd(eventsockfd);
501            hungup = 1;
502            lcp_lowerdown(0);	/* PPTP link is no longer available */
503            link_terminated(0);
504            ppp_auxiliary_probe_stop();
505            pptp_clear_nat_port_mapping();
506			ppp_session_clear(&pptp_session);
507            session = NULL;
508	   }
509    }
510
511	ppp_process_nat_port_mapping_events();
512	ppp_process_auxiliary_probe_input();
513}
514
515/* -----------------------------------------------------------------------------
516----------------------------------------------------------------------------- */
517void *pptp_resolver_thread(void *arg)
518{
519    struct hostent 	*host;
520    char		result = -1;
521	int			count, fd;
522	u_int8_t	rd8;
523
524    if (pthread_detach(pthread_self()) == 0) {
525
526        // try to resolve the name
527        if ((host = gethostbyname(remoteaddress))) {
528
529			for (count = 0; host->h_addr_list[count]; count++);
530
531			rd8 = 0;
532			fd = open("/dev/random", O_RDONLY);
533			if (fd) {
534				read(fd, &rd8, sizeof(rd8));
535				close(fd);
536			}
537
538			bzero(&peeraddress, sizeof(peeraddress));
539			if (count)
540				peeraddress = *ALIGNED_CAST(struct in_addr*)host->h_addr_list[rd8 % count];
541            bzero(alt_peer_address, sizeof(alt_peer_address));
542            num_alt_peer_address = 0;
543            if (count > 1) {
544                while (num_alt_peer_address < (count - 1) &&
545                       num_alt_peer_address < MAX_CONNECT_RETRIES) {
546                    alt_peer_address[num_alt_peer_address] = *ALIGNED_CAST(struct in_addr*)host->h_addr_list[(rd8 + num_alt_peer_address + 1)% count];
547                    num_alt_peer_address++;
548                }
549            }
550            result = 0;
551        }
552    }
553
554    write(resolverfds[1], &result, 1);
555    return 0;
556}
557
558#if TARGET_OS_EMBEDDED
559static
560void callbackEDGE(CTServerConnectionRef connection, CFStringRef notification, CFDictionaryRef notificationInfo, void* info) {
561
562	/* not used */
563}
564
565/* -----------------------------------------------------------------------------
566 ----------------------------------------------------------------------------- */
567void *pptp_edge_thread(void *arg)
568{
569    char		result = -1;
570	int			count;
571	CTServerConnectionRef	edgeConnection;
572	_CTServerConnectionContext ctxt = { 0, NULL, NULL, NULL, NULL };
573	Boolean active = FALSE;
574	CTError cterror = { kCTErrorDomainNoError, 0 };
575
576    if (pthread_detach(pthread_self()) == 0) {
577
578		edgeConnection = _CTServerConnectionCreate(kCFAllocatorDefault, callbackEDGE, &ctxt);
579		if (edgeConnection) {
580			_CTServerConnectionSetPacketContextActiveByServiceType(edgeConnection, kCTDataConnectionServiceTypeInternet, TRUE);
581
582			count = PPPD_WWAN_INTERFACE_TIMEOUT;
583			cterror = _CTServerConnectionGetPacketContextActive(edgeConnection, 0, &active);
584			while (!cterror.error && !active && count--) {
585				sleep(1);
586				cterror = _CTServerConnectionGetPacketContextActive(edgeConnection, 0, &active);
587			}
588			CFRelease(edgeConnection);
589
590			if (active) {
591				sleep(2); // additionnal 2 seconds for DNS information to be installed
592				result = 0;
593			}
594		}
595	}
596
597
598    write(edgefds[1], &result, 1);
599    return 0;
600}
601#endif
602
603int pptp_pre_start_link_check()
604{
605    int                      reachable = FALSE;
606    SCNetworkReachabilityRef ref;
607    SCNetworkConnectionFlags flags;
608
609    ref = SCNetworkReachabilityCreateWithName(NULL, remoteaddress);
610    if (ref) {
611        if (SCNetworkReachabilityGetFlags(ref, &flags)) {
612            if (REACHABLE_NOW || REACHABLE_AUTOMATICALLY_WITHOUT_USER) {
613                reachable = TRUE;
614            }
615        }
616        CFRelease(ref);
617    }
618
619    if (reachable) {
620        return 0;
621    }
622    return -1;
623}
624
625/* -----------------------------------------------------------------------------
626get the socket ready to start doing PPP.
627That is, open the socket and start the PPTP dialog
628----------------------------------------------------------------------------- */
629int pptp_connect(int *errorcode)
630{
631    char 		dev[32], name[MAXPATHLEN], c;
632    int 		err = 0, fd, val;
633	uint32_t    len;
634    CFURLRef		url;
635    CFDictionaryRef	dict;
636    CFStringRef		string, key;
637    struct sockaddr_in 	addr;
638    struct kev_request	kev_req;
639    u_int32_t		baudrate;
640    int             num_connect_retries = 0;
641    int             connect_timeout = 15;
642
643	*errorcode = 0;
644
645    if (cfgCache == NULL || serviceidRef == NULL) {
646        goto fail;
647    }
648
649    snprintf(dev, sizeof(dev), "socket[%d:%d]", PF_PPP, PPPPROTO_PPTP);
650    strlcpy(ppp_devnam, dev, sizeof(ppp_devnam));
651
652    hungup = 0;
653    kill_link = 0;
654    linkdown = 0;
655    our_call_id = getpid();
656    routeraddress[0] = 0;
657    interface[0] = 0;
658
659    key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
660    if (key) {
661        dict = SCDynamicStoreCopyValue(cfgCache, key);
662	CFRelease(key);
663        if (dict) {
664            if ((string  = CFDictionaryGetValue(dict, kSCPropNetIPv4Router)))
665                CFStringGetCString(string, (char*)routeraddress, sizeof(routeraddress), kCFStringEncodingUTF8);
666            if ((string  = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface)))
667                CFStringGetCString(string, (char*)interface, sizeof(interface), kCFStringEncodingUTF8);
668            CFRelease(dict);
669        }
670    }
671
672	/* now that we know our interface, adjust the MTU if necessary */
673	if (interface[0]) {
674		int min_mtu = pptp_get_if_mtu((char*)interface) - PPTP_MIN_HDR_SIZE;
675		if (lcp_allowoptions[0].mru > min_mtu)	/* defines out mtu */
676			lcp_allowoptions[0].mru = min_mtu;
677
678		/* Don't adjust MRU, radar 3974763 */
679#if 0
680		if (lcp_wantoptions[0].mru > min_mtu)	/* defines out mru */
681			lcp_wantoptions[0].mru = min_mtu;
682		if (lcp_wantoptions[0].neg_mru > min_mtu)	/* defines our mru */
683			lcp_wantoptions[0].neg_mru = min_mtu;
684#endif
685	}
686
687#if !TARGET_OS_EMBEDDED
688    interface_media = pptp_get_if_media((char*)interface);
689#endif /* !iPhone */
690
691	// check to see if interface is captive: if so, bail if the interface is not ready.
692	if (check_vpn_interface_captive_and_not_ready(cfgCache, (char *)interface)) {
693		// TODO: perhaps we should wait for a few seconds?
694		goto fail;
695	}
696
697	/* let's say our underlying transport is up */
698	transport_up = 1;
699	wait_interface_timer_running = 0;
700	wait_underlying_interface_up = 0;
701	ppp_session_clear(&pptp_session);
702	session = NULL;
703
704    eventsockfd = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
705    if (eventsockfd != -1) {
706        // PPTP can survive without event socket anyway
707        kev_req.vendor_code = KEV_VENDOR_APPLE;
708        kev_req.kev_class = KEV_NETWORK_CLASS;
709        kev_req.kev_subclass = KEV_INET_SUBCLASS;
710        ioctl(eventsockfd, SIOCSKEVFILT, &kev_req);
711    }
712
713    /* -------------------------------------------------------------*/
714    /* connect mode : we need a valid remote address or name */
715    if (!strcmp(mode, MODE_CONNECT)) {
716        if (remoteaddress == 0) {
717            error("PPTP: No remote address supplied...\n");
718            devstatus = EXIT_PPTP_NOSERVER;
719            goto fail;
720        }
721
722		set_network_signature("VPN.RemoteAddress", remoteaddress, 0, 0);
723
724#if TARGET_OS_EMBEDDED
725		{
726			/* first, bring up EDGE */
727			int need_edge = FALSE;
728			SCNetworkReachabilityRef ref = NULL;
729			SCNetworkConnectionFlags	flags;
730
731			ref = SCNetworkReachabilityCreateWithName(NULL, remoteaddress);
732			if (ref) {
733
734				if (SCNetworkReachabilityGetFlags(ref, &flags)) {
735					if ((flags & kSCNetworkReachabilityFlagsReachable) &&
736						(flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
737						(flags & kSCNetworkReachabilityFlagsIsWWAN)) {
738						need_edge = TRUE;
739					}
740				}
741				CFRelease(ref);
742			}
743
744			if (need_edge) {
745
746				if (pipe(edgefds) < 0) {
747					error("PPTP: failed to create pipe for starting edge...\n");
748					goto fail;
749				}
750
751				if (pthread_create(&edgethread, NULL, pptp_edge_thread, NULL)) {
752					error("PPTP: failed to create thread for starting edge...\n");
753					close(edgefds[0]);
754					close(edgefds[1]);
755					goto fail;
756				}
757
758				while (read(edgefds[0], &c, 1) != 1) {
759					if (kill_link) {
760						pthread_cancel(edgethread);
761						break;
762					}
763				}
764
765				close(edgefds[0]);
766				close(edgefds[1]);
767
768				if (kill_link)
769					goto fail1;
770
771				if (c) {
772					error("PPTP: Cannot start EDGE connection...\n");
773					*errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */
774					devstatus = EXIT_PPTP_NOEDGE;
775					goto fail;
776				}
777
778			}
779
780		}
781#endif
782
783        if (inet_aton(remoteaddress, &peeraddress) == 0) {
784
785            if (pipe(resolverfds) < 0) {
786                error("PPTP: failed to create pipe for gethostbyname...\n");
787                goto fail;
788            }
789
790            if (pthread_create(&resolverthread, NULL, pptp_resolver_thread, NULL)) {
791                error("PPTP: failed to create thread for gethostbyname...\n");
792                close(resolverfds[0]);
793                close(resolverfds[1]);
794                goto fail;
795            }
796
797            while (read(resolverfds[0], &c, 1) != 1) {
798                if (kill_link) {
799                    pthread_cancel(resolverthread);
800                    break;
801                }
802            }
803
804            close(resolverfds[0]);
805            close(resolverfds[1]);
806
807            if (kill_link)
808                goto fail1;
809
810            if (c) {
811                error("PPTP: Host '%s' not found...\n", remoteaddress);
812				*errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */
813                devstatus = EXIT_PPTP_NOSERVER;
814                goto fail;
815            }
816        }
817
818        notice("PPTP connecting to server '%s' (%s)...\n", remoteaddress, inet_ntoa(peeraddress));
819
820        set_server_peer(peeraddress);
821
822        if ((ctrlsockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
823            error("PPTP can't create control socket...\n");
824            goto fail;
825        }
826        // TODO: make connection_timeout configurable
827        if (setsockopt(ctrlsockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &connect_timeout, sizeof(connect_timeout))) {
828            error("PPTP can't set control socket's maximum timeout ...\n");
829            // prevent retries since the default 90 sec is *too* long
830            num_alt_peer_address = 0;
831        }
832
833        /* connect to the pptp server */
834        bzero(&addr, sizeof(addr));
835        addr.sin_len = sizeof(addr);
836        addr.sin_family = AF_INET;
837        addr.sin_port = htons(PPTP_TCP_PORT);
838        addr.sin_addr = peeraddress;
839
840        while (connect(ctrlsockfd, (struct sockaddr *)&addr, sizeof(addr))) {
841            if (errno != EINTR) {
842                error("PPTP connect errno = %d %m\n", errno);
843                if ((errno == ETIMEDOUT || errno == ECONNREFUSED) &&
844                    num_connect_retries < num_alt_peer_address) {
845                    peeraddress = alt_peer_address[num_connect_retries];
846                    notice("PPTP connecting to alternate server '%s' (%s)...\n", remoteaddress, inet_ntoa(peeraddress));
847                    set_server_peer(peeraddress);
848                    addr.sin_addr = peeraddress;
849                    num_connect_retries++;
850                    continue;
851                }
852                *errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */
853                devstatus = EXIT_PPTP_NOANSWER;
854                goto fail;
855            }
856            if (kill_link)
857                goto fail1;
858        }
859
860		/* enable keepalive on control connection. need to be done before sending data */
861		enable_keepalive(ctrlsockfd);
862
863        err = pptp_outgoing_call(ctrlsockfd,
864            our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd);
865
866        /* setup the specific route */
867        pptp_set_peer_route();
868    }
869    /* -------------------------------------------------------------*/
870    /* answer mode : we need a valid remote address or name */
871    else if (!strcmp(mode, MODE_ANSWER)) {
872        len = sizeof(addr);
873        if (getpeername(ctrlsockfd, (struct sockaddr *)&addr, &len) < 0) {
874            error("PPTP: cannot get client address... %m\n");
875            //devstatus = EXIT_PPTP_NOSERVER;
876            goto fail;
877        }
878        peeraddress = addr.sin_addr;
879        remoteaddress = inet_ntoa(peeraddress);
880
881        notice("PPTP incoming call in progress from '%s'...", remoteaddress);
882
883		/* enable keepalive on control connection. need to be done before sending data */
884		enable_keepalive(ctrlsockfd);
885
886        err = pptp_incoming_call(ctrlsockfd,
887            our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd);
888    }
889    /* -------------------------------------------------------------*/
890    else if (!strcmp(mode, MODE_LISTEN)) {
891
892        notice("PPTP listening...\n");
893
894        if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
895            error("PPTP can't create listening socket...\n");
896            goto fail;
897        }
898
899        val = 1;
900        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
901
902        bzero(&addr, sizeof(addr));
903        addr.sin_len = sizeof(addr);
904        addr.sin_family = AF_INET;
905        addr.sin_port = htons(PPTP_TCP_PORT);
906        addr.sin_addr.s_addr = INADDR_ANY;
907        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
908            error("PPTP bind failed, %m");
909            goto fail;
910        }
911
912        if (listen(fd, 10) < 0) {
913            error("PPTP listen failed, %m");
914            return errno;
915        }
916
917        len = sizeof(addr);
918        ctrlsockfd = accept(fd, (struct sockaddr *)&addr, &len);
919        close(fd);	// close the socket used for listening
920        if (ctrlsockfd < 0) {
921            error("PPTP accept failed, %m");
922            goto fail;
923        }
924
925        peeraddress = addr.sin_addr;
926        remoteaddress = inet_ntoa(peeraddress);
927
928        notice("PPTP incoming call in progress from '%s'...", remoteaddress);
929
930		/* enable keepalive on control connection. need to be done before sending data */
931		enable_keepalive(ctrlsockfd);
932
933        err = pptp_incoming_call(ctrlsockfd,
934                our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd);
935    }
936
937    if (err) {
938        if (err != -2) {
939            if (err != -1)
940                devstatus = err;
941            goto fail;
942        }
943        goto fail1;
944    }
945
946    notice("PPTP connection established.");
947
948	bzero(&ouraddress, sizeof(ouraddress));
949	len = sizeof(ouraddress);
950	getsockname(ctrlsockfd, (struct sockaddr *)&ouraddress, &len);
951
952    /* get reachability flags of peer */
953    bzero(&addr, sizeof(addr));
954    addr.sin_len = sizeof(addr);
955    addr.sin_family = AF_INET;
956    addr.sin_port = htons(PPTP_TCP_PORT);
957    addr.sin_addr = peeraddress;
958
959    /* open the data socket */
960    datasockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_PPTP);
961    if (datasockfd < 0) {
962        if (!noload) {
963            if ((url = CFBundleCopyBundleURL(bundle))) {
964                name[0] = 0;
965                CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)name, MAXPATHLEN - 1);
966                CFRelease(url);
967                strlcat(name, "/", sizeof(name));
968                if ((url = CFBundleCopyBuiltInPlugInsURL(bundle))) {
969                    CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)(name + strlen(name)),
970                        MAXPATHLEN - strlen(name) - strlen(PPTP_NKE) - 1);
971                    CFRelease(url);
972                    strlcat(name, "/", sizeof(name));
973                    strlcat(name, PPTP_NKE, sizeof(name));
974#if !TARGET_OS_EMBEDDED
975                    if (!load_kext(name, 0))
976#else
977                    if (!load_kext(PPTP_NKE_ID, 1))
978#endif
979                        datasockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_PPTP);
980                }
981            }
982        }
983        if (datasockfd < 0) {
984            error("Failed to open PPTP socket: %m");
985            goto fail;
986       }
987    }
988
989    if (kdebugflag & 1) {
990        u_int32_t 	flags;
991        flags = debug ? PPTP_FLAG_DEBUG : 0;
992        if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_FLAGS, &flags, 4)) {
993            error("PPTP can't set PPTP flags...\n");
994            goto fail;
995        }
996    }
997
998    len = sizeof(addr);
999    if (getsockname(ctrlsockfd, (struct sockaddr *)&addr, &len) < 0) {
1000        error("PPTP: cannot get our address... %m\n");
1001        goto fail;
1002    }
1003    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_OURADDRESS, &addr.sin_addr.s_addr, 4)) {
1004        error("PPTP can't set our PPTP address...\n");
1005        goto fail;
1006    }
1007    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEERADDRESS, &peeraddress.s_addr, 4)) {
1008        error("PPTP can't set PPTP server address...\n");
1009        goto fail;
1010    }
1011
1012	baudrate = pptp_get_if_baudrate((char*)interface);
1013	if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_BAUDRATE, &baudrate, 4)) {
1014        error("PPTP can't set our baudrate...\n");
1015        goto fail;
1016    }
1017
1018    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_CALL_ID, &our_call_id, 2)) {
1019        error("PPTP can't set our call id...\n");
1020        goto fail;
1021    }
1022
1023    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_CALL_ID, &peer_call_id, 2)) {
1024        error("PPTP can't set peer call id...\n");
1025        goto fail;
1026    }
1027    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_WINDOW, &our_window, 2)) {
1028        error("PPTP can't set our receive window size...\n");
1029        goto fail;
1030    }
1031    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_WINDOW, &peer_window, 2)) {
1032        error("PPTP can't set peer receive window size...\n");
1033        goto fail;
1034    }
1035    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_PPD, &peer_ppd, 2)) {
1036        error("PPTP can't set peer packet processing delay ...\n");
1037        goto fail;
1038    }
1039    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_MAXTIMEOUT, &maxtimeout, 2)) {
1040        error("PPTP can't set adaptative maximum timeout ...\n");
1041        goto fail;
1042    }
1043
1044    if (!strcmp(mode, MODE_CONNECT)) {
1045        pptp_init_session((char *)interface, sizeof(interface), &ouraddress.sin_addr, ppp_variable_echo_start);
1046        pptp_set_nat_port_mapping();
1047    }
1048
1049    return datasockfd;
1050
1051fail:
1052    status = EXIT_CONNECT_FAILED;
1053fail1:
1054    if (eventsockfd != -1) {
1055        close(eventsockfd);
1056        eventsockfd = -1;
1057    }
1058    if (ctrlsockfd != -1) {
1059        close(ctrlsockfd);
1060        ctrlsockfd = -1;
1061    }
1062    return -1;
1063}
1064
1065/* -----------------------------------------------------------------------------
1066run the disconnector
1067----------------------------------------------------------------------------- */
1068void pptp_disconnect()
1069{
1070    notice("PPTP disconnecting...\n");
1071
1072    if (eventsockfd != -1) {
1073        close(eventsockfd);
1074        eventsockfd = -1;
1075    }
1076    if (ctrlsockfd >= 0) {
1077        close(ctrlsockfd);
1078        ctrlsockfd = -1;
1079    }
1080
1081    ppp_auxiliary_probe_stop();
1082    pptp_clear_nat_port_mapping();
1083    ppp_session_clear(&pptp_session);
1084    session = NULL;
1085
1086    notice("PPTP disconnected\n");
1087}
1088
1089/* -----------------------------------------------------------------------------
1090close the socket descriptors
1091----------------------------------------------------------------------------- */
1092void pptp_close()
1093{
1094
1095	pptp_stop_echo_check();
1096
1097    if (eventsockfd != -1) {
1098        close(eventsockfd);
1099        eventsockfd = -1;
1100    }
1101    if (datasockfd >= 0) {
1102        close(datasockfd);
1103        datasockfd = -1;
1104    }
1105    if (ctrlsockfd >= 0) {
1106        close(ctrlsockfd);
1107        ctrlsockfd = -1;
1108    }
1109}
1110
1111/* -----------------------------------------------------------------------------
1112clean up before quitting
1113----------------------------------------------------------------------------- */
1114void pptp_cleanup()
1115{
1116    pptp_close();
1117    pptp_clean_peer_route();
1118}
1119
1120/* -----------------------------------------------------------------------------
1121establish the socket as a ppp link
1122----------------------------------------------------------------------------- */
1123int pptp_establish_ppp(int fd)
1124{
1125    int x, new_fd;
1126
1127    if (ioctl(fd, PPPIOCATTACH, &x) < 0) {
1128        error("Couldn't attach socket to the link layer: %m");
1129        return -1;
1130    }
1131
1132    new_fd = generic_establish_ppp(fd, interface);
1133    if (new_fd == -1)
1134        return -1;
1135
1136    // add just the control socket to the select
1137    // the data socket is just for moving data in the kernel
1138    add_fd(ctrlsockfd);
1139    add_fd(eventsockfd);
1140    return new_fd;
1141}
1142
1143/* -----------------------------------------------------------------------------
1144disestablish the socket as a ppp link
1145----------------------------------------------------------------------------- */
1146void pptp_disestablish_ppp(int fd)
1147{
1148    int 	x;
1149
1150    remove_fd(ctrlsockfd);
1151    remove_fd(eventsockfd);
1152
1153    if (ioctl(fd, PPPIOCDETACH, &x) < 0)
1154        error("Couldn't detach socket from link layer: %m");
1155
1156    generic_disestablish_ppp(fd);
1157}
1158
1159/* -----------------------------------------------------------------------------
1160----------------------------------------------------------------------------- */
1161void closeall()
1162{
1163    int i;
1164
1165    for (i = getdtablesize() - 1; i >= 0; i--) close(i);
1166    open("/dev/null", O_RDWR, 0);
1167    dup(0);
1168    dup(0);
1169    return;
1170}
1171
1172/* -----------------------------------------------------------------------------
1173----------------------------------------------------------------------------- */
1174u_long load_kext(char *kext, int byBundleID)
1175{
1176    int pid;
1177
1178    if ((pid = fork()) < 0)
1179        return 1;
1180
1181    if (pid == 0) {
1182        closeall();
1183        // PPP kernel extension not loaded, try load it...
1184		if (byBundleID)
1185			execle("/sbin/kextload", "kextload", "-b", kext, (char *)0, (char *)0);
1186		else
1187			execle("/sbin/kextload", "kextload", kext, (char *)0, (char *)0);
1188        exit(1);
1189    }
1190
1191    while (waitpid(pid, 0, 0) < 0) {
1192        if (errno == EINTR)
1193            continue;
1194       return 1;
1195    }
1196    return 0;
1197}
1198
1199/* -----------------------------------------------------------------------------
1200get the MTU on the network interface
1201----------------------------------------------------------------------------- */
1202u_int32_t
1203pptp_get_if_mtu(char *if_name)
1204{
1205	struct ifreq ifr;
1206	int s, err;
1207
1208    ifr.ifr_mtu = 1500;
1209
1210    s = socket(AF_INET, SOCK_DGRAM, 0);
1211    if (s >= 0) {
1212		strlcpy(ifr.ifr_name, if_name, sizeof (ifr.ifr_name));
1213		if ((err = ioctl(s, SIOCGIFMTU, (caddr_t) &ifr)) < 0)
1214			error("PPTP: can't get interface '%s' mtu, err %d (%m)", if_name, err);
1215		close(s);
1216	}
1217	return ifr.ifr_mtu;
1218}
1219
1220/* -----------------------------------------------------------------------------
1221 Get the media of an interface.
1222
1223 Parameters:
1224 if_name: interface we want information about.
1225
1226 Return code:
1227 media for the interface.
1228 ----------------------------------------------------------------------------- */
1229u_int32_t
1230pptp_get_if_media(char *if_name)
1231{
1232	struct ifmediareq ifr;
1233	int s, err;
1234
1235    if (!if_name || !if_name[0]) {
1236        return 0;
1237    }
1238
1239    bzero(&ifr, sizeof(ifr));
1240
1241    s = socket(AF_INET, SOCK_DGRAM, 0);
1242    if (s >= 0) {
1243		strlcpy(ifr.ifm_name, if_name, sizeof (ifr.ifm_name));
1244		if ((err = ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifr)) < 0) {
1245			error("PPTP: can't get interface '%s' media, err %d (%m)", if_name, err);
1246        }
1247		close(s);
1248	}
1249	return ifr.ifm_current;
1250}
1251
1252/* -----------------------------------------------------------------------------
1253----------------------------------------------------------------------------- */
1254u_int32_t
1255pptp_get_if_baudrate(char *if_name)
1256{
1257    char *                  buf     = NULL;
1258    size_t                  buf_len = 0;
1259    struct if_msghdr *      ifm;
1260    unsigned int            if_index;
1261    u_int32_t               baudrate = 0;
1262    int                     mib[6];
1263
1264    /* get the interface index */
1265
1266    if_index = if_nametoindex(if_name);
1267    if (if_index == 0) {
1268        goto done;      // if unknown interface
1269    }
1270
1271    /* get information for the specified device */
1272
1273    mib[0] = CTL_NET;
1274    mib[1] = PF_ROUTE;
1275    mib[2] = 0;
1276    mib[3] = AF_LINK;
1277    mib[4] = NET_RT_IFLIST;
1278    mib[5] = if_index;      /* ask for exactly one interface */
1279
1280    if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) < 0) {
1281        goto done;
1282    }
1283    buf = malloc(buf_len);
1284    if (sysctl(mib, 6, buf, &buf_len, NULL, 0) < 0) {
1285        goto done;
1286    }
1287
1288    /* get the baudrate for the interface */
1289
1290    ifm = ALIGNED_CAST(struct if_msghdr *)buf;
1291    switch (ifm->ifm_type) {
1292        case RTM_IFINFO : {
1293            baudrate = ifm->ifm_data.ifi_baudrate;
1294            break;
1295        }
1296    }
1297
1298done :
1299
1300    if (buf != NULL)
1301        free(buf);
1302
1303    return baudrate;
1304}
1305
1306/* -----------------------------------------------------------------------------
1307----------------------------------------------------------------------------- */
1308int pptp_set_peer_route()
1309{
1310    SCNetworkReachabilityRef	ref;
1311    SCNetworkConnectionFlags	flags;
1312    bool 			is_peer_local;
1313    struct in_addr		gateway;
1314    struct sockaddr_in  	addr;
1315
1316   if (peeraddress.s_addr == 0)
1317        return -1;
1318
1319    /* check if is peer on our local subnet */
1320    bzero(&addr, sizeof(addr));
1321    addr.sin_len = sizeof(addr);
1322    addr.sin_family = AF_INET;
1323    addr.sin_port = htons(PPTP_TCP_PORT);
1324    addr.sin_addr = peeraddress;
1325    ref = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&addr);
1326    is_peer_local = SCNetworkReachabilityGetFlags(ref, &flags) && (flags & kSCNetworkFlagsIsDirect);
1327    CFRelease(ref);
1328
1329    host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, 0);
1330
1331    if (is_peer_local
1332        || routeraddress[0] == 0
1333        || inet_aton((char*)routeraddress, &gateway) != 1) {
1334
1335        if (interface[0]) {
1336            bzero(&gateway, sizeof(gateway));
1337            /* subnet route */
1338            host_gateway(RTM_ADD, peeraddress, gateway, (char*)interface, 1);
1339            peer_route_set = 2;
1340        }
1341    }
1342    else {
1343        /* host route */
1344        host_gateway(RTM_ADD, peeraddress, gateway, 0, 0);
1345        peer_route_set = 1;
1346    }
1347
1348    return 0;
1349}
1350
1351/* -----------------------------------------------------------------------------
1352----------------------------------------------------------------------------- */
1353int pptp_clean_peer_route()
1354{
1355
1356    if (peeraddress.s_addr == 0)
1357        return -1;
1358
1359    if (peer_route_set) {
1360	host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, peer_route_set == 1 ? 0 : 1);
1361        peer_route_set = 0;
1362    }
1363
1364    return 0;
1365}
1366
1367/* -----------------------------------------------------------------------------
1368----------------------------------------------------------------------------- */
1369void pptp_ip_up(void *arg, uintptr_t p)
1370{
1371
1372    if (peer_route_set == 2) {
1373        /* in the link local case, delete the route to the server,
1374            in case it conflicts with the one from the ppp interface */
1375	host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, 0);
1376    }
1377}
1378
1379/* -----------------------------------------------------------------------------
1380add/remove a host route
1381----------------------------------------------------------------------------- */
1382static boolean_t
1383host_gateway(int cmd, struct in_addr host, struct in_addr gateway, char *ifname, int isnet)
1384{
1385    int 			len;
1386    int 			rtm_seq = 0;
1387    struct {
1388	struct rt_msghdr	hdr;
1389	struct sockaddr_in	dst;
1390	struct sockaddr_in	gway;
1391	struct sockaddr_in	mask;
1392	struct sockaddr_dl	link;
1393    } 				rtmsg;
1394    int 			sockfd = -1;
1395
1396    if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) {
1397	syslog(LOG_INFO, "host_gateway: open routing socket failed, %s",
1398	       strerror(errno));
1399	return (FALSE);
1400    }
1401
1402    memset(&rtmsg, 0, sizeof(rtmsg));
1403    rtmsg.hdr.rtm_type = cmd;
1404    rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
1405    if (isnet)
1406        rtmsg.hdr.rtm_flags |= RTF_CLONING;
1407    else
1408        rtmsg.hdr.rtm_flags |= RTF_HOST;
1409    if (gateway.s_addr)
1410        rtmsg.hdr.rtm_flags |= RTF_GATEWAY;
1411    rtmsg.hdr.rtm_version = RTM_VERSION;
1412    rtmsg.hdr.rtm_seq = ++rtm_seq;
1413    rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
1414    rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1415    rtmsg.dst.sin_family = AF_INET;
1416    rtmsg.dst.sin_addr = host;
1417    rtmsg.hdr.rtm_addrs |= RTA_GATEWAY;
1418    rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1419    rtmsg.gway.sin_family = AF_INET;
1420    rtmsg.gway.sin_addr = gateway;
1421    rtmsg.mask.sin_len = sizeof(rtmsg.mask);
1422    rtmsg.mask.sin_family = AF_INET;
1423    rtmsg.mask.sin_addr.s_addr = 0xFFFFFFFF;
1424
1425    len = sizeof(rtmsg);
1426    if (ifname) {
1427	rtmsg.link.sdl_len = sizeof(rtmsg.link);
1428	rtmsg.link.sdl_family = AF_LINK;
1429	rtmsg.link.sdl_nlen = MIN(strlen(ifname), sizeof(rtmsg.link.sdl_data));
1430	rtmsg.hdr.rtm_addrs |= RTA_IFP;
1431	bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen);
1432    }
1433    else {
1434	/* no link information */
1435	len -= sizeof(rtmsg.link);
1436    }
1437    rtmsg.hdr.rtm_msglen = len;
1438    if (write(sockfd, &rtmsg, len) < 0) {
1439	syslog(LOG_DEBUG, "host_gateway: write routing socket failed, %s",
1440	       strerror(errno));
1441	close(sockfd);
1442	return (FALSE);
1443    }
1444
1445    close(sockfd);
1446    return (TRUE);
1447}
1448
1449/* -----------------------------------------------------------------------------
1450----------------------------------------------------------------------------- */
1451static void pptp_echo_check ()
1452{
1453    if (echo_active == 0 || echo_timer_running != 0)
1454        return;
1455
1456    pptp_send_echo_request ();
1457
1458    TIMEOUT (pptp_echo_timeout, 0, echo_interval);
1459    echo_timer_running = 1;
1460}
1461
1462/* -----------------------------------------------------------------------------
1463----------------------------------------------------------------------------- */
1464static void pptp_stop_echo_check ()
1465{
1466    echo_active = 0;
1467    if (echo_timer_running) {
1468        UNTIMEOUT (pptp_echo_timeout, 0);
1469        echo_timer_running = 0;
1470    }
1471}
1472
1473/* -----------------------------------------------------------------------------
1474----------------------------------------------------------------------------- */
1475static void pptp_echo_timeout (void *arg)
1476{
1477    if (echo_timer_running != 0) {
1478        echo_timer_running = 0;
1479        pptp_echo_check ();
1480    }
1481}
1482
1483/* -----------------------------------------------------------------------------
1484----------------------------------------------------------------------------- */
1485void pptp_received_echo_reply(u_int32_t identifier, u_int8_t result, u_int8_t error)
1486{
1487    // not really interested in the content
1488    // we just know our link is still alive
1489    dbglog("PPTP received Echo Reply, id = %d", identifier);
1490    /* Reset the number of outstanding echo frames */
1491    echos_pending = 0;
1492    echo_active = 0;
1493}
1494
1495/* -----------------------------------------------------------------------------
1496----------------------------------------------------------------------------- */
1497static void pptp_link_failure ()
1498{
1499    // major change happen on the interface we are using.
1500    // disconnect PPTP
1501    // Enhancement : should check if link is still usable
1502    notice("PPTP has detected change in the network and lost connection with the server.");
1503    devstatus = EXIT_PPTP_NETWORKCHANGED;
1504    status = EXIT_HANGUP;
1505    remove_fd(ctrlsockfd);
1506    remove_fd(eventsockfd);
1507    hungup = 1;
1508    lcp_lowerdown(0);	/* PPTP link is no longer available */
1509    link_terminated(0);
1510    ppp_auxiliary_probe_stop();
1511    pptp_clear_nat_port_mapping();
1512    ppp_session_clear(&pptp_session);
1513    session = NULL;
1514}
1515
1516/* -----------------------------------------------------------------------------
1517----------------------------------------------------------------------------- */
1518static void pptp_send_echo_request ()
1519{
1520    /*
1521     * Detect the failure of the peer at this point.
1522     */
1523    if (echo_fails != 0) {
1524        if (echos_pending >= echo_fails) {
1525            pptp_link_failure();
1526	    echos_pending = 0;
1527	}
1528    }
1529
1530    /*
1531     * Make and send the echo request frame.
1532     */
1533    dbglog("PPTP sent Echo Request, id = %d", echo_identifier);
1534    if (pptp_echo(ctrlsockfd, echo_identifier++) == -1)
1535        pptp_link_failure();
1536    echos_pending++;
1537}
1538
1539/* -----------------------------------------------------------------------------
1540----------------------------------------------------------------------------- */
1541static void enable_keepalive (int fd)
1542{
1543	int val;
1544
1545	if (tcp_keepalive) {
1546		val = 1;
1547		setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
1548		setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepalive, sizeof(tcp_keepalive));
1549		setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
1550	}
1551}
1552
1553/* -----------------------------------------------------------------------------
1554 ----------------------------------------------------------------------------- */
1555int
1556pptp_ip_probe_init (struct sockaddr_in *probe_addrs,
1557					int                *probe_fds,
1558					int                 num)
1559{
1560	int scope;
1561
1562	if (!probe_addrs || !probe_fds || num < 3) {
1563		return -1;
1564	}
1565
1566	scope = if_nametoindex((char *)interface);
1567
1568	bzero(probe_addrs, (sizeof(*probe_addrs) * num));
1569	probe_addrs[GOOG_DNS_PROBE].sin_len = sizeof(struct in_addr);
1570	probe_addrs[GOOG_DNS_PROBE].sin_family = AF_INET;
1571	probe_addrs[GOOG_DNS_PROBE].sin_port = 0;
1572	probe_addrs[GOOG_DNS_PROBE].sin_addr.s_addr = GOOG_DNS_PROBE_ADDR_A; // google-public-dns-a.google.com
1573	if (peeraddress.s_addr) {
1574		probe_addrs[PEER_ADDR_PROBE].sin_len = sizeof(peeraddress);
1575		probe_addrs[PEER_ADDR_PROBE].sin_family = AF_INET;
1576		probe_addrs[PEER_ADDR_PROBE].sin_port = 0;
1577		probe_addrs[PEER_ADDR_PROBE].sin_addr = peeraddress;
1578		if (num_alt_peer_address) {
1579			probe_addrs[ALT_PEER_ADDR_PROBE].sin_len = sizeof(peeraddress);
1580			probe_addrs[ALT_PEER_ADDR_PROBE].sin_family = AF_INET;
1581			probe_addrs[ALT_PEER_ADDR_PROBE].sin_port = 0;
1582			probe_addrs[ALT_PEER_ADDR_PROBE].sin_addr = alt_peer_address[(arc4random() % num_alt_peer_address)];
1583		}
1584	}
1585	probe_fds[GOOG_DNS_PROBE] = -1;
1586	probe_fds[PEER_ADDR_PROBE] = -1;
1587	probe_fds[ALT_PEER_ADDR_PROBE] = -1;
1588	return 0;
1589}
1590
1591static char *pptp_sd_name = "PPTP";
1592void
1593pptp_init_session (char              *interface_name,
1594				   u_int32_t          interface_name_siz,
1595				   struct in_addr    *addr,
1596				   link_failure_func  func)
1597{
1598	ppp_session_clear(&pptp_session);
1599	pptp_session.sd_name = pptp_sd_name;
1600	pptp_session.interface_name = interface_name;
1601	pptp_session.interface_name_siz = interface_name_siz;
1602	pptp_session.interface_address.s_addr = addr->s_addr;
1603	pptp_session.failure_func = func;
1604	//sess->probe_timer_running = 0;
1605	pptp_ip_probe_init(pptp_session.probe_addrs, pptp_session.probe_fds, MAX_PROBE_ADDRS);
1606	pptp_session.valid = 1;
1607	session = &pptp_session;
1608}
1609