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
625static CFStringRef pptp_copy_str_at_index(CFStringRef key, int index)
626{
627    CFArrayRef	components;
628    CFStringRef foundstr = NULL;
629
630    components = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
631    if (index < CFArrayGetCount(components)) {
632        if ((foundstr = CFArrayGetValueAtIndex(components, index))){
633            CFRetain(foundstr);
634        }
635    }
636    CFRelease(components);
637    return foundstr;
638}
639
640static void pptp_get_router_address(CFStringRef serviceID)
641{
642    CFStringRef		routerAddress = NULL;
643    CFStringRef     ipv4Key = NULL;
644    CFDictionaryRef ipv4Dict = NULL;
645
646    if (serviceID == NULL) {
647        goto done;
648    }
649    warning("pptp_get_router_address\n");
650    ipv4Key = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault,
651                                                          kSCDynamicStoreDomainState,
652                                                          serviceID,
653                                                          kSCEntNetIPv4);
654    if (ipv4Key == NULL) {
655        goto done;
656    }
657
658    ipv4Dict = SCDynamicStoreCopyValue(NULL, ipv4Key);
659    if (ipv4Dict == NULL) {
660        goto done;
661    }
662
663    routerAddress = CFDictionaryGetValue(ipv4Dict, kSCPropNetIPv4Router);
664    if (routerAddress) {
665        CFStringGetCString(routerAddress, (char*)routeraddress, sizeof(routeraddress), kCFStringEncodingUTF8);
666        warning("pptp_get_router_address %s\n", routeraddress);
667    }
668
669done:
670    if (ipv4Key) {
671        CFRelease(ipv4Key);
672    }
673    if (ipv4Dict) {
674        CFRelease(ipv4Dict);
675    }
676}
677
678static void pptp_get_router_address_for_interface(void)
679{
680    CFDictionaryRef     dict = NULL;
681    CFStringRef         pattern = NULL;
682    CFMutableArrayRef   patterns = NULL;
683    CFStringRef         *keys = NULL;
684    CFDictionaryRef     *values = NULL;
685    CFIndex             count = 0;
686    CFIndex             i = 0;
687    CFStringRef         serviceID = NULL;
688
689    if (interface == NULL || interface[0] == 0) {
690        goto done;
691    }
692
693    patterns = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
694    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(kCFAllocatorDefault,
695                                                          kSCDynamicStoreDomainState,
696                                                          kSCCompAnyRegex,
697                                                          kSCEntNetIPv4);
698
699    if (patterns == NULL || pattern == NULL)
700        goto done;
701    CFArrayAppendValue(patterns, pattern);
702
703    dict = SCDynamicStoreCopyMultiple(NULL, NULL, patterns);
704    if (dict == NULL)
705        goto done;
706
707    count = CFDictionaryGetCount(dict);
708
709    keys = calloc(count, sizeof(CFStringRef));
710    values = calloc(count, sizeof(CFDictionaryRef));
711    if (keys == NULL || values == NULL)
712        goto done;
713    CFDictionaryGetKeysAndValues(dict, (const void**)keys, (const void**)values);
714    for (i=0; i < count; i++) {
715        CFDictionaryRef ipv4Dict = NULL;
716        CFStringRef     ipv4Key = NULL;
717
718        ipv4Key  = keys[i];
719        ipv4Dict = values[i];
720
721        if (ipv4Key == NULL || ipv4Dict == NULL) {
722            continue;
723        }
724
725        /* Match interface name here */
726        CFStringRef ifnameRef = CFDictionaryGetValue(ipv4Dict, kSCPropInterfaceName);
727        if (ifnameRef) {
728            char ifname[IFNAMSIZ] = { 0 };
729            CFStringGetCString(ifnameRef, ifname, sizeof(ifname), kCFStringEncodingASCII);
730            if (!strcmp(ifname, interface)) {
731                if ((CFStringHasPrefix(ipv4Key, kSCDynamicStoreDomainState)) && (CFStringHasSuffix(ipv4Key, kSCEntNetIPv4))) {
732                    // Fetch the serviceID, then the router address
733                    serviceID = pptp_copy_str_at_index(ipv4Key, 3);
734                    pptp_get_router_address(serviceID);
735                    break;
736                }
737            }
738        }
739    }
740
741done:
742    if (serviceID) {
743        CFRelease(serviceID);
744    }
745    if (pattern) {
746        CFRelease(pattern);
747    }
748    if (patterns) {
749        CFRelease(patterns);
750    }
751    if (dict) {
752        CFRelease(dict);
753    }
754    if (keys) {
755        free(keys);
756    }
757    if (values) {
758        free(values);
759    }
760}
761
762/* -----------------------------------------------------------------------------
763get the socket ready to start doing PPP.
764That is, open the socket and start the PPTP dialog
765----------------------------------------------------------------------------- */
766int pptp_connect(int *errorcode)
767{
768    char 		dev[32], name[MAXPATHLEN], c;
769    int 		err = 0, fd, val;
770	uint32_t    len;
771    CFURLRef		url;
772    CFDictionaryRef	dict;
773    CFStringRef		string, key;
774    struct sockaddr_in 	addr;
775    struct kev_request	kev_req;
776    u_int32_t		baudrate;
777    int             num_connect_retries = 0;
778    int             connect_timeout = 15;
779
780	*errorcode = 0;
781
782    if (cfgCache == NULL || serviceidRef == NULL) {
783        goto fail;
784    }
785
786    snprintf(dev, sizeof(dev), "socket[%d:%d]", PF_PPP, PPPPROTO_PPTP);
787    strlcpy(ppp_devnam, dev, sizeof(ppp_devnam));
788
789    hungup = 0;
790    kill_link = 0;
791    linkdown = 0;
792    our_call_id = getpid();
793    routeraddress[0] = 0;
794    interface[0] = 0;
795
796    if (ifscope && ifscope[0]) {
797        strcpy(interface, ifscope);
798        pptp_get_router_address_for_interface();
799    } else {
800        key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
801        if (key) {
802            dict = SCDynamicStoreCopyValue(cfgCache, key);
803            CFRelease(key);
804            if (dict) {
805                if ((string  = CFDictionaryGetValue(dict, kSCPropNetIPv4Router)))
806                    CFStringGetCString(string, (char*)routeraddress, sizeof(routeraddress), kCFStringEncodingUTF8);
807                if ((string  = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface)))
808                    CFStringGetCString(string, (char*)interface, sizeof(interface), kCFStringEncodingUTF8);
809                CFRelease(dict);
810            }
811        }
812    }
813
814	/* now that we know our interface, adjust the MTU if necessary */
815	if (interface[0]) {
816		int min_mtu = pptp_get_if_mtu((char*)interface) - PPTP_MIN_HDR_SIZE;
817		if (lcp_allowoptions[0].mru > min_mtu)	/* defines out mtu */
818			lcp_allowoptions[0].mru = min_mtu;
819
820		/* Don't adjust MRU, radar 3974763 */
821#if 0
822		if (lcp_wantoptions[0].mru > min_mtu)	/* defines out mru */
823			lcp_wantoptions[0].mru = min_mtu;
824		if (lcp_wantoptions[0].neg_mru > min_mtu)	/* defines our mru */
825			lcp_wantoptions[0].neg_mru = min_mtu;
826#endif
827	}
828
829#if !TARGET_OS_EMBEDDED
830    interface_media = pptp_get_if_media((char*)interface);
831#endif /* !iPhone */
832
833	/* let's say our underlying transport is up */
834	transport_up = 1;
835	wait_interface_timer_running = 0;
836	wait_underlying_interface_up = 0;
837	ppp_session_clear(&pptp_session);
838	session = NULL;
839
840    eventsockfd = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
841    if (eventsockfd != -1) {
842        // PPTP can survive without event socket anyway
843        kev_req.vendor_code = KEV_VENDOR_APPLE;
844        kev_req.kev_class = KEV_NETWORK_CLASS;
845        kev_req.kev_subclass = KEV_INET_SUBCLASS;
846        ioctl(eventsockfd, SIOCSKEVFILT, &kev_req);
847    }
848
849    /* -------------------------------------------------------------*/
850    /* connect mode : we need a valid remote address or name */
851    if (!strcmp(mode, MODE_CONNECT)) {
852        if (remoteaddress == 0) {
853            error("PPTP: No remote address supplied...\n");
854            devstatus = EXIT_PPTP_NOSERVER;
855            goto fail;
856        }
857
858		set_network_signature("VPN.RemoteAddress", remoteaddress, 0, 0);
859
860#if TARGET_OS_EMBEDDED
861		{
862			/* first, bring up EDGE */
863			int need_edge = FALSE;
864			SCNetworkReachabilityRef ref = NULL;
865			SCNetworkConnectionFlags	flags;
866
867			ref = SCNetworkReachabilityCreateWithName(NULL, remoteaddress);
868			if (ref) {
869
870				if (SCNetworkReachabilityGetFlags(ref, &flags)) {
871					if ((flags & kSCNetworkReachabilityFlagsReachable) &&
872						(flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
873						(flags & kSCNetworkReachabilityFlagsIsWWAN)) {
874						need_edge = TRUE;
875					}
876				}
877				CFRelease(ref);
878			}
879
880			if (need_edge) {
881
882				if (pipe(edgefds) < 0) {
883					error("PPTP: failed to create pipe for starting edge...\n");
884					goto fail;
885				}
886
887				if (pthread_create(&edgethread, NULL, pptp_edge_thread, NULL)) {
888					error("PPTP: failed to create thread for starting edge...\n");
889					close(edgefds[0]);
890					close(edgefds[1]);
891					goto fail;
892				}
893
894				while (read(edgefds[0], &c, 1) != 1) {
895					if (kill_link) {
896						pthread_cancel(edgethread);
897						break;
898					}
899				}
900
901				close(edgefds[0]);
902				close(edgefds[1]);
903
904				if (kill_link)
905					goto fail1;
906
907				if (c) {
908					error("PPTP: Cannot start EDGE connection...\n");
909					*errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */
910					devstatus = EXIT_PPTP_NOEDGE;
911					goto fail;
912				}
913
914			}
915
916		}
917#endif
918
919        if (inet_aton(remoteaddress, &peeraddress) == 0) {
920
921            if (pipe(resolverfds) < 0) {
922                error("PPTP: failed to create pipe for gethostbyname...\n");
923                goto fail;
924            }
925
926            if (pthread_create(&resolverthread, NULL, pptp_resolver_thread, NULL)) {
927                error("PPTP: failed to create thread for gethostbyname...\n");
928                close(resolverfds[0]);
929                close(resolverfds[1]);
930                goto fail;
931            }
932
933            while (read(resolverfds[0], &c, 1) != 1) {
934                if (kill_link) {
935                    pthread_cancel(resolverthread);
936                    break;
937                }
938            }
939
940            close(resolverfds[0]);
941            close(resolverfds[1]);
942
943            if (kill_link)
944                goto fail1;
945
946            if (c) {
947                error("PPTP: Host '%s' not found...\n", remoteaddress);
948				*errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */
949                devstatus = EXIT_PPTP_NOSERVER;
950                goto fail;
951            }
952        }
953
954        notice("PPTP connecting to server '%s' (%s)...\n", remoteaddress, inet_ntoa(peeraddress));
955
956        set_server_peer(peeraddress);
957
958        if ((ctrlsockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
959            error("PPTP can't create control socket...\n");
960            goto fail;
961        }
962        // TODO: make connection_timeout configurable
963        if (setsockopt(ctrlsockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &connect_timeout, sizeof(connect_timeout))) {
964            error("PPTP can't set control socket's maximum timeout ...\n");
965            // prevent retries since the default 90 sec is *too* long
966            num_alt_peer_address = 0;
967        }
968
969        /* connect to the pptp server */
970        bzero(&addr, sizeof(addr));
971        addr.sin_len = sizeof(addr);
972        addr.sin_family = AF_INET;
973        addr.sin_port = htons(PPTP_TCP_PORT);
974        addr.sin_addr = peeraddress;
975
976        uint32_t ifindex = 0;
977        if (ifscope && ifscope[0]) {
978            ifindex = if_nametoindex(ifscope);
979        }
980        while (connectx(ctrlsockfd, NULL, 0, (struct sockaddr *)&addr, sizeof(addr), ifindex, ASSOCID_ANY, CONNID_ANY)) {
981            if (errno != EINTR) {
982                error("PPTP connect errno = %d %m\n", errno);
983                if ((errno == ETIMEDOUT || errno == ECONNREFUSED) &&
984                    num_connect_retries < num_alt_peer_address) {
985                    peeraddress = alt_peer_address[num_connect_retries];
986                    notice("PPTP connecting to alternate server '%s' (%s)...\n", remoteaddress, inet_ntoa(peeraddress));
987                    set_server_peer(peeraddress);
988                    addr.sin_addr = peeraddress;
989                    num_connect_retries++;
990                    continue;
991                }
992                *errorcode = PPTP_RETRY_CONNECT_CODE; /* wait and retry if necessary */
993                devstatus = EXIT_PPTP_NOANSWER;
994                goto fail;
995            }
996            if (kill_link)
997                goto fail1;
998        }
999
1000		/* enable keepalive on control connection. need to be done before sending data */
1001		enable_keepalive(ctrlsockfd);
1002
1003        err = pptp_outgoing_call(ctrlsockfd,
1004            our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd);
1005
1006        /* setup the specific route */
1007        pptp_set_peer_route();
1008    }
1009    /* -------------------------------------------------------------*/
1010    /* answer mode : we need a valid remote address or name */
1011    else if (!strcmp(mode, MODE_ANSWER)) {
1012        len = sizeof(addr);
1013        if (getpeername(ctrlsockfd, (struct sockaddr *)&addr, &len) < 0) {
1014            error("PPTP: cannot get client address... %m\n");
1015            //devstatus = EXIT_PPTP_NOSERVER;
1016            goto fail;
1017        }
1018        peeraddress = addr.sin_addr;
1019        remoteaddress = inet_ntoa(peeraddress);
1020
1021        notice("PPTP incoming call in progress from '%s'...", remoteaddress);
1022
1023		/* enable keepalive on control connection. need to be done before sending data */
1024		enable_keepalive(ctrlsockfd);
1025
1026        err = pptp_incoming_call(ctrlsockfd,
1027            our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd);
1028    }
1029    /* -------------------------------------------------------------*/
1030    else if (!strcmp(mode, MODE_LISTEN)) {
1031
1032        notice("PPTP listening...\n");
1033
1034        if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
1035            error("PPTP can't create listening socket...\n");
1036            goto fail;
1037        }
1038
1039        val = 1;
1040        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
1041
1042        bzero(&addr, sizeof(addr));
1043        addr.sin_len = sizeof(addr);
1044        addr.sin_family = AF_INET;
1045        addr.sin_port = htons(PPTP_TCP_PORT);
1046        addr.sin_addr.s_addr = INADDR_ANY;
1047        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1048            error("PPTP bind failed, %m");
1049            goto fail;
1050        }
1051
1052        if (listen(fd, 10) < 0) {
1053            error("PPTP listen failed, %m");
1054            return errno;
1055        }
1056
1057        len = sizeof(addr);
1058        ctrlsockfd = accept(fd, (struct sockaddr *)&addr, &len);
1059        close(fd);	// close the socket used for listening
1060        if (ctrlsockfd < 0) {
1061            error("PPTP accept failed, %m");
1062            goto fail;
1063        }
1064
1065        peeraddress = addr.sin_addr;
1066        remoteaddress = inet_ntoa(peeraddress);
1067
1068        notice("PPTP incoming call in progress from '%s'...", remoteaddress);
1069
1070		/* enable keepalive on control connection. need to be done before sending data */
1071		enable_keepalive(ctrlsockfd);
1072
1073        err = pptp_incoming_call(ctrlsockfd,
1074                our_call_id, our_window, our_ppd, &peer_call_id, &peer_window, &peer_ppd);
1075    }
1076
1077    if (err) {
1078        if (err != -2) {
1079            if (err != -1)
1080                devstatus = err;
1081            goto fail;
1082        }
1083        goto fail1;
1084    }
1085
1086    notice("PPTP connection established.");
1087
1088	bzero(&ouraddress, sizeof(ouraddress));
1089	len = sizeof(ouraddress);
1090	getsockname(ctrlsockfd, (struct sockaddr *)&ouraddress, &len);
1091
1092    /* get reachability flags of peer */
1093    bzero(&addr, sizeof(addr));
1094    addr.sin_len = sizeof(addr);
1095    addr.sin_family = AF_INET;
1096    addr.sin_port = htons(PPTP_TCP_PORT);
1097    addr.sin_addr = peeraddress;
1098
1099    /* open the data socket */
1100    datasockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_PPTP);
1101    if (datasockfd < 0) {
1102        if (!noload) {
1103            if ((url = CFBundleCopyBundleURL(bundle))) {
1104                name[0] = 0;
1105                CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)name, MAXPATHLEN - 1);
1106                CFRelease(url);
1107                strlcat(name, "/", sizeof(name));
1108                if ((url = CFBundleCopyBuiltInPlugInsURL(bundle))) {
1109                    CFURLGetFileSystemRepresentation(url, 0, (UInt8 *)(name + strlen(name)),
1110                        MAXPATHLEN - strlen(name) - strlen(PPTP_NKE) - 1);
1111                    CFRelease(url);
1112                    strlcat(name, "/", sizeof(name));
1113                    strlcat(name, PPTP_NKE, sizeof(name));
1114#if !TARGET_OS_EMBEDDED
1115                    if (!load_kext(name, 0))
1116#else
1117                    if (!load_kext(PPTP_NKE_ID, 1))
1118#endif
1119                        datasockfd = socket(PF_PPP, SOCK_DGRAM, PPPPROTO_PPTP);
1120                }
1121            }
1122        }
1123        if (datasockfd < 0) {
1124            error("Failed to open PPTP socket: %m");
1125            goto fail;
1126       }
1127    }
1128
1129    if (kdebugflag & 1) {
1130        u_int32_t 	flags;
1131        flags = debug ? PPTP_FLAG_DEBUG : 0;
1132        if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_FLAGS, &flags, 4)) {
1133            error("PPTP can't set PPTP flags...\n");
1134            goto fail;
1135        }
1136    }
1137
1138    len = sizeof(addr);
1139    if (getsockname(ctrlsockfd, (struct sockaddr *)&addr, &len) < 0) {
1140        error("PPTP: cannot get our address... %m\n");
1141        goto fail;
1142    }
1143    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_OURADDRESS, &addr.sin_addr.s_addr, 4)) {
1144        error("PPTP can't set our PPTP address...\n");
1145        goto fail;
1146    }
1147    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEERADDRESS, &peeraddress.s_addr, 4)) {
1148        error("PPTP can't set PPTP server address...\n");
1149        goto fail;
1150    }
1151
1152	baudrate = pptp_get_if_baudrate((char*)interface);
1153	if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_BAUDRATE, &baudrate, 4)) {
1154        error("PPTP can't set our baudrate...\n");
1155        goto fail;
1156    }
1157
1158    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_CALL_ID, &our_call_id, 2)) {
1159        error("PPTP can't set our call id...\n");
1160        goto fail;
1161    }
1162
1163    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_CALL_ID, &peer_call_id, 2)) {
1164        error("PPTP can't set peer call id...\n");
1165        goto fail;
1166    }
1167    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_WINDOW, &our_window, 2)) {
1168        error("PPTP can't set our receive window size...\n");
1169        goto fail;
1170    }
1171    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_WINDOW, &peer_window, 2)) {
1172        error("PPTP can't set peer receive window size...\n");
1173        goto fail;
1174    }
1175    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_PEER_PPD, &peer_ppd, 2)) {
1176        error("PPTP can't set peer packet processing delay ...\n");
1177        goto fail;
1178    }
1179    if (setsockopt(datasockfd, PPPPROTO_PPTP, PPTP_OPT_MAXTIMEOUT, &maxtimeout, 2)) {
1180        error("PPTP can't set adaptative maximum timeout ...\n");
1181        goto fail;
1182    }
1183
1184    if (!strcmp(mode, MODE_CONNECT)) {
1185        pptp_init_session((char *)interface, sizeof(interface), &ouraddress.sin_addr, ppp_variable_echo_start);
1186        pptp_set_nat_port_mapping();
1187    }
1188
1189    return datasockfd;
1190
1191fail:
1192    status = EXIT_CONNECT_FAILED;
1193fail1:
1194    if (eventsockfd != -1) {
1195        close(eventsockfd);
1196        eventsockfd = -1;
1197    }
1198    if (ctrlsockfd != -1) {
1199        close(ctrlsockfd);
1200        ctrlsockfd = -1;
1201    }
1202    return -1;
1203}
1204
1205/* -----------------------------------------------------------------------------
1206run the disconnector
1207----------------------------------------------------------------------------- */
1208void pptp_disconnect()
1209{
1210    notice("PPTP disconnecting...\n");
1211
1212    if (eventsockfd != -1) {
1213        close(eventsockfd);
1214        eventsockfd = -1;
1215    }
1216    if (ctrlsockfd >= 0) {
1217        close(ctrlsockfd);
1218        ctrlsockfd = -1;
1219    }
1220
1221    ppp_auxiliary_probe_stop();
1222    pptp_clear_nat_port_mapping();
1223    ppp_session_clear(&pptp_session);
1224    session = NULL;
1225
1226    notice("PPTP disconnected\n");
1227}
1228
1229/* -----------------------------------------------------------------------------
1230close the socket descriptors
1231----------------------------------------------------------------------------- */
1232void pptp_close()
1233{
1234
1235	pptp_stop_echo_check();
1236
1237    if (eventsockfd != -1) {
1238        close(eventsockfd);
1239        eventsockfd = -1;
1240    }
1241    if (datasockfd >= 0) {
1242        close(datasockfd);
1243        datasockfd = -1;
1244    }
1245    if (ctrlsockfd >= 0) {
1246        close(ctrlsockfd);
1247        ctrlsockfd = -1;
1248    }
1249}
1250
1251/* -----------------------------------------------------------------------------
1252clean up before quitting
1253----------------------------------------------------------------------------- */
1254void pptp_cleanup()
1255{
1256    pptp_close();
1257    pptp_clean_peer_route();
1258}
1259
1260/* -----------------------------------------------------------------------------
1261establish the socket as a ppp link
1262----------------------------------------------------------------------------- */
1263int pptp_establish_ppp(int fd)
1264{
1265    int x, new_fd;
1266
1267    if (ioctl(fd, PPPIOCATTACH, &x) < 0) {
1268        error("Couldn't attach socket to the link layer: %m");
1269        return -1;
1270    }
1271
1272    new_fd = generic_establish_ppp(fd, interface);
1273    if (new_fd == -1)
1274        return -1;
1275
1276    // add just the control socket to the select
1277    // the data socket is just for moving data in the kernel
1278    add_fd(ctrlsockfd);
1279    add_fd(eventsockfd);
1280    return new_fd;
1281}
1282
1283/* -----------------------------------------------------------------------------
1284disestablish the socket as a ppp link
1285----------------------------------------------------------------------------- */
1286void pptp_disestablish_ppp(int fd)
1287{
1288    int 	x;
1289
1290    remove_fd(ctrlsockfd);
1291    remove_fd(eventsockfd);
1292
1293    if (ioctl(fd, PPPIOCDETACH, &x) < 0)
1294        error("Couldn't detach socket from link layer: %m");
1295
1296    generic_disestablish_ppp(fd);
1297}
1298
1299/* -----------------------------------------------------------------------------
1300----------------------------------------------------------------------------- */
1301void closeall()
1302{
1303    int i;
1304
1305    for (i = getdtablesize() - 1; i >= 0; i--) close(i);
1306    open("/dev/null", O_RDWR, 0);
1307    dup(0);
1308    dup(0);
1309    return;
1310}
1311
1312/* -----------------------------------------------------------------------------
1313----------------------------------------------------------------------------- */
1314u_long load_kext(char *kext, int byBundleID)
1315{
1316    int pid;
1317
1318    if ((pid = fork()) < 0)
1319        return 1;
1320
1321    if (pid == 0) {
1322        closeall();
1323        // PPP kernel extension not loaded, try load it...
1324		if (byBundleID)
1325			execle("/sbin/kextload", "kextload", "-b", kext, (char *)0, (char *)0);
1326		else
1327			execle("/sbin/kextload", "kextload", kext, (char *)0, (char *)0);
1328        exit(1);
1329    }
1330
1331    while (waitpid(pid, 0, 0) < 0) {
1332        if (errno == EINTR)
1333            continue;
1334       return 1;
1335    }
1336    return 0;
1337}
1338
1339/* -----------------------------------------------------------------------------
1340get the MTU on the network interface
1341----------------------------------------------------------------------------- */
1342u_int32_t
1343pptp_get_if_mtu(char *if_name)
1344{
1345	struct ifreq ifr;
1346	int s, err;
1347
1348    ifr.ifr_mtu = 1500;
1349
1350    s = socket(AF_INET, SOCK_DGRAM, 0);
1351    if (s >= 0) {
1352		strlcpy(ifr.ifr_name, if_name, sizeof (ifr.ifr_name));
1353		if ((err = ioctl(s, SIOCGIFMTU, (caddr_t) &ifr)) < 0)
1354			error("PPTP: can't get interface '%s' mtu, err %d (%m)", if_name, err);
1355		close(s);
1356	}
1357	return ifr.ifr_mtu;
1358}
1359
1360/* -----------------------------------------------------------------------------
1361 Get the media of an interface.
1362
1363 Parameters:
1364 if_name: interface we want information about.
1365
1366 Return code:
1367 media for the interface.
1368 ----------------------------------------------------------------------------- */
1369u_int32_t
1370pptp_get_if_media(char *if_name)
1371{
1372	struct ifmediareq ifr;
1373	int s, err;
1374
1375    if (!if_name || !if_name[0]) {
1376        return 0;
1377    }
1378
1379    bzero(&ifr, sizeof(ifr));
1380
1381    s = socket(AF_INET, SOCK_DGRAM, 0);
1382    if (s >= 0) {
1383		strlcpy(ifr.ifm_name, if_name, sizeof (ifr.ifm_name));
1384		if ((err = ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifr)) < 0) {
1385			error("PPTP: can't get interface '%s' media, err %d (%m)", if_name, err);
1386        }
1387		close(s);
1388	}
1389	return ifr.ifm_current;
1390}
1391
1392/* -----------------------------------------------------------------------------
1393----------------------------------------------------------------------------- */
1394u_int32_t
1395pptp_get_if_baudrate(char *if_name)
1396{
1397    char *                  buf     = NULL;
1398    size_t                  buf_len = 0;
1399    struct if_msghdr *      ifm;
1400    unsigned int            if_index;
1401    u_int32_t               baudrate = 0;
1402    int                     mib[6];
1403
1404    /* get the interface index */
1405
1406    if_index = if_nametoindex(if_name);
1407    if (if_index == 0) {
1408        goto done;      // if unknown interface
1409    }
1410
1411    /* get information for the specified device */
1412
1413    mib[0] = CTL_NET;
1414    mib[1] = PF_ROUTE;
1415    mib[2] = 0;
1416    mib[3] = AF_LINK;
1417    mib[4] = NET_RT_IFLIST;
1418    mib[5] = if_index;      /* ask for exactly one interface */
1419
1420    if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) < 0) {
1421        goto done;
1422    }
1423    buf = malloc(buf_len);
1424    if (sysctl(mib, 6, buf, &buf_len, NULL, 0) < 0) {
1425        goto done;
1426    }
1427
1428    /* get the baudrate for the interface */
1429
1430    ifm = ALIGNED_CAST(struct if_msghdr *)buf;
1431    switch (ifm->ifm_type) {
1432        case RTM_IFINFO : {
1433            baudrate = ifm->ifm_data.ifi_baudrate;
1434            break;
1435        }
1436    }
1437
1438done :
1439
1440    if (buf != NULL)
1441        free(buf);
1442
1443    return baudrate;
1444}
1445
1446/* -----------------------------------------------------------------------------
1447----------------------------------------------------------------------------- */
1448int pptp_set_peer_route()
1449{
1450    SCNetworkReachabilityRef	ref;
1451    SCNetworkConnectionFlags	flags;
1452    bool 			is_peer_local;
1453    struct in_addr		gateway;
1454    struct sockaddr_in  	addr;
1455
1456   if (peeraddress.s_addr == 0)
1457        return -1;
1458
1459    /* check if is peer on our local subnet */
1460    bzero(&addr, sizeof(addr));
1461    addr.sin_len = sizeof(addr);
1462    addr.sin_family = AF_INET;
1463    addr.sin_port = htons(PPTP_TCP_PORT);
1464    addr.sin_addr = peeraddress;
1465    ref = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&addr);
1466    is_peer_local = SCNetworkReachabilityGetFlags(ref, &flags) && (flags & kSCNetworkFlagsIsDirect);
1467    CFRelease(ref);
1468
1469    host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, 0);
1470
1471    if (is_peer_local
1472        || routeraddress[0] == 0
1473        || inet_aton((char*)routeraddress, &gateway) != 1) {
1474
1475        if (interface[0]) {
1476            bzero(&gateway, sizeof(gateway));
1477            /* subnet route */
1478            host_gateway(RTM_ADD, peeraddress, gateway, (char*)interface, 1);
1479            peer_route_set = 2;
1480        }
1481    }
1482    else {
1483        /* host route */
1484        host_gateway(RTM_ADD, peeraddress, gateway, 0, 0);
1485        peer_route_set = 1;
1486    }
1487
1488    return 0;
1489}
1490
1491/* -----------------------------------------------------------------------------
1492----------------------------------------------------------------------------- */
1493int pptp_clean_peer_route()
1494{
1495
1496    if (peeraddress.s_addr == 0)
1497        return -1;
1498
1499    if (peer_route_set) {
1500	host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, peer_route_set == 1 ? 0 : 1);
1501        peer_route_set = 0;
1502    }
1503
1504    return 0;
1505}
1506
1507/* -----------------------------------------------------------------------------
1508----------------------------------------------------------------------------- */
1509void pptp_ip_up(void *arg, uintptr_t p)
1510{
1511
1512    if (peer_route_set == 2) {
1513        /* in the link local case, delete the route to the server,
1514            in case it conflicts with the one from the ppp interface */
1515	host_gateway(RTM_DELETE, peeraddress, ip_zeros, 0, 0);
1516    }
1517}
1518
1519/* -----------------------------------------------------------------------------
1520add/remove a host route
1521----------------------------------------------------------------------------- */
1522static boolean_t
1523host_gateway(int cmd, struct in_addr host, struct in_addr gateway, char *ifname, int isnet)
1524{
1525    int 			len;
1526    int 			rtm_seq = 0;
1527    struct {
1528	struct rt_msghdr	hdr;
1529	struct sockaddr_in	dst;
1530	struct sockaddr_in	gway;
1531	struct sockaddr_in	mask;
1532	struct sockaddr_dl	link;
1533    } 				rtmsg;
1534    int 			sockfd = -1;
1535
1536    if ((sockfd = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)) < 0) {
1537	syslog(LOG_INFO, "host_gateway: open routing socket failed, %s",
1538	       strerror(errno));
1539	return (FALSE);
1540    }
1541
1542    memset(&rtmsg, 0, sizeof(rtmsg));
1543    rtmsg.hdr.rtm_type = cmd;
1544    rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
1545    if (isnet)
1546        rtmsg.hdr.rtm_flags |= RTF_CLONING;
1547    else
1548        rtmsg.hdr.rtm_flags |= RTF_HOST;
1549    if (gateway.s_addr)
1550        rtmsg.hdr.rtm_flags |= RTF_GATEWAY;
1551    rtmsg.hdr.rtm_version = RTM_VERSION;
1552    rtmsg.hdr.rtm_seq = ++rtm_seq;
1553    rtmsg.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
1554    rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1555    rtmsg.dst.sin_family = AF_INET;
1556    rtmsg.dst.sin_addr = host;
1557    rtmsg.hdr.rtm_addrs |= RTA_GATEWAY;
1558    rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1559    rtmsg.gway.sin_family = AF_INET;
1560    rtmsg.gway.sin_addr = gateway;
1561    rtmsg.mask.sin_len = sizeof(rtmsg.mask);
1562    rtmsg.mask.sin_family = AF_INET;
1563    rtmsg.mask.sin_addr.s_addr = 0xFFFFFFFF;
1564
1565    len = sizeof(rtmsg);
1566    if (ifname) {
1567	rtmsg.link.sdl_len = sizeof(rtmsg.link);
1568	rtmsg.link.sdl_family = AF_LINK;
1569	rtmsg.link.sdl_nlen = MIN(strlen(ifname), sizeof(rtmsg.link.sdl_data));
1570	rtmsg.hdr.rtm_addrs |= RTA_IFP;
1571	bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen);
1572    }
1573    else {
1574	/* no link information */
1575	len -= sizeof(rtmsg.link);
1576    }
1577    rtmsg.hdr.rtm_msglen = len;
1578    if (write(sockfd, &rtmsg, len) < 0) {
1579	syslog(LOG_DEBUG, "host_gateway: write routing socket failed, %s",
1580	       strerror(errno));
1581	close(sockfd);
1582	return (FALSE);
1583    }
1584
1585    close(sockfd);
1586    return (TRUE);
1587}
1588
1589/* -----------------------------------------------------------------------------
1590----------------------------------------------------------------------------- */
1591static void pptp_echo_check ()
1592{
1593    if (echo_active == 0 || echo_timer_running != 0)
1594        return;
1595
1596    pptp_send_echo_request ();
1597
1598    TIMEOUT (pptp_echo_timeout, 0, echo_interval);
1599    echo_timer_running = 1;
1600}
1601
1602/* -----------------------------------------------------------------------------
1603----------------------------------------------------------------------------- */
1604static void pptp_stop_echo_check ()
1605{
1606    echo_active = 0;
1607    if (echo_timer_running) {
1608        UNTIMEOUT (pptp_echo_timeout, 0);
1609        echo_timer_running = 0;
1610    }
1611}
1612
1613/* -----------------------------------------------------------------------------
1614----------------------------------------------------------------------------- */
1615static void pptp_echo_timeout (void *arg)
1616{
1617    if (echo_timer_running != 0) {
1618        echo_timer_running = 0;
1619        pptp_echo_check ();
1620    }
1621}
1622
1623/* -----------------------------------------------------------------------------
1624----------------------------------------------------------------------------- */
1625void pptp_received_echo_reply(u_int32_t identifier, u_int8_t result, u_int8_t error)
1626{
1627    // not really interested in the content
1628    // we just know our link is still alive
1629    dbglog("PPTP received Echo Reply, id = %d", identifier);
1630    /* Reset the number of outstanding echo frames */
1631    echos_pending = 0;
1632    echo_active = 0;
1633}
1634
1635/* -----------------------------------------------------------------------------
1636----------------------------------------------------------------------------- */
1637static void pptp_link_failure ()
1638{
1639    // major change happen on the interface we are using.
1640    // disconnect PPTP
1641    // Enhancement : should check if link is still usable
1642    notice("PPTP has detected change in the network and lost connection with the server.");
1643    devstatus = EXIT_PPTP_NETWORKCHANGED;
1644    status = EXIT_HANGUP;
1645    remove_fd(ctrlsockfd);
1646    remove_fd(eventsockfd);
1647    hungup = 1;
1648    lcp_lowerdown(0);	/* PPTP link is no longer available */
1649    link_terminated(0);
1650    ppp_auxiliary_probe_stop();
1651    pptp_clear_nat_port_mapping();
1652    ppp_session_clear(&pptp_session);
1653    session = NULL;
1654}
1655
1656/* -----------------------------------------------------------------------------
1657----------------------------------------------------------------------------- */
1658static void pptp_send_echo_request ()
1659{
1660    /*
1661     * Detect the failure of the peer at this point.
1662     */
1663    if (echo_fails != 0) {
1664        if (echos_pending >= echo_fails) {
1665            pptp_link_failure();
1666	    echos_pending = 0;
1667	}
1668    }
1669
1670    /*
1671     * Make and send the echo request frame.
1672     */
1673    dbglog("PPTP sent Echo Request, id = %d", echo_identifier);
1674    if (pptp_echo(ctrlsockfd, echo_identifier++) == -1)
1675        pptp_link_failure();
1676    echos_pending++;
1677}
1678
1679/* -----------------------------------------------------------------------------
1680----------------------------------------------------------------------------- */
1681static void enable_keepalive (int fd)
1682{
1683	int val;
1684
1685	if (tcp_keepalive) {
1686		val = 1;
1687		setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
1688		setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepalive, sizeof(tcp_keepalive));
1689		setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
1690	}
1691}
1692
1693/* -----------------------------------------------------------------------------
1694 ----------------------------------------------------------------------------- */
1695int
1696pptp_ip_probe_init (struct sockaddr_in *probe_addrs,
1697					int                *probe_fds,
1698					int                 num)
1699{
1700	int scope;
1701
1702	if (!probe_addrs || !probe_fds || num < 3) {
1703		return -1;
1704	}
1705
1706	scope = if_nametoindex((char *)interface);
1707
1708	bzero(probe_addrs, (sizeof(*probe_addrs) * num));
1709	probe_addrs[GOOG_DNS_PROBE].sin_len = sizeof(struct in_addr);
1710	probe_addrs[GOOG_DNS_PROBE].sin_family = AF_INET;
1711	probe_addrs[GOOG_DNS_PROBE].sin_port = 0;
1712	probe_addrs[GOOG_DNS_PROBE].sin_addr.s_addr = GOOG_DNS_PROBE_ADDR_A; // google-public-dns-a.google.com
1713	if (peeraddress.s_addr) {
1714		probe_addrs[PEER_ADDR_PROBE].sin_len = sizeof(peeraddress);
1715		probe_addrs[PEER_ADDR_PROBE].sin_family = AF_INET;
1716		probe_addrs[PEER_ADDR_PROBE].sin_port = 0;
1717		probe_addrs[PEER_ADDR_PROBE].sin_addr = peeraddress;
1718		if (num_alt_peer_address) {
1719			probe_addrs[ALT_PEER_ADDR_PROBE].sin_len = sizeof(peeraddress);
1720			probe_addrs[ALT_PEER_ADDR_PROBE].sin_family = AF_INET;
1721			probe_addrs[ALT_PEER_ADDR_PROBE].sin_port = 0;
1722			probe_addrs[ALT_PEER_ADDR_PROBE].sin_addr = alt_peer_address[(arc4random() % num_alt_peer_address)];
1723		}
1724	}
1725	probe_fds[GOOG_DNS_PROBE] = -1;
1726	probe_fds[PEER_ADDR_PROBE] = -1;
1727	probe_fds[ALT_PEER_ADDR_PROBE] = -1;
1728	return 0;
1729}
1730
1731static char *pptp_sd_name = "PPTP";
1732void
1733pptp_init_session (char              *interface_name,
1734				   u_int32_t          interface_name_siz,
1735				   struct in_addr    *addr,
1736				   link_failure_func  func)
1737{
1738	ppp_session_clear(&pptp_session);
1739	pptp_session.sd_name = pptp_sd_name;
1740	pptp_session.interface_name = interface_name;
1741	pptp_session.interface_name_siz = interface_name_siz;
1742	pptp_session.interface_address.s_addr = addr->s_addr;
1743	pptp_session.failure_func = func;
1744	//sess->probe_timer_running = 0;
1745	pptp_ip_probe_init(pptp_session.probe_addrs, pptp_session.probe_fds, MAX_PROBE_ADDRS);
1746	pptp_session.valid = 1;
1747	session = &pptp_session;
1748}
1749