1/*
2 * Copyright (c) 2003, 2014 Apple 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 * main.c - Point-to-Point Protocol main module
25 *
26 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 *
32 * 1. Redistributions of source code must retain the above copyright
33 *    notice, this list of conditions and the following disclaimer.
34 *
35 * 2. Redistributions in binary form must reproduce the above copyright
36 *    notice, this list of conditions and the following disclaimer in
37 *    the documentation and/or other materials provided with the
38 *    distribution.
39 *
40 * 3. The name "Carnegie Mellon University" must not be used to
41 *    endorse or promote products derived from this software without
42 *    prior written permission. For permission or any legal
43 *    details, please contact
44 *      Office of Technology Transfer
45 *      Carnegie Mellon University
46 *      5000 Forbes Avenue
47 *      Pittsburgh, PA  15213-3890
48 *      (412) 268-4387, fax: (412) 268-7395
49 *      tech-transfer@andrew.cmu.edu
50 *
51 * 4. Redistributions of any form whatsoever must retain the following
52 *    acknowledgment:
53 *    "This product includes software developed by Computing Services
54 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
55 *
56 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
57 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
58 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
59 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
60 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
61 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
62 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
63 */
64
65#define RCSID	"$Id: main.c,v 1.34.20.1 2006/04/17 18:37:15 callie Exp $"
66
67#include <stdio.h>
68#include <ctype.h>
69#include <stdlib.h>
70#include <string.h>
71#include <unistd.h>
72#include <signal.h>
73#include <errno.h>
74#include <fcntl.h>
75#include <syslog.h>
76#include <netdb.h>
77#include <pwd.h>
78#include <setjmp.h>
79#include <sys/param.h>
80#include <sys/types.h>
81#include <sys/wait.h>
82#include <sys/time.h>
83#include <sys/resource.h>
84#include <sys/stat.h>
85#include <sys/socket.h>
86#include <pthread.h>
87#include <netinet/in.h>
88#include <arpa/inet.h>
89
90#include "pppd.h"
91#include "magic.h"
92#include "fsm.h"
93#include "lcp.h"
94#include "ipcp.h"
95#ifdef INET6
96#include "ipv6cp.h"
97#endif
98#ifdef ACSCP
99#include "acscp.h"
100#endif
101#include "upap.h"
102#include "chap-new.h"
103#include "eap.h"
104#include "ccp.h"
105#include "ecp.h"
106#include "pathnames.h"
107
108#ifdef USE_TDB
109#include "tdb.h"
110#endif
111
112#ifdef CBCP_SUPPORT
113#include "cbcp.h"
114#endif
115
116#ifdef IPX_CHANGE
117#include "ipxcp.h"
118#endif /* IPX_CHANGE */
119#ifdef AT_CHANGE
120#include "atcp.h"
121#endif
122
123#ifndef lint
124static const char rcsid[] = RCSID;
125#endif
126
127/* interface vars */
128char ifname[32];		/* Interface name */
129int ifunit;			/* Interface unit number */
130
131struct channel *the_channel;
132
133char *progname;			/* Name of this program */
134char hostname[MAXNAMELEN];	/* Our hostname */
135static char pidfilename[MAXPATHLEN];	/* name of pid file */
136static char linkpidfile[MAXPATHLEN];	/* name of linkname pid file */
137char ppp_devnam[MAXPATHLEN];	/* name of PPP tty (maybe ttypx) */
138uid_t uid;			/* Our real user-id */
139struct notifier *pidchange = NULL;
140struct notifier *phasechange = NULL;
141struct notifier *exitnotify = NULL;
142struct notifier *sigreceived = NULL;
143struct notifier *fork_notifier = NULL;
144struct notifier *protocolsready_notifier = NULL;
145struct notifier *acspdhcpready_notifier = NULL;
146
147int hungup;			/* terminal has been hung up */
148int do_modem_hungup;			/* need to finish disconnection */
149int privileged;			/* we're running as real uid root */
150int need_holdoff;		/* need holdoff period before restarting */
151int detached;			/* have detached from terminal */
152volatile int status;		/* exit status for pppd */
153#ifdef __APPLE__
154volatile int devstatus;		/* exit device status for pppd */
155#endif
156int unsuccess;			/* # unsuccessful connection attempts */
157int do_callback;		/* != 0 if we should do callback next */
158int doing_callback;		/* != 0 if we are doing callback */
159int ppp_session_number;		/* Session number, for channels with such a
160				   concept (eg PPPoE) */
161#ifdef USE_TDB
162TDB_CONTEXT *pppdb;		/* database for storing status etc. */
163#endif
164
165char db_key[32];
166
167int (*holdoff_hook) __P((void)) = NULL;
168int (*new_phase_hook) __P((int)) = NULL;
169void (*snoop_recv_hook) __P((unsigned char *p, int len)) = NULL;
170void (*snoop_send_hook) __P((unsigned char *p, int len)) = NULL;
171
172static int conn_running;	/* we have a [dis]connector running */
173static int devfd;		/* fd of underlying device */
174static int fd_ppp = -1;		/* fd for talking PPP */
175static int fd_loop;		/* fd for getting demand-dial packets */
176static int fd_devnull;		/* fd for /dev/null */
177
178int phase;			/* where the link is at */
179int kill_link;
180int open_ccp_flag;
181int listen_time;
182int got_sigusr2;
183int got_sigterm;
184int got_sighup;
185#ifdef __APPLE__
186int stop_link;
187int cont_link;
188int got_sigtstp;
189int got_sigcont;
190#endif
191
192static int waiting;
193static sigjmp_buf sigjmp;
194
195char **script_env;		/* Env. variable values for scripts */
196int s_env_nalloc;		/* # words avail at script_env */
197
198/*
199 *  WCast-align fix - these buffers need to be aligned so that (after the 4 byte ppp header is removed)
200 *  the protocol handling routines such as acsp can expect that the data is aligned on a 4 byte boundary
201 */
202u_char outpacket_buf[PPP_MRU+PPP_HDRLEN] __attribute__ ((aligned (4))); /* buffer for outgoing packet */
203u_char inpacket_buf[PPP_MRU+PPP_HDRLEN] __attribute__ ((aligned (4))); /* buffer for incoming packet */
204
205static int n_children;		/* # child processes still running */
206static int got_sigchld;		/* set if we have received a SIGCHLD */
207
208int privopen;			/* don't lock, open device as root */
209
210char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
211
212GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */
213int ngroups;			/* How many groups valid in groups */
214
215static struct timeval start_time;	/* Time when link was started. */
216
217struct pppd_stats link_stats;
218unsigned link_connect_time;
219int link_stats_valid;
220
221int error_count;
222
223/*
224 * We maintain a list of child process pids and
225 * functions to call when they exit.
226 */
227struct subprocess {
228    pid_t	pid;
229    char	*prog;
230    void	(*done) __P((void *));
231    void	*arg;
232    struct subprocess *next;
233};
234
235static struct subprocess *children;
236
237#ifdef __APPLE__
238static pthread_t mainthread_id = NULL;
239#endif
240
241/* Prototypes for procedures local to this file. */
242
243static void setup_signals __P((void));
244static void create_pidfile __P((int pid));
245static void create_linkpidfile __P((int pid));
246static void cleanup __P((void));
247static void get_input __P((void));
248static void calltimeout __P((void));
249static struct timeval *timeleft __P((struct timeval *));
250static void kill_my_pg __P((int));
251static void hup __P((int));
252#ifdef __APPLE__
253static void stop __P((int));
254static void cont __P((int));
255#endif
256static void term __P((int));
257static void chld __P((int));
258static void toggle_debug __P((int));
259static void open_ccp __P((int));
260static void bad_signal __P((int));
261static void holdoff_end __P((void *));
262static int reap_kids __P((int waitfor));
263
264#ifdef USE_TDB
265static void update_db_entry __P((void));
266static void add_db_key __P((const char *));
267static void delete_db_key __P((const char *));
268static void cleanup_db __P((void));
269#endif
270
271static void handle_events __P((void));
272static void print_link_stats __P((void));
273
274extern	char	*ttyname __P((int));
275extern	char	*getlogin __P((void));
276int main __P((int, char *[]));
277
278#ifdef __APPLE__
279void (*wait_input_hook) __P((void)) = NULL;
280int (*start_link_hook) __P((void))		= NULL;
281int (*link_up_hook) __P((void))			= NULL;
282bool link_up_done = 0;
283int (*terminal_window_hook) __P((char *, int, int)) 	= NULL;
284int  redialingcount = 0;
285bool  redialingalternate = 0;
286struct notifier *connect_started_notify = NULL;
287struct notifier *connect_success_notify = NULL;
288struct notifier *connect_fail_notify = NULL;
289struct notifier *disconnect_started_notify = NULL;
290struct notifier *disconnect_done_notify = NULL;
291struct notifier *stop_notify = NULL;
292struct notifier *cont_notify = NULL;
293struct notifier *system_inited_notify = NULL;
294struct notifier *network_probed_notify = NULL;
295int wait_underlying_interface_up = 0;
296int retry_pre_start_link_check = 0;
297#endif
298
299#ifdef ultrix
300#undef	O_NONBLOCK
301#define	O_NONBLOCK	O_NDELAY
302#endif
303
304#ifdef ULTRIX
305#define setlogmask(x)
306#endif
307
308
309/*
310 * PPP Data Link Layer "protocol" table.
311 * One entry per supported protocol.
312 * The last entry must be NULL.
313 */
314struct protent *protocols[] = {
315    &lcp_protent,
316    &pap_protent,
317    &chap_protent,
318#ifdef CBCP_SUPPORT
319    &cbcp_protent,
320#endif
321    &ipcp_protent,
322#ifdef INET6
323    &ipv6cp_protent,
324#endif
325#ifdef ACSCP
326    &acscp_protent,
327#endif
328    &ccp_protent,
329    &ecp_protent,
330#ifdef IPX_CHANGE
331    &ipxcp_protent,
332#endif
333#ifdef AT_CHANGE
334    &atcp_protent,
335#endif
336    &eap_protent,
337    NULL
338};
339
340/*
341 * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
342 */
343#if !defined(PPP_DRV_NAME)
344#define PPP_DRV_NAME	"ppp"
345#endif /* !defined(PPP_DRV_NAME) */
346
347int
348main(argc, argv)
349    int argc;
350    char *argv[];
351{
352    int i, t = 0;
353    char *p;
354    struct passwd *pw;
355    struct protent *protp;
356    char numbuf[16];
357
358    /* Initialize syslog facilities */
359    reopen_log();
360
361
362#ifdef __APPLE__
363    mainthread_id = pthread_self();
364#endif
365    link_stats_valid = 0;
366    new_phase(PHASE_INITIALIZE);
367
368
369    script_env = NULL;
370
371    if (gethostname(hostname, MAXNAMELEN) < 0 ) {
372	option_error("Couldn't get hostname: %m");
373	exit(1);
374    }
375    hostname[MAXNAMELEN-1] = 0;
376
377    /* make sure we don't create world or group writable files. */
378    umask(umask(0777) | 022);
379
380    uid = getuid();
381    privileged = uid == 0;
382#ifdef __APPLE__
383	if (!privileged)
384		privileged = sys_check_controller();
385#endif
386    slprintf(numbuf, sizeof(numbuf), "%d", uid);
387    script_setenv("ORIG_UID", numbuf, 0);
388
389    ngroups = getgroups(NGROUPS_MAX, groups);
390
391    /*
392     * Initialize magic number generator now so that protocols may
393     * use magic numbers in initialization.
394     */
395    magic_init();
396
397    /*
398     * Initialize each protocol.
399     */
400    for (i = 0; (protp = protocols[i]) != NULL; ++i)
401        (*protp->init)(0);
402
403    /*
404     * Initialize the default channel.
405     */
406    tty_init();
407
408    progname = *argv;
409
410#ifdef __APPLE__
411    sys_install_options();
412#endif
413
414    /*
415     * Parse, in order, the system options file, the user's options file,
416     * and the command line arguments.
417     */
418    if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
419	|| !options_from_user()
420	|| !parse_args(argc-1, argv+1)
421#ifdef __APPLE__
422	|| ((controlled) && !options_from_controller())
423        // options file to add additionnal parameters, after the plugins are loaded
424        // should not be used, except for debugging purpose, or specific behavior override
425        // anything set there will override what is specified as argument by the PPPController
426        // so only the admin should use it...
427    	|| !options_from_file(_PATH_SYSPOSTOPTIONS, 0, 0, 1)
428#endif
429        )
430	exit(EXIT_OPTION_ERROR);
431    devnam_fixed = 1;		/* can no longer change device name */
432
433    /*
434     * Work out the device name, if it hasn't already been specified,
435     * and parse the tty's options file.
436     */
437    if (the_channel->process_extra_options)
438	(*the_channel->process_extra_options)();
439
440    if (debug)
441	setlogmask(LOG_UPTO(LOG_DEBUG));
442
443    /*
444     * Check that we are running as root.
445     */
446    if (geteuid() != 0) {
447	option_error("must be root to run %s, since it is not setuid-root",
448		     argv[0]);
449	exit(EXIT_NOT_ROOT);
450    }
451
452    if (!ppp_available()) {
453	option_error("%s", no_ppp_msg);
454	exit(EXIT_NO_KERNEL_SUPPORT);
455    }
456
457    /*
458     * Check that the options given are valid and consistent.
459     */
460    check_options();
461    if (!sys_check_options())
462	exit(EXIT_OPTION_ERROR);
463    auth_check_options();
464#ifdef HAVE_MULTILINK
465    mp_check_options();
466#endif
467    for (i = 0; (protp = protocols[i]) != NULL; ++i)
468	if (protp->check_options != NULL)
469	    (*protp->check_options)();
470    if (the_channel->check_options)
471	(*the_channel->check_options)();
472
473    if (dump_options || dryrun) {
474	init_pr_log(NULL, LOG_INFO);
475	print_options(pr_log, NULL);
476	end_pr_log();
477    }
478
479    if (dryrun)
480	die(0);
481
482    /*
483     * Initialize system-dependent stuff.
484     */
485    sys_init();
486#ifdef __APPLE__
487	notify(system_inited_notify, 0);
488#endif
489
490
491    /* Make sure fds 0, 1, 2 are open to somewhere. */
492    fd_devnull = open(_PATH_DEVNULL, O_RDWR);
493    if (fd_devnull < 0)
494	fatal("Couldn't open %s: %m", _PATH_DEVNULL);
495    while (fd_devnull <= 2) {
496	i = dup(fd_devnull);
497	if (i < 0)
498	    fatal("Critical shortage of file descriptors: dup failed: %m");
499	fd_devnull = i;
500    }
501
502#ifdef USE_TDB
503    pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644);
504    if (pppdb != NULL) {
505	slprintf(db_key, sizeof(db_key), "pppd%d", getpid());
506	update_db_entry();
507    } else {
508	warning("Warning: couldn't open ppp database %s", _PATH_PPPDB);
509	if (multilink) {
510	    warning("Warning: disabling multilink");
511	    multilink = 0;
512	}
513    }
514#endif
515
516    /*
517     * Detach ourselves from the terminal, if required,
518     * and identify who is running us.
519     */
520    if (!nodetach && !updetach)
521	detach();
522#ifndef __APPLE__
523	// radar 6153490
524	p = getlogin();
525    if (p == NULL) {
526#endif
527	pw = getpwuid(uid);
528	if (pw != NULL && pw->pw_name != NULL)
529	    p = pw->pw_name;
530	else
531	    p = "(unknown)";
532#ifndef __APPLE__
533    }
534#endif
535#ifdef __APPLE__
536    sys_log(LOG_NOTICE, "pppd %s (Apple version %s) started by %s, uid %d", VERSION, PPP_VERSION,  p, uid);
537#else
538    sys_log(LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid);
539#endif
540    script_setenv("PPPLOGNAME", p, 0);
541
542    if (devnam[0])
543	script_setenv("DEVICE", devnam, 1);
544    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
545    script_setenv("PPPD_PID", numbuf, 1);
546
547#if __APPLE__
548    if (controlfd !=-1)
549        add_fd(controlfd);
550#endif
551
552    setup_signals();
553
554    waiting = 0;
555
556    /*
557     * If we're doing dial-on-demand, set up the interface now.
558     */
559    if (demand) {
560	/*
561	 * Open the loopback channel and set it up to be the ppp interface.
562	 */
563#ifdef USE_TDB
564	tdb_writelock(pppdb);
565#endif
566	fd_loop = open_ppp_loopback();
567	set_ifunit(1);
568#ifdef USE_TDB
569	tdb_writeunlock(pppdb);
570#endif
571	/*
572	 * Configure the interface and mark it up, etc.
573	 */
574	demand_conf();
575	create_linkpidfile(getpid());
576    }
577
578#ifdef __APPLE__
579	if (holdfirst) {
580		need_holdoff = 1;
581		goto hold;
582	}
583#endif
584
585    do_callback = 0;
586    for (;;) {
587
588	listen_time = 0;
589	need_holdoff = 1;
590	devfd = -1;
591	status = EXIT_OK;
592#ifdef __APPLE__
593	devstatus = 0;
594#endif
595	++unsuccess;
596	doing_callback = do_callback;
597	do_callback = 0;
598
599	if (demand && !doing_callback) {
600	    /*
601	     * Don't do anything until we see some activity.
602	     */
603	    new_phase(PHASE_DORMANT);
604	    demand_unblock();
605	    add_fd(fd_loop);
606	    for (;;) {
607		handle_events();
608		if (kill_link && !persist)
609		    break;
610		if (get_loop_output())
611		    break;
612	    }
613	    remove_fd(fd_loop);
614	    if (kill_link && !persist)
615		break;
616
617	    /*
618	     * Now we want to bring up the link.
619	     */
620	    demand_block();
621	    info("Starting link");
622	}
623
624#ifdef __APPLE__
625        if (start_link_hook) {
626            if (the_channel->pre_start_link_check) {
627                int rc = -1;
628                if (retry_pre_start_link_check < 0)
629                    retry_pre_start_link_check = 0;
630                for (i = 1 + retry_pre_start_link_check; i > 0; i--) {
631                    if (!(rc = the_channel->pre_start_link_check())) {
632                        break;
633                    }
634                }
635                if (rc) {
636                    status = EXIT_PEER_UNREACHABLE;
637                    goto end;
638                }
639            }
640
641            t = (*start_link_hook)();
642            if (t == 0) {
643               // cancelled
644                status = EXIT_USER_REQUEST;
645                goto end;
646            }
647        }
648#endif
649
650#ifdef __APPLE__
651	sys_publish_remoteaddress(remoteaddress);
652#endif
653	new_phase(PHASE_SERIALCONN);
654
655#ifdef __APPLE__
656    notify(connect_started_notify, 0);
657    link_up_done = 0;
658    redialingcount = 0;
659    redialingalternate = 0;
660    do {
661        if (redialingcount || redialingalternate) {
662            if (the_channel->cleanup)
663                (*the_channel->cleanup)();
664            if (redialalternate)
665                sys_publish_remoteaddress(redialingalternate ? altremoteaddress : remoteaddress);
666        }
667
668        if (redialtimer && redialingcount && !redialingalternate) {
669            if (hasbusystate)
670				new_phase(PHASE_WAITONBUSY);
671            sleep(redialtimer);
672            if (hasbusystate)
673				new_phase(PHASE_SERIALCONN);
674        }
675        if (kill_link)
676			break;
677	devfd = the_channel->connect(&t);
678
679        if (redialalternate)
680            redialingalternate = !redialingalternate;
681        if (!redialingalternate)
682            redialingcount++;
683    }
684    while ((busycode != -1) && (t == busycode) && (redialingcount <= redialcount) && !kill_link);
685#else
686	devfd = the_channel->connect();
687#endif
688	if (devfd < 0) {
689#ifdef __APPLE__
690            if (devfd == -2) {
691                if (conn_running)
692                    /* Send the signal to the [dis]connector process(es) also */
693                    kill_my_pg(SIGHUP);
694                goto disconnect;
695            }
696            else {
697                notify(connect_fail_notify, t);
698#endif
699	    goto fail;
700#ifdef __APPLE__
701            }
702#endif
703    }
704#ifdef __APPLE__
705        /*
706            link_up_done is there to give a chance to a device to implement
707            a double step connection.
708            For example, the serial connection will call directly link_up_hook
709            between the connection script and terminal script.
710            The link_up_hook hook can be used to ask for a password, that
711            could be used by a terminal script
712        */
713        if (!link_up_done) {
714            if (link_up_hook) {
715                t = (*link_up_hook)();
716                if (t == 0) {
717                    // cancelled
718                    status = EXIT_USER_REQUEST;
719                    goto disconnect;
720                }
721            }
722            link_up_done = 1;
723        }
724        notify(connect_success_notify, 0);
725#endif
726
727#ifdef __APPLE__
728        /* republish the remote address in case the connector has changed it */
729	sys_publish_remoteaddress(remoteaddress);
730#endif
731
732	/* set up the serial device as a ppp interface */
733#ifdef USE_TDB
734	tdb_writelock(pppdb);
735#endif
736	fd_ppp = the_channel->establish_ppp(devfd);
737	if (fd_ppp < 0) {
738#ifdef USE_TDB
739	    tdb_writeunlock(pppdb);
740#endif
741	    status = EXIT_FATAL_ERROR;
742	    goto disconnect;
743	}
744	/* create the pid file, now that we've obtained a ppp interface */
745	if (!demand)
746	    create_linkpidfile(getpid());
747
748	if (!demand && ifunit >= 0)
749	    set_ifunit(1);
750#ifdef USE_TDB
751	tdb_writeunlock(pppdb);
752#endif
753
754	/*
755	 * Start opening the connection and wait for
756	 * incoming events (reply, timeout, etc.).
757	 */
758	if (ifunit >= 0)
759		notice("Connect: %s <--> %s", ifname, ppp_devnam);
760	else
761		notice("Starting negotiation on %s", ppp_devnam);
762	gettimeofday(&start_time, NULL);
763	script_unsetenv("CONNECT_TIME");
764	script_unsetenv("BYTES_SENT");
765	script_unsetenv("BYTES_RCVD");
766	lcp_lowerup(0);
767
768	add_fd(fd_ppp);
769	lcp_open(0);		/* Start protocol */
770	status = EXIT_NEGOTIATION_FAILED;
771	new_phase(PHASE_ESTABLISH);
772	while (phase != PHASE_DEAD) {
773		handle_events();
774	    get_input();
775#ifdef __APPLE__
776            if (stop_link) {
777                if (phase == PHASE_RUNNING) {
778                    new_phase(PHASE_ONHOLD);
779                    ppp_hold(0);
780                    auth_hold(0);
781                    for (i = 0; (protp = protocols[i]) != NULL; ++i)
782                        if (protp->hold != NULL)
783                            (*protp->hold)(0);
784                    notify(stop_notify, 0);
785                }
786            }
787            if (cont_link) {
788                if (phase == PHASE_ONHOLD) {
789                    new_phase(PHASE_RUNNING);
790                    ppp_cont(0);
791                    auth_cont(0);
792                    for (i = 0; (protp = protocols[i]) != NULL; ++i)
793                        if (protp->cont != NULL)
794                            (*protp->cont)(0);
795                    notify(cont_notify, 0);
796                }
797            }
798#endif
799	    if (kill_link) {
800#ifdef __APPLE__
801                if (do_modem_hungup || stop_link || phase == PHASE_ONHOLD) {
802					if (do_modem_hungup) {
803						notice("Modem hangup");
804						do_modem_hungup = 0;
805					}
806                    hungup = 1;
807                    lcp_lowerdown(0);
808                    link_terminated(0);
809                }
810#endif
811		lcp_close(0, "User request");
812            }
813	    if (open_ccp_flag) {
814		if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) {
815		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
816		    (*ccp_protent.open)(0);
817		}
818	    }
819#ifdef __APPLE__
820		sys_runloop();
821#endif
822	}
823
824	print_link_stats();
825
826	/*
827	 * Delete pid file before disestablishing ppp.  Otherwise it
828	 * can happen that another pppd gets the same unit and then
829	 * we delete its pid file.
830	 */
831	if (!demand) {
832	    if (pidfilename[0] != 0
833		&& unlink(pidfilename) < 0 && errno != ENOENT)
834		warning("unable to delete pid file %s: %m", pidfilename);
835	    pidfilename[0] = 0;
836	}
837
838	/*
839	 * If we may want to bring the link up again, transfer
840	 * the ppp unit back to the loopback.  Set the
841	 * real serial device back to its normal mode of operation.
842	 */
843	remove_fd(fd_ppp);
844	clean_check();
845	the_channel->disestablish_ppp(devfd);
846	fd_ppp = -1;
847	if (!hungup)
848	    lcp_lowerdown(0);
849	if (!demand)
850	    script_unsetenv("IFNAME");
851
852	/*
853	 * Run disconnector script, if requested.
854	 * XXX we may not be able to do this if the line has hung up!
855	 */
856    disconnect:
857	new_phase(PHASE_DISCONNECT);
858#ifdef __APPLE__
859        notify(disconnect_started_notify, status);
860#endif
861	if (the_channel->disconnect)
862	    the_channel->disconnect();
863#ifdef __APPLE__
864        notify(disconnect_done_notify, status);
865#endif
866    fail:
867#ifdef __APPLE__
868    if (phase != PHASE_DISCONNECT)
869        new_phase(PHASE_DISCONNECT);
870#endif
871	if (the_channel->cleanup)
872	    (*the_channel->cleanup)();
873#ifdef __APPLE__
874    end:
875#endif
876#ifdef __APPLE__
877        sys_statusnotify();
878#endif
879
880	if (!demand) {
881	    if (pidfilename[0] != 0
882		&& unlink(pidfilename) < 0 && errno != ENOENT)
883		warning("unable to delete pid file %s: %m", pidfilename);
884	    pidfilename[0] = 0;
885	}
886
887	if (!persist || (maxfail > 0 && unsuccess >= maxfail))
888	    break;
889
890	if (demand)
891	    demand_discard();
892#ifdef __APPLE__
893	hold:
894#endif
895	t = need_holdoff? holdoff: 0;
896	if (holdoff_hook)
897	    t = (*holdoff_hook)();
898	if (t > 0) {
899	    new_phase(PHASE_HOLDOFF);
900	    TIMEOUT(holdoff_end, NULL, t);
901		/* clear kill_link related signal flags */
902		got_sighup = got_sigterm = 0;
903	    do {
904		handle_events();
905		if (kill_link) {
906		    new_phase(PHASE_DORMANT); /* allow signal to end holdoff */
907		}
908	    } while (phase == PHASE_HOLDOFF);
909	    if (!persist)
910		break;
911	}
912    }
913
914    /* Wait for scripts to finish */
915    /* XXX should have a timeout here */
916    while (n_children > 0) {
917	if (debug) {
918	    struct subprocess *chp;
919	    dbglog("Waiting for %d child processes...", n_children);
920	    for (chp = children; chp != NULL; chp = chp->next)
921		dbglog("  script %s, pid %d", chp->prog, chp->pid);
922	}
923	if (reap_kids(1) < 0)
924	    break;
925    }
926
927    die(status);
928    return 0;
929}
930
931/*
932 * control fron controller - Read a string of commandd from controller file descriptor,
933 * and interpret them.
934 */
935void
936ppp_control()
937{
938    int newline, c, flags;
939    char cmd[MAXWORDLEN];
940
941    /* set the file descriptor in non blocking mode */
942    flags = fcntl(controlfd, F_GETFL);
943    if (flags == -1
944        || fcntl(controlfd, F_SETFL, flags | O_NONBLOCK) == -1) {
945        warning("Couldn't set controlfd to nonblock: %m");
946        return;
947    }
948    /* skip chars until beginning of next command */
949    for (;;) {
950	c = getc(controlfile);
951	if (c == EOF)
952	    break;
953        if (c == '[')
954            ungetc(c, controlfile);
955            break;
956    }
957    /* reset blocking mode */
958    fcntl(controlfd, F_SETFL, flags);
959
960    /* we get eof if controller exits */
961    if (feof(controlfile))
962        die(1);
963
964    /* clear error */
965    clearerr(controlfile);
966
967    if (c != '[')
968        return;
969
970    /* now ready to read the command */
971    while (getword(controlfile, cmd, &newline, "controller")) {
972
973        if (!strcmp(cmd, "[OPTIONS]")) {
974            options_from_controller();
975            if (dump_options) {
976                init_pr_log(NULL, LOG_INFO);
977                print_options(pr_log, NULL);
978                end_pr_log();
979            }
980            return;
981        }
982
983        if (!strcmp(cmd, "[DISCONNECT]")) {
984            error("[DISCONNECT]");
985            hup(SIGHUP);
986            continue;
987        }
988
989        if (!strcmp(cmd, "[TERMINATE]")) {
990            error("[TERMINATE]");
991            term(SIGTERM);
992            continue;
993        }
994
995#ifdef __APPLE__
996        if (!strcmp(cmd, "[INSTALL]")) {
997			sys_install();
998            return;
999        }
1000
1001        if (!strcmp(cmd, "[UNINSTALL]")) {
1002			sys_uninstall();
1003			return;
1004        }
1005#endif
1006
1007/*
1008        if (!strcmp(cmd, "[SUSPEND]")) {
1009            error("[SUSPEND]");
1010            stop(SIGTSTP);
1011            continue;
1012        }
1013
1014        if (!strcmp(cmd, "[RESUME]")) {
1015            error("[RESUME]");
1016            cont(SIGCONT);
1017            continue;
1018        }
1019*/
1020
1021        if (!strcmp(cmd, "[EOP]")) {
1022            break;
1023        }
1024
1025    }
1026
1027    // got EOF
1028    die(1);
1029}
1030
1031/*
1032 * handle_events - wait for something to happen and respond to it.
1033 */
1034static void
1035handle_events()
1036{
1037    struct timeval timo;
1038    sigset_t mask;
1039
1040
1041    kill_link = open_ccp_flag = 0;
1042#ifdef __APPLE__
1043    stop_link = cont_link = 0;
1044#endif
1045    if (sigsetjmp(sigjmp, 1) == 0) {
1046	sigprocmask(SIG_BLOCK, &mask, NULL);
1047	if (got_sighup || got_sigterm || got_sigusr2 || got_sigchld
1048#ifdef __APPLE__
1049            || got_sigtstp || got_sigcont
1050#endif
1051            ) {
1052	    sigprocmask(SIG_UNBLOCK, &mask, NULL);
1053	} else {
1054	    waiting = 1;
1055	    sigprocmask(SIG_UNBLOCK, &mask, NULL);
1056	    wait_input(timeleft(&timo));
1057#ifdef __APPLE__
1058            if (wait_input_hook)
1059                (*wait_input_hook)();
1060            if (the_channel->wait_input)
1061                the_channel->wait_input();
1062#endif
1063	}
1064    }
1065#ifdef __APPLE__
1066    if (controlfd !=-1 && is_ready_fd(controlfd)) {
1067        ppp_control();
1068    }
1069#endif
1070    waiting = 0;
1071    calltimeout();
1072#ifdef __APPLE__
1073    if (got_sigtstp) {
1074		info("Stopping on signal %d.", got_sigtstp);
1075        stop_link = 1;
1076        got_sigtstp = 0;
1077    }
1078    if (got_sigcont) {
1079		info("Resuming on signal %d.", got_sigcont);
1080        cont_link = 1;
1081        got_sigcont = 0;
1082    }
1083#endif
1084    if (got_sighup) {
1085    info("Hangup (SIGHUP)");
1086	kill_link = 1;
1087	got_sighup = 0;
1088	if (status != EXIT_HANGUP)
1089	    status = EXIT_USER_REQUEST;
1090    }
1091    if (got_sigterm) {
1092    info("Terminating on signal %d.", got_sigterm);
1093	kill_link = 1;
1094	persist = 0;
1095	status = EXIT_USER_REQUEST;
1096	got_sigterm = 0;
1097    }
1098    if (got_sigchld) {
1099	reap_kids(0);	/* Don't leave dead kids lying around */
1100	got_sigchld = 0;
1101    }
1102    if (got_sigusr2) {
1103	open_ccp_flag = 1;
1104	got_sigusr2 = 0;
1105    }
1106}
1107
1108/*
1109 * setup_signals - initialize signal handling.
1110 */
1111static void
1112setup_signals()
1113{
1114    struct sigaction sa;
1115    sigset_t mask;
1116
1117    /*
1118     * Compute mask of all interesting signals and install signal handlers
1119     * for each.  Only one signal handler may be active at a time.  Therefore,
1120     * all other signals should be masked when any handler is executing.
1121     */
1122    sigemptyset(&mask);
1123    sigaddset(&mask, SIGHUP);
1124    sigaddset(&mask, SIGINT);
1125    sigaddset(&mask, SIGTERM);
1126    sigaddset(&mask, SIGCHLD);
1127    sigaddset(&mask, SIGUSR2);
1128#ifdef __APPLE__
1129    sigaddset(&mask, SIGTSTP);
1130    sigaddset(&mask, SIGCONT);
1131#endif
1132
1133#define SIGNAL(s, handler)	do { \
1134	sa.sa_handler = handler; \
1135	if (sigaction(s, &sa, NULL) < 0) \
1136	    fatal("Couldn't establish signal handler (%d): %m", s); \
1137    } while (0)
1138
1139    sa.sa_mask = mask;
1140    sa.sa_flags = 0;
1141    SIGNAL(SIGHUP, hup);		/* Hangup */
1142    SIGNAL(SIGINT, term);		/* Interrupt */
1143    SIGNAL(SIGTERM, term);		/* Terminate */
1144    SIGNAL(SIGCHLD, chld);
1145#ifdef __APPLE__
1146    SIGNAL(SIGTSTP, stop);		/* stop all activity */
1147    SIGNAL(SIGCONT, cont);		/* resume activity */
1148#endif
1149
1150    SIGNAL(SIGUSR1, toggle_debug);	/* Toggle debug flag */
1151    SIGNAL(SIGUSR2, open_ccp);		/* Reopen CCP */
1152
1153    /*
1154     * Install a handler for other signals which would otherwise
1155     * cause pppd to exit without cleaning up.
1156     */
1157    SIGNAL(SIGABRT, bad_signal);
1158    SIGNAL(SIGALRM, bad_signal);
1159    SIGNAL(SIGFPE, bad_signal);
1160    SIGNAL(SIGILL, bad_signal);
1161    SIGNAL(SIGPIPE, bad_signal);
1162    SIGNAL(SIGQUIT, bad_signal);
1163    SIGNAL(SIGSEGV, bad_signal);
1164#ifdef SIGBUS
1165    SIGNAL(SIGBUS, bad_signal);
1166#endif
1167#ifdef SIGEMT
1168    SIGNAL(SIGEMT, bad_signal);
1169#endif
1170#ifdef SIGPOLL
1171    SIGNAL(SIGPOLL, bad_signal);
1172#endif
1173#ifdef SIGPROF
1174    SIGNAL(SIGPROF, bad_signal);
1175#endif
1176#ifdef SIGSYS
1177    SIGNAL(SIGSYS, bad_signal);
1178#endif
1179#ifdef SIGTRAP
1180    SIGNAL(SIGTRAP, bad_signal);
1181#endif
1182#ifdef SIGVTALRM
1183    SIGNAL(SIGVTALRM, bad_signal);
1184#endif
1185#ifdef SIGXCPU
1186    SIGNAL(SIGXCPU, bad_signal);
1187#endif
1188#ifdef SIGXFSZ
1189    SIGNAL(SIGXFSZ, bad_signal);
1190#endif
1191
1192    /*
1193     * Apparently we can get a SIGPIPE when we call syslog, if
1194     * syslogd has died and been restarted.  Ignoring it seems
1195     * be sufficient.
1196     */
1197#ifndef __APPLE__
1198    signal(SIGPIPE, SIG_IGN);
1199#endif
1200}
1201
1202/*
1203 * set_ifunit - do things we need to do once we know which ppp
1204 * unit we are using.
1205 */
1206void
1207set_ifunit(iskey)
1208    int iskey;
1209{
1210    info("Using interface %s%d", PPP_DRV_NAME, ifunit);
1211    slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
1212    script_setenv("IFNAME", ifname, iskey);
1213    if (iskey) {
1214	create_pidfile(getpid());	/* write pid to file */
1215	create_linkpidfile(getpid());
1216    }
1217}
1218
1219/*
1220 * detach - detach us from the controlling terminal.
1221 */
1222void
1223detach()
1224{
1225    int pid;
1226    char numbuf[16];
1227    int pipefd[2];
1228
1229    if (detached)
1230	return;
1231    if (pipe(pipefd) == -1)
1232	pipefd[0] = pipefd[1] = -1;
1233    if ((pid = fork()) < 0) {
1234	error("Couldn't detach (fork failed: %m)");
1235	die(1);			/* or just return? */
1236    }
1237    if (pid != 0) {
1238	/* parent */
1239	notify(pidchange, pid);
1240	/* update pid files if they have been written already */
1241	if (pidfilename[0])
1242	    create_pidfile(pid);
1243	if (linkpidfile[0])
1244	    create_linkpidfile(pid);
1245	exit(0);		/* parent dies */
1246    }
1247    setsid();
1248    chdir("/");
1249    dup2(fd_devnull, 0);
1250    dup2(fd_devnull, 1);
1251    dup2(fd_devnull, 2);
1252    detached = 1;
1253    if (log_default)
1254	log_to_fd = -1;
1255    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
1256    script_setenv("PPPD_PID", numbuf, 1);
1257
1258    /* wait for parent to finish updating pid & lock files and die */
1259    close(pipefd[1]);
1260    complete_read(pipefd[0], numbuf, 1);
1261    close(pipefd[0]);
1262
1263#ifdef __APPLE__
1264    sys_reinit();
1265#endif
1266}
1267
1268/*
1269 * reopen_log - (re)open our connection to syslog.
1270 */
1271void
1272reopen_log()
1273{
1274#ifdef ULTRIX
1275    openlog("pppd", LOG_PID);
1276#else
1277    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
1278    setlogmask(LOG_UPTO(LOG_INFO));
1279#endif
1280}
1281
1282/*
1283 * Create a file containing our process ID.
1284 */
1285static void
1286create_pidfile(pid)
1287    int pid;
1288{
1289    FILE *pidfile;
1290
1291    slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
1292	     _PATH_VARRUN, ifname);
1293    if ((pidfile = fopen(pidfilename, "w")) != NULL) {
1294	fprintf(pidfile, "%d\n", pid);
1295	(void) fclose(pidfile);
1296    } else {
1297	error("Failed to create pid file %s: %m", pidfilename);
1298	pidfilename[0] = 0;
1299    }
1300}
1301
1302static void
1303create_linkpidfile(pid)
1304    int pid;
1305{
1306    FILE *pidfile;
1307
1308    if (linkname[0] == 0)
1309	return;
1310    script_setenv("LINKNAME", linkname, 1);
1311    slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid",
1312	     _PATH_VARRUN, linkname);
1313    if ((pidfile = fopen(linkpidfile, "w")) != NULL) {
1314	fprintf(pidfile, "%d\n", pid);
1315	if (ifname[0])
1316	    fprintf(pidfile, "%s\n", ifname);
1317	(void) fclose(pidfile);
1318    } else {
1319	error("Failed to create pid file %s: %m", linkpidfile);
1320	linkpidfile[0] = 0;
1321    }
1322}
1323
1324/*
1325 * holdoff_end - called via a timeout when the holdoff period ends.
1326 */
1327static void
1328holdoff_end(arg)
1329    void *arg;
1330{
1331    new_phase(PHASE_DORMANT);
1332}
1333
1334/* List of protocol names, to make our messages a little more informative. */
1335struct protocol_list {
1336    u_short	proto;
1337    const char	*name;
1338} protocol_list[] = {
1339    { 0x21,	"IP" },
1340    { 0x23,	"OSI Network Layer" },
1341    { 0x25,	"Xerox NS IDP" },
1342    { 0x27,	"DECnet Phase IV" },
1343    { 0x29,	"Appletalk" },
1344    { 0x2b,	"Novell IPX" },
1345    { 0x2d,	"VJ compressed TCP/IP" },
1346    { 0x2f,	"VJ uncompressed TCP/IP" },
1347    { 0x31,	"Bridging PDU" },
1348    { 0x33,	"Stream Protocol ST-II" },
1349    { 0x35,	"Banyan Vines" },
1350    { 0x39,	"AppleTalk EDDP" },
1351    { 0x3b,	"AppleTalk SmartBuffered" },
1352    { 0x3d,	"Multi-Link" },
1353    { 0x3f,	"NETBIOS Framing" },
1354    { 0x41,	"Cisco Systems" },
1355    { 0x43,	"Ascom Timeplex" },
1356    { 0x45,	"Fujitsu Link Backup and Load Balancing (LBLB)" },
1357    { 0x47,	"DCA Remote Lan" },
1358    { 0x49,	"Serial Data Transport Protocol (PPP-SDTP)" },
1359    { 0x4b,	"SNA over 802.2" },
1360    { 0x4d,	"SNA" },
1361    { 0x4f,	"IP6 Header Compression" },
1362    { 0x6f,	"Stampede Bridging" },
1363    { 0xfb,	"single-link compression" },
1364    { 0xfd,	"1st choice compression" },
1365    { 0x0201,	"802.1d Hello Packets" },
1366    { 0x0203,	"IBM Source Routing BPDU" },
1367    { 0x0205,	"DEC LANBridge100 Spanning Tree" },
1368    { 0x0231,	"Luxcom" },
1369    { 0x0233,	"Sigma Network Systems" },
1370    { 0x0235,	"Apple Client Server Protocol" },
1371    { 0x8021,	"Internet Protocol Control Protocol" },
1372    { 0x8023,	"OSI Network Layer Control Protocol" },
1373    { 0x8025,	"Xerox NS IDP Control Protocol" },
1374    { 0x8027,	"DECnet Phase IV Control Protocol" },
1375    { 0x8029,	"Appletalk Control Protocol" },
1376    { 0x802b,	"Novell IPX Control Protocol" },
1377    { 0x8031,	"Bridging NCP" },
1378    { 0x8033,	"Stream Protocol Control Protocol" },
1379    { 0x8035,	"Banyan Vines Control Protocol" },
1380    { 0x803d,	"Multi-Link Control Protocol" },
1381    { 0x803f,	"NETBIOS Framing Control Protocol" },
1382    { 0x8041,	"Cisco Systems Control Protocol" },
1383    { 0x8043,	"Ascom Timeplex" },
1384    { 0x8045,	"Fujitsu LBLB Control Protocol" },
1385    { 0x8047,	"DCA Remote Lan Network Control Protocol (RLNCP)" },
1386    { 0x8049,	"Serial Data Control Protocol (PPP-SDCP)" },
1387    { 0x804b,	"SNA over 802.2 Control Protocol" },
1388    { 0x804d,	"SNA Control Protocol" },
1389    { 0x804f,	"IP6 Header Compression Control Protocol" },
1390    { 0x006f,	"Stampede Bridging Control Protocol" },
1391    { 0x80fb,	"Single Link Compression Control Protocol" },
1392    { 0x80fd,	"Compression Control Protocol" },
1393    { 0x8235,	"Apple Client Server Control Protocol" },
1394    { 0xc021,	"Link Control Protocol" },
1395    { 0xc023,	"Password Authentication Protocol" },
1396    { 0xc025,	"Link Quality Report" },
1397    { 0xc027,	"Shiva Password Authentication Protocol" },
1398    { 0xc029,	"CallBack Control Protocol (CBCP)" },
1399    { 0xc081,	"Container Control Protocol" },
1400    { 0xc223,	"Challenge Handshake Authentication Protocol" },
1401    { 0xc281,	"Proprietary Authentication Protocol" },
1402    { 0,	NULL },
1403};
1404
1405/*
1406 * protocol_name - find a name for a PPP protocol.
1407 */
1408const char *
1409protocol_name(proto)
1410    int proto;
1411{
1412    struct protocol_list *lp;
1413
1414    for (lp = protocol_list; lp->proto != 0; ++lp)
1415	if (proto == lp->proto)
1416	    return lp->name;
1417    return NULL;
1418}
1419
1420/*
1421 * get_input - called when incoming data is available.
1422 */
1423static void
1424get_input()
1425{
1426    int len, i;
1427    u_char *p;
1428    u_short protocol;
1429    struct protent *protp;
1430
1431    p = inpacket_buf;	/* point to beginning of packet buffer */
1432
1433    len = read_packet(inpacket_buf);
1434    if (len < 0)
1435	return;
1436
1437    if (len == 0) {
1438	notice("Modem hangup");
1439	hungup = 1;
1440#ifdef __APPLE__
1441        if (status != EXIT_USER_REQUEST)
1442#endif
1443	status = EXIT_HANGUP;
1444	lcp_lowerdown(0);	/* serial link is no longer available */
1445	link_terminated(0);
1446	return;
1447    }
1448
1449    if (len < PPP_HDRLEN) {
1450#ifdef __APPLE__
1451	if (debug > 1)
1452#endif
1453	dbglog("received short packet:%.*B", len, p);
1454	return;
1455    }
1456
1457    dump_packet("rcvd", p, len);
1458    if (snoop_recv_hook) snoop_recv_hook(p, len);
1459
1460    p += 2;				/* Skip address and control */
1461    GETSHORT(protocol, p);
1462    len -= PPP_HDRLEN;
1463
1464    /*
1465     * Toss all non-LCP packets unless LCP is OPEN.
1466     */
1467    if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
1468#ifdef __APPLE__
1469	if (debug > 1)
1470#endif
1471	dbglog("Discarded non-LCP packet when LCP not open");
1472	return;
1473    }
1474
1475    /*
1476     * Until we get past the authentication phase, toss all packets
1477     * except LCP, LQR and authentication packets.
1478     */
1479    if (phase <= PHASE_AUTHENTICATE
1480	&& !(protocol == PPP_LCP || protocol == PPP_LQR
1481	     || protocol == PPP_PAP || protocol == PPP_CHAP ||
1482		protocol == PPP_EAP)) {
1483#ifdef __APPLE__
1484		if (unexpected_network_packet(0, protocol)) {
1485#endif
1486
1487#ifdef __APPLE__
1488	if (debug > 1)
1489#endif
1490	dbglog("discarding proto 0x%x in phase %d",
1491		   protocol, phase);
1492	return;
1493#ifdef __APPLE__
1494		}
1495#endif
1496    }
1497
1498    /*
1499     * Upcall the proper protocol input routine.
1500     */
1501    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
1502	if (protp->protocol == protocol && protp->enabled_flag) {
1503	    (*protp->input)(0, p, len);
1504	    return;
1505	}
1506#ifdef __APPLE__
1507		if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag) {
1508			if (protp->datainput != NULL) {
1509				(*protp->datainput)(0, p, len);
1510				return;
1511			}
1512			if (protp->state != NULL && (protp->state(0) == OPENED)) {
1513				// pppd receives data for a protocol in opened state.
1514				// this can happen if the peer sends packets too fast after its control protocol
1515				// reaches the opened state, pppd hasn't had time yet to process the control protocol
1516				// packet, and the kernel is still configured to reject the data packet.
1517				// in this case, just ignore the packet.
1518				// if this happens for an other reason, then there is probably a bug somewhere
1519				MAINDEBUG(("Data packet of protocol 0x%x received, with control prococol in opened state", protocol));
1520				return;
1521			}
1522		}
1523#else
1524        if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
1525	    && protp->datainput != NULL) {
1526	    (*protp->datainput)(0, p, len);
1527	    return;
1528	}
1529#endif
1530    }
1531
1532    if (debug) {
1533	const char *pname = protocol_name(protocol);
1534	if (pname != NULL)
1535	    warning("Unsupported protocol '%s' (0x%x) received", pname, protocol);
1536	else
1537	    warning("Unsupported protocol 0x%x received", protocol);
1538    }
1539    lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
1540}
1541
1542/*
1543 * ppp_send_config - configure the transmit-side characteristics of
1544 * the ppp interface.  Returns -1, indicating an error, if the channel
1545 * send_config procedure called error() (or incremented error_count
1546 * itself), otherwise 0.
1547 */
1548int
1549ppp_send_config(unit, mtu, accm, pcomp, accomp)
1550    int unit, mtu;
1551    u_int32_t accm;
1552    int pcomp, accomp;
1553{
1554	int errs;
1555
1556	if (the_channel->send_config == NULL)
1557		return 0;
1558	errs = error_count;
1559	(*the_channel->send_config)(mtu, accm, pcomp, accomp);
1560	return (error_count != errs)? -1: 0;
1561}
1562
1563/*
1564 * ppp_recv_config - configure the receive-side characteristics of
1565 * the ppp interface.  Returns -1, indicating an error, if the channel
1566 * recv_config procedure called error() (or incremented error_count
1567 * itself), otherwise 0.
1568 */
1569int
1570ppp_recv_config(unit, mru, accm, pcomp, accomp)
1571    int unit, mru;
1572    u_int32_t accm;
1573    int pcomp, accomp;
1574{
1575	int errs;
1576
1577	if (the_channel->recv_config == NULL)
1578		return 0;
1579	errs = error_count;
1580	(*the_channel->recv_config)(mru, accm, pcomp, accomp);
1581	return (error_count != errs)? -1: 0;
1582}
1583
1584/*
1585 * new_phase - signal the start of a new phase of pppd's operation.
1586 */
1587void
1588new_phase(p)
1589    int p;
1590{
1591    phase = p;
1592    if (new_phase_hook)
1593	(*new_phase_hook)(p);
1594    notify(phasechange, p);
1595}
1596
1597/*
1598 * die - clean up state and exit with the specified status.
1599 */
1600void
1601die(status)
1602    int status;
1603{
1604#ifndef __APPLE__
1605	print_link_stats();
1606#endif
1607    cleanup();
1608    notify(exitnotify, status);
1609    sys_log(LOG_INFO, "Exit.");
1610    exit(status);
1611}
1612
1613/*
1614 * cleanup - restore anything which needs to be restored before we exit
1615 */
1616/* ARGSUSED */
1617static void
1618cleanup()
1619{
1620    sys_cleanup();
1621
1622    if (fd_ppp >= 0)
1623	the_channel->disestablish_ppp(devfd);
1624    if (the_channel->cleanup)
1625	(*the_channel->cleanup)();
1626
1627    if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
1628	warning("unable to delete pid file %s: %m", pidfilename);
1629    pidfilename[0] = 0;
1630    if (linkpidfile[0] != 0 && unlink(linkpidfile) < 0 && errno != ENOENT)
1631	warning("unable to delete pid file %s: %m", linkpidfile);
1632    linkpidfile[0] = 0;
1633
1634#ifdef USE_TDB
1635    if (pppdb != NULL)
1636	cleanup_db();
1637#endif
1638
1639}
1640
1641void
1642print_link_stats()
1643{
1644    /*
1645     * Print connect time and statistics.
1646     */
1647    if (link_stats_valid) {
1648       int t = (link_connect_time + 5) / 6;    /* 1/10ths of minutes */
1649       info("Connect time %d.%d minutes.", t/10, t%10);
1650       info("Sent %u bytes, received %u bytes.",
1651	    link_stats.bytes_out, link_stats.bytes_in);
1652    }
1653}
1654
1655/*
1656 * update_link_stats - get stats at link termination.
1657 */
1658void
1659update_link_stats(u)
1660    int u;
1661{
1662    struct timeval now;
1663    char numbuf[32];
1664
1665    if (!get_ppp_stats(u, &link_stats)
1666	|| gettimeofday(&now, NULL) < 0)
1667	return;
1668    link_connect_time = now.tv_sec - start_time.tv_sec;
1669    link_stats_valid = 1;
1670
1671    slprintf(numbuf, sizeof(numbuf), "%u", link_connect_time);
1672    script_setenv("CONNECT_TIME", numbuf, 0);
1673    slprintf(numbuf, sizeof(numbuf), "%u", link_stats.bytes_out);
1674    script_setenv("BYTES_SENT", numbuf, 0);
1675    slprintf(numbuf, sizeof(numbuf), "%u", link_stats.bytes_in);
1676    script_setenv("BYTES_RCVD", numbuf, 0);
1677}
1678
1679
1680struct	callout {
1681    struct timeval	c_time;		/* time at which to call routine */
1682    void		*c_arg;		/* argument to routine */
1683    void		(*c_func) __P((void *)); /* routine */
1684    struct		callout *c_next;
1685};
1686
1687static struct callout *callout = NULL;	/* Callout list */
1688static struct timeval timenow;		/* Current time */
1689
1690/*
1691 * timeout - Schedule a timeout.
1692 */
1693void
1694timeout(func, arg, secs, usecs)
1695    void (*func) __P((void *));
1696    void *arg;
1697    int secs, usecs;
1698{
1699    struct callout *newp, *p, **pp;
1700
1701    MAINDEBUG(("Timeout %p:%p in %d.%03d seconds.", func, arg,
1702	       secs, usecs/1000));
1703
1704    /*
1705     * Allocate timeout.
1706     */
1707    if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
1708	fatal("Out of memory in timeout()!");
1709    newp->c_arg = arg;
1710    newp->c_func = func;
1711#ifdef __APPLE__
1712    // timeout get screwed up if you change the current time of the machine...
1713    // use absolute time instead, as we are just interested in deltas, not actual time.
1714    getabsolutetime(&timenow);
1715#else
1716    gettimeofday(&timenow, NULL);
1717#endif
1718    newp->c_time.tv_sec = timenow.tv_sec + secs;
1719    newp->c_time.tv_usec = timenow.tv_usec + usecs;
1720    if (newp->c_time.tv_usec >= 1000000) {
1721	newp->c_time.tv_sec += newp->c_time.tv_usec / 1000000;
1722	newp->c_time.tv_usec %= 1000000;
1723    }
1724
1725    /*
1726     * Find correct place and link it in.
1727     */
1728    for (pp = &callout; (p = *pp); pp = &p->c_next)
1729	if (newp->c_time.tv_sec < p->c_time.tv_sec
1730	    || (newp->c_time.tv_sec == p->c_time.tv_sec
1731		&& newp->c_time.tv_usec < p->c_time.tv_usec))
1732	    break;
1733    newp->c_next = p;
1734    *pp = newp;
1735}
1736
1737
1738/*
1739 * untimeout - Unschedule a timeout.
1740 */
1741void
1742untimeout(func, arg)
1743    void (*func) __P((void *));
1744    void *arg;
1745{
1746    struct callout **copp, *freep;
1747
1748    MAINDEBUG(("Untimeout %p:%p.", func, arg));
1749
1750    /*
1751     * Find first matching timeout and remove it from the list.
1752     */
1753    for (copp = &callout; (freep = *copp); copp = &freep->c_next)
1754	if (freep->c_func == func && freep->c_arg == arg) {
1755	    *copp = freep->c_next;
1756	    free((char *) freep);
1757	    break;
1758	}
1759}
1760
1761
1762/*
1763 * calltimeout - Call any timeout routines which are now due.
1764 */
1765static void
1766calltimeout()
1767{
1768    struct callout *p;
1769
1770    while (callout != NULL) {
1771	p = callout;
1772
1773#ifdef __APPLE__
1774        if (getabsolutetime(&timenow) < 0)
1775#else
1776	if (gettimeofday(&timenow, NULL) < 0)
1777#endif
1778	    fatal("Failed to get time of day: %m");
1779	if (!(p->c_time.tv_sec < timenow.tv_sec
1780	      || (p->c_time.tv_sec == timenow.tv_sec
1781		  && p->c_time.tv_usec <= timenow.tv_usec)))
1782	    break;		/* no, it's not time yet */
1783
1784	callout = p->c_next;
1785	(*p->c_func)(p->c_arg);
1786
1787	free((char *) p);
1788    }
1789}
1790
1791
1792/*
1793 * timeleft - return the length of time until the next timeout is due.
1794 */
1795static struct timeval *
1796timeleft(tvp)
1797    struct timeval *tvp;
1798{
1799    if (callout == NULL)
1800	return NULL;
1801
1802#ifdef __APPLE__
1803    getabsolutetime(&timenow);
1804#else
1805    gettimeofday(&timenow, NULL);
1806#endif
1807    tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
1808    tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
1809    if (tvp->tv_usec < 0) {
1810	tvp->tv_usec += 1000000;
1811	tvp->tv_sec -= 1;
1812    }
1813    if (tvp->tv_sec < 0)
1814	tvp->tv_sec = tvp->tv_usec = 0;
1815
1816    return tvp;
1817}
1818
1819
1820/*
1821 * kill_my_pg - send a signal to our process group, and ignore it ourselves.
1822 */
1823static void
1824kill_my_pg(sig)
1825    int sig;
1826{
1827    struct sigaction act, oldact;
1828
1829    act.sa_handler = SIG_IGN;
1830    act.sa_flags = 0;
1831    sigaction(sig, &act, &oldact);
1832    kill(0, sig);
1833    sigaction(sig, &oldact, NULL);
1834}
1835
1836
1837/*
1838 * hup - Catch SIGHUP signal.
1839 *
1840 * Indicates that the physical layer has been disconnected.
1841 * We don't rely on this indication; if the user has sent this
1842 * signal, we just take the link down.
1843 */
1844static void
1845hup(sig)
1846    int sig;
1847{
1848#ifdef __APPLE__
1849    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
1850        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
1851        /* <rdar://10258474> */
1852        return;
1853    }
1854#endif
1855    got_sighup = sig;
1856
1857#ifdef __APPLE__
1858    // connectors test that flag
1859    // handle event is not called when we are in the connect stage
1860    kill_link = 1;
1861#endif
1862
1863    if (conn_running)
1864	/* Send the signal to the [dis]connector process(es) also */
1865	kill_my_pg(sig);
1866    notify(sigreceived, sig);
1867#ifdef __APPLE__
1868    if (!hungup)
1869	status = EXIT_USER_REQUEST;
1870#endif
1871    if (waiting)
1872	siglongjmp(sigjmp, 1);
1873}
1874
1875
1876/*
1877 * term - Catch SIGTERM signal and SIGINT signal (^C/del).
1878 *
1879 * Indicates that we should initiate a graceful disconnect and exit.
1880 */
1881/*ARGSUSED*/
1882static void
1883term(sig)
1884    int sig;
1885{
1886#ifdef __APPLE__
1887    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
1888        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
1889        /* <rdar://10258474> */
1890        return;
1891    }
1892#endif
1893    got_sigterm = sig;
1894
1895#ifdef __APPLE__
1896    // connectors test that flag
1897    // handle event is not called when we are in the connect stage
1898    kill_link = 1;
1899    persist = 0;
1900    status = EXIT_USER_REQUEST;
1901#endif
1902
1903    if (conn_running)
1904	/* Send the signal to the [dis]connector process(es) also */
1905	kill_my_pg(sig);
1906    notify(sigreceived, sig);
1907    if (waiting)
1908	siglongjmp(sigjmp, 1);
1909}
1910
1911
1912/*
1913 * chld - Catch SIGCHLD signal.
1914 * Sets a flag so we will call reap_kids in the mainline.
1915 */
1916static void
1917chld(sig)
1918    int sig;
1919{
1920#ifdef __APPLE__
1921    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
1922        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
1923        /* <rdar://10258474> */
1924        return;
1925    }
1926#endif
1927    got_sigchld = 1;
1928    if (waiting)
1929	siglongjmp(sigjmp, 1);
1930}
1931
1932/*
1933 * stop - Catch SIGTSTP signal.
1934 *
1935 * Indicates that the physical is gone "on hold".
1936 * Stop all activity until we get the SIGCONT signal
1937 * or until we take the line down.
1938 */
1939static void
1940stop(sig)
1941    int sig;
1942{
1943
1944#ifdef __APPLE__
1945    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
1946        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
1947        /* <rdar://10258474> */
1948        return;
1949    }
1950#endif
1951    got_sigtstp = sig;
1952    switch (phase) {
1953        case PHASE_ONHOLD:	// already on hold
1954            break;
1955        case PHASE_RUNNING:	// needs to stop connection
1956            break;
1957        default:		// other states, simulate a sighup
1958            got_sighup = 1;
1959            if (conn_running)
1960                /* Send the signal to the [dis]connector process(es) also */
1961                kill_my_pg(sig);
1962    }
1963    notify(sigreceived, sig);
1964    if (waiting)
1965	siglongjmp(sigjmp, 1);
1966}
1967
1968/*
1969 * cont - Catch SIGCONT signal.
1970 *
1971 * resume all previously stopped activities.
1972 *
1973 */
1974static void
1975cont(sig)
1976    int sig;
1977{
1978#ifdef __APPLE__
1979    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
1980        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
1981        /* <rdar://10258474> */
1982        return;
1983    }
1984#endif
1985    got_sigcont = sig;
1986    notify(sigreceived, sig);
1987    if (waiting)
1988	siglongjmp(sigjmp, 1);
1989}
1990
1991/*
1992 * toggle_debug - Catch SIGUSR1 signal.
1993 *
1994 * Toggle debug flag.
1995 */
1996/*ARGSUSED*/
1997static void
1998toggle_debug(sig)
1999    int sig;
2000{
2001#ifdef __APPLE__
2002    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
2003        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
2004        /* <rdar://10258474> */
2005        return;
2006    }
2007#endif
2008    debug = !debug;
2009    if (debug) {
2010	setlogmask(LOG_UPTO(LOG_DEBUG));
2011    } else {
2012	setlogmask(LOG_UPTO(LOG_WARNING));
2013    }
2014}
2015
2016
2017/*
2018 * open_ccp - Catch SIGUSR2 signal.
2019 *
2020 * Try to (re)negotiate compression.
2021 */
2022/*ARGSUSED*/
2023static void
2024open_ccp(sig)
2025    int sig;
2026{
2027#ifdef __APPLE__
2028    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
2029        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
2030        /* <rdar://10258474> */
2031        return;
2032    }
2033#endif
2034    got_sigusr2 = 1;
2035    if (waiting)
2036	siglongjmp(sigjmp, 1);
2037}
2038
2039
2040/*
2041 * bad_signal - We've caught a fatal signal.  Clean up state and exit.
2042 */
2043static void
2044bad_signal(sig)
2045    int sig;
2046{
2047    static int crashed = 0;
2048
2049#ifdef __APPLE__
2050    if (mainthread_id && !(pthread_equal(mainthread_id, pthread_self()))){
2051        /* ignore signals if it's not the main thread, we will be dropping sigals but that's insignificant */
2052        /* <rdar://10258474> */
2053        return;
2054    }
2055#endif
2056    if (crashed)
2057	_exit(127);
2058    crashed = 1;
2059    error("Fatal signal %d", sig);
2060    if (conn_running)
2061	kill_my_pg(SIGTERM);
2062    notify(sigreceived, sig);
2063    die(127);
2064}
2065
2066/*
2067 * safe_fork - Create a child process.  The child closes all the
2068 * file descriptors that we don't want to leak to a script.
2069 * The parent waits for the child to do this before returning.
2070 */
2071pid_t
2072safe_fork()
2073{
2074	pid_t pid;
2075	int pipefd[2];
2076	char buf[1];
2077
2078	if (pipe(pipefd) == -1)
2079		pipefd[0] = pipefd[1] = -1;
2080	pid = fork();
2081	if (pid < 0)
2082		return -1;
2083	if (pid > 0) {
2084		close(pipefd[1]);
2085		/* this read() blocks until the close(pipefd[1]) below */
2086		complete_read(pipefd[0], buf, 1);
2087		close(pipefd[0]);
2088		return pid;
2089	}
2090	sys_close();
2091#ifdef __APPLE__
2092	options_close();
2093#endif
2094#ifdef USE_TDB
2095	tdb_close(pppdb);
2096#endif
2097	notify(fork_notifier, 0);
2098	close(pipefd[0]);
2099	/* this close unblocks the read() call above in the parent */
2100	close(pipefd[1]);
2101	return 0;
2102}
2103
2104/*
2105 * device_script - run a program to talk to the specified fds
2106 * (e.g. to run the connector or disconnector script).
2107 * stderr gets connected to the log fd or to the _PATH_CONNERRS file.
2108 */
2109#ifdef __APPLE__
2110#define PPP_ARG_FD 3
2111int
2112device_script(program, in, out, dont_wait, program_uid, pipe_args, pipe_args_len)
2113    char *program;
2114    int in, out;
2115    int dont_wait;
2116	uid_t program_uid;
2117	char *pipe_args;
2118	int pipe_args_len;
2119#else
2120int
2121device_script(program, in, out, dont_wait)
2122    char *program;
2123    int in, out;
2124    int dont_wait;
2125#endif
2126{
2127    int pid;
2128    int status = -1;
2129    int errfd;
2130    int fd;
2131	int fdp[2];
2132
2133//error("device script '%s'\n", program);
2134
2135	fdp[0] = fdp[1] = -1;
2136    if (pipe_args) {
2137		if (pipe(fdp) == -1) {
2138			error("Failed to setup pipe with device script: %m");
2139			return -1;
2140		}
2141	}
2142
2143    ++conn_running;
2144    pid = safe_fork();
2145
2146    if (pid < 0) {
2147		--conn_running;
2148		error("Failed to create child process: %m");
2149		return -1;
2150    }
2151
2152	if (pid > 0) {
2153		// running in parent
2154		// close read end of the pipe
2155			if (fdp[0] != -1) {
2156			close(fdp[0]);
2157			fdp[0] = -1;
2158		}
2159		// write args on the write end of the pipe, and close it
2160			if (fdp[1] != -1) {
2161			write(fdp[1], pipe_args, pipe_args_len);
2162			close(fdp[1]);
2163			fdp[1] = -1;
2164		}
2165		if (dont_wait) {
2166			record_child(pid, program, NULL, NULL);
2167			status = 0;
2168		} else {
2169			while (waitpid(pid, &status, 0) < 0) {
2170				if (errno == EINTR)
2171					continue;
2172				fatal("error waiting for (dis)connection process: %m");
2173			}
2174			--conn_running;
2175		}
2176#ifdef __APPLE__
2177	// return real status code
2178	// Fix me :	return only the lowest 8 bits
2179			return WEXITSTATUS(status);
2180#else
2181		return (status == 0 ? 0 : -1);
2182#endif
2183	}
2184
2185	/* here we are executing in the child */
2186
2187	/* make sure fds 0, 1, 2 are occupied */
2188	while ((fd = dup(in)) >= 0) {
2189		if (fd > 2) {
2190			close(fd);
2191			break;
2192		}
2193	}
2194
2195    /* dup in and out to fds > 2 */
2196    {
2197	int fd1 = in, fd2 = out, fd3 = log_to_fd;
2198
2199	in = dup(in);
2200	out = dup(out);
2201	if (log_to_fd >= 0) {
2202	    errfd = dup(log_to_fd);
2203	} else {
2204	    errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
2205	}
2206	close(fd1);
2207	close(fd2);
2208	close(fd3);
2209    }
2210
2211    /* close fds 0 - 2 and any others we can think of */
2212    close(0);
2213    close(1);
2214    close(2);
2215    if (the_channel->close)
2216	(*the_channel->close)();
2217    closelog();
2218    close(fd_devnull);
2219	if (fdp[1] != -1) {
2220		close(fdp[1]);
2221		fdp[1] = -1;
2222	}
2223
2224    /* dup the in, out, err fds to 0, 1, 2 */
2225    dup2(in, 0);
2226    close(in);
2227    dup2(out, 1);
2228    close(out);
2229    if (errfd >= 0) {
2230	dup2(errfd, 2);
2231	close(errfd);
2232    }
2233
2234#ifdef __APPLE__
2235    if (fdp[0] != -1) {
2236        dup2(fdp[0], PPP_ARG_FD);
2237        close(fdp[0]);
2238        fdp[0] = PPP_ARG_FD;
2239        closeallfrom(PPP_ARG_FD + 1);
2240    } else {
2241        /* make sure all fds 3 and above get closed, in case a library leaked */
2242        closeallfrom(3);
2243    }
2244
2245    if (program_uid == -1)
2246        program_uid = uid;
2247    setuid(program_uid);
2248    if (getuid() != program_uid) {
2249	error("setuid failed");
2250	exit(1);
2251    }
2252    setgid(getgid());
2253#else
2254    setuid(uid);
2255    if (getuid() != uid) {
2256	error("setuid failed");
2257	exit(1);
2258    }
2259    setgid(getgid());
2260	}
2261#endif
2262    execle("/bin/sh", "sh", "-c", program, (char *)0, (char *)0);
2263    error("could not exec /bin/sh: %m");
2264    exit(99);
2265    /* NOTREACHED */
2266}
2267
2268
2269/*
2270 * run-program - execute a program with given arguments,
2271 * but don't wait for it.
2272 * If the program can't be executed, logs an error unless
2273 * must_exist is 0 and the program file doesn't exist.
2274 * Returns -1 if it couldn't fork, 0 if the file doesn't exist
2275 * or isn't an executable plain file, or the process ID of the child.
2276 * If done != NULL, (*done)(arg) will be called later (within
2277 * reap_kids) iff the return value is > 0.
2278 */
2279pid_t
2280run_program(prog, args, must_exist, done, arg)
2281    char *prog;
2282    char **args;
2283    int must_exist;
2284    void (*done) __P((void *));
2285    void *arg;
2286{
2287    int pid;
2288    struct stat sbuf;
2289
2290    /*
2291     * First check if the file exists and is executable.
2292     * We don't use access() because that would use the
2293     * real user-id, which might not be root, and the script
2294     * might be accessible only to root.
2295     */
2296    errno = EINVAL;
2297    if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)
2298	|| (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
2299	if (must_exist || errno != ENOENT)
2300	    warning("Can't execute %s: %m", prog);
2301
2302	return 0;
2303    }
2304
2305    pid = safe_fork();
2306    if (pid == -1) {
2307	error("Failed to create child process for %s: %m", prog);
2308	return -1;
2309    }
2310    if (pid != 0) {
2311	if (debug)
2312	    dbglog("Script %s started (pid %d)", prog, pid);
2313	record_child(pid, prog, done, arg);
2314	return pid;
2315    }
2316
2317    /* Leave the current location */
2318    (void) setsid();	/* No controlling tty. */
2319    (void) umask (S_IRWXG|S_IRWXO);
2320    (void) chdir ("/");	/* no current directory. */
2321    setuid(0);		/* set real UID = root */
2322    setgid(getegid());
2323
2324    /* Ensure that nothing of our device environment is inherited. */
2325    closelog();
2326    if (the_channel->close)
2327	(*the_channel->close)();
2328
2329    /* Don't pass handles to the PPP device, even by accident. */
2330    dup2(fd_devnull, 0);
2331    dup2(fd_devnull, 1);
2332    dup2(fd_devnull, 2);
2333    close(fd_devnull);
2334
2335
2336#ifdef __APPLE__
2337	/* make sure all fd 3 and above, in case a library leaked */
2338	closeallfrom(3);
2339#endif
2340
2341#ifdef BSD
2342    /* Force the priority back to zero if pppd is running higher. */
2343    if (setpriority (PRIO_PROCESS, 0, 0) < 0)
2344	warning("can't reset priority to 0: %m");
2345#endif
2346
2347    /* SysV recommends a second fork at this point. */
2348
2349    /* run the program */
2350    execve(prog, args, script_env);
2351    if (must_exist || errno != ENOENT) {
2352	/* have to reopen the log, there's nowhere else
2353	   for the message to go. */
2354	reopen_log();
2355	sys_log(LOG_ERR, "Can't execute %s: %m", prog);
2356	closelog();
2357    }
2358    _exit(-1);
2359}
2360
2361
2362/*
2363 * record_child - add a child process to the list for reap_kids
2364 * to use.
2365 */
2366void
2367record_child(pid, prog, done, arg)
2368    int pid;
2369    char *prog;
2370    void (*done) __P((void *));
2371    void *arg;
2372{
2373    struct subprocess *chp;
2374
2375    ++n_children;
2376
2377    chp = (struct subprocess *) malloc(sizeof(struct subprocess));
2378    if (chp == NULL) {
2379	warning("losing track of %s process", prog);
2380    } else {
2381	chp->pid = pid;
2382	chp->prog = prog;
2383	chp->done = done;
2384	chp->arg = arg;
2385	chp->next = children;
2386	children = chp;
2387    }
2388}
2389
2390
2391/*
2392 * reap_kids - get status from any dead child processes,
2393 * and log a message for abnormal terminations.
2394 */
2395static int
2396reap_kids(waitfor)
2397    int waitfor;
2398{
2399    int pid, status;
2400    struct subprocess *chp, **prevp;
2401
2402    if (n_children == 0)
2403	return 0;
2404    while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1
2405	   && pid != 0) {
2406	for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
2407	    if (chp->pid == pid) {
2408		--n_children;
2409		*prevp = chp->next;
2410		break;
2411	    }
2412	}
2413	if (WIFSIGNALED(status)) {
2414	    warning("Child process %s (pid %d) terminated with signal %d",
2415		 (chp? chp->prog: "??"), pid, WTERMSIG(status));
2416	} else if (debug)
2417	    dbglog("Script %s finished (pid %d), status = 0x%x",
2418		   (chp? chp->prog: "??"), pid,
2419		   WIFEXITED(status) ? WEXITSTATUS(status) : status);
2420	if (chp && chp->done)
2421	    (*chp->done)(chp->arg);
2422	if (chp)
2423	    free(chp);
2424    }
2425    if (pid == -1) {
2426	if (errno == ECHILD)
2427	    return -1;
2428	if (errno != EINTR)
2429	    error("Error waiting for child process: %m");
2430    }
2431    return 0;
2432}
2433
2434/*
2435 * add_notifier - add a new function to be called when something happens.
2436 */
2437void
2438add_notifier(notif, func, arg)
2439    struct notifier **notif;
2440    notify_func func;
2441    void *arg;
2442{
2443    struct notifier *np;
2444
2445    np = malloc(sizeof(struct notifier));
2446    if (np == 0)
2447	novm("notifier struct");
2448    np->next = *notif;
2449    np->func = func;
2450    np->arg = arg;
2451    *notif = np;
2452}
2453
2454void
2455add_notifier_last(notif, func, arg)
2456    struct notifier **notif;
2457    notify_func func;
2458    void *arg;
2459{
2460    struct notifier *np;
2461
2462    np = malloc(sizeof(struct notifier));
2463    if (np == 0)
2464        novm("notifier struct");
2465
2466    np->next = NULL;
2467    np->func = func;
2468    np->arg = arg;
2469
2470    if (*notif == NULL)
2471        *notif = np;
2472    else {
2473        struct notifier *cur = *notif;
2474        while (cur->next != NULL)
2475            cur = cur->next;
2476        cur->next = np;
2477    }
2478}
2479
2480/*
2481 * remove_notifier - remove a function from the list of things to
2482 * be called when something happens.
2483 */
2484void
2485remove_notifier(notif, func, arg)
2486    struct notifier **notif;
2487    notify_func func;
2488    void *arg;
2489{
2490    struct notifier *np;
2491
2492    for (; (np = *notif) != 0; notif = &np->next) {
2493	if (np->func == func && np->arg == arg) {
2494	    *notif = np->next;
2495	    free(np);
2496	    break;
2497	}
2498    }
2499}
2500
2501/*
2502 * notify - call a set of functions registered with add_notifier.
2503 */
2504void
2505notify(notif, val)
2506    struct notifier *notif;
2507    int val;
2508{
2509    struct notifier *np;
2510
2511    while ((np = notif) != 0) {
2512	notif = np->next;
2513	(*np->func)(np->arg, val);
2514    }
2515}
2516
2517/*
2518 * notify - call a set of functions registered with add_notifier using a unsigned 64-bit val (e.g a pointer).
2519 */
2520void
2521notify_with_ptr(notif, val)
2522    struct notifier *notif;
2523    uintptr_t val;
2524{
2525    struct notifier *np;
2526
2527    while ((np = notif) != 0) {
2528	notif = np->next;
2529	(*np->func)(np->arg, val);
2530    }
2531}
2532
2533/*
2534 * novm - log an error message saying we ran out of memory, and die.
2535 */
2536void
2537novm(msg)
2538    char *msg;
2539{
2540    fatal("Virtual memory exhausted allocating %s\n", msg);
2541}
2542
2543/*
2544 * script_setenv - set an environment variable value to be used
2545 * for scripts that we run (e.g. ip-up, auth-up, etc.)
2546 */
2547void
2548script_setenv(var, value, iskey)
2549    char *var, *value;
2550    int iskey;
2551{
2552    size_t varl = strlen(var);
2553    size_t vl = varl + strlen(value) + 2;
2554    int i;
2555    char *p, *newstring;
2556
2557    newstring = (char *) malloc(vl+1);
2558    if (newstring == 0)
2559	return;
2560
2561#ifdef USE_TDB
2562	/*
2563		The byte before the string is used to store the "iskey" value.
2564		It will be used later to know if delete_db_key() needs to be called.
2565		By moving the pointer to the actual start of the string, the original
2566		pointer to the allocated memory is "lost", and the string will appear
2567		as leaked in the 'leaks' command.
2568		This could be done better. It is only necessary when TDB is used.
2569	*/
2570    *newstring++ = iskey;
2571#endif
2572
2573    slprintf(newstring, vl, "%s=%s", var, value);
2574
2575    /* check if this variable is already set */
2576    if (script_env != 0) {
2577	for (i = 0; (p = script_env[i]) != 0; ++i) {
2578	    if (strncmp(p, var, varl) == 0 && p[varl] == '=') {
2579#ifdef USE_TDB
2580		if (p[-1] && pppdb != NULL)
2581		    delete_db_key(p);
2582#endif
2583#ifdef USE_TDB
2584		/* see comment about how "iskey" is stored */
2585		free(p-1);
2586#else
2587		free(p);
2588#endif
2589		script_env[i] = newstring;
2590#ifdef USE_TDB
2591		if (iskey && pppdb != NULL)
2592		    add_db_key(newstring);
2593		update_db_entry();
2594#endif
2595		return;
2596	    }
2597	}
2598    } else {
2599	/* no space allocated for script env. ptrs. yet */
2600	i = 0;
2601	script_env = (char **) malloc(16 * sizeof(char *));
2602	if (script_env == 0)
2603	    return;
2604	s_env_nalloc = 16;
2605    }
2606
2607    /* reallocate script_env with more space if needed */
2608    if (i + 1 >= s_env_nalloc) {
2609	int new_n = i + 17;
2610	char **newenv = (char **) realloc((void *)script_env,
2611					  new_n * sizeof(char *));
2612	if (newenv == 0)
2613	    return;
2614	script_env = newenv;
2615	s_env_nalloc = new_n;
2616    }
2617
2618    script_env[i] = newstring;
2619    script_env[i+1] = 0;
2620
2621#ifdef USE_TDB
2622    if (pppdb != NULL) {
2623	if (iskey)
2624	    add_db_key(newstring);
2625	update_db_entry();
2626    }
2627#endif
2628}
2629
2630/*
2631 * script_unsetenv - remove a variable from the environment
2632 * for scripts.
2633 */
2634void
2635script_unsetenv(var)
2636    char *var;
2637{
2638    int vl = strlen(var);
2639    int i;
2640    char *p;
2641
2642    if (script_env == 0)
2643	return;
2644    for (i = 0; (p = script_env[i]) != 0; ++i) {
2645	if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
2646#ifdef USE_TDB
2647	    if (p[-1] && pppdb != NULL)
2648		delete_db_key(p);
2649#endif
2650#ifdef USE_TDB
2651		/* see comment about how "iskey" is stored */
2652		free(p-1);
2653#else
2654		free(p);
2655#endif
2656	    while ((script_env[i] = script_env[i+1]) != 0)
2657		++i;
2658	    break;
2659	}
2660    }
2661#ifdef USE_TDB
2662    if (pppdb != NULL)
2663	update_db_entry();
2664#endif
2665}
2666
2667#ifdef USE_TDB
2668/*
2669 * update_db_entry - update our entry in the database.
2670 */
2671static void
2672update_db_entry()
2673{
2674    TDB_DATA key, dbuf;
2675    int vlen, i;
2676    char *p, *q, *vbuf;
2677
2678    if (script_env == NULL)
2679	return;
2680    vlen = 0;
2681    for (i = 0; (p = script_env[i]) != 0; ++i)
2682	vlen += strlen(p) + 1;
2683    vbuf = malloc(vlen);
2684    if (vbuf == 0)
2685	novm("database entry");
2686    q = vbuf;
2687    for (i = 0; (p = script_env[i]) != 0; ++i)
2688	q += slprintf(q, vbuf + vlen - q, "%s;", p);
2689
2690    key.dptr = db_key;
2691    key.dsize = strlen(db_key);
2692    dbuf.dptr = vbuf;
2693    dbuf.dsize = vlen;
2694    if (tdb_store(pppdb, key, dbuf, TDB_REPLACE))
2695	error("tdb_store failed: %s", tdb_error(pppdb));
2696
2697    if (vbuf)
2698        free(vbuf);
2699
2700}
2701
2702/*
2703 * add_db_key - add a key that we can use to look up our database entry.
2704 */
2705static void
2706add_db_key(str)
2707    const char *str;
2708{
2709    TDB_DATA key, dbuf;
2710
2711    key.dptr = (char *) str;
2712    key.dsize = strlen(str);
2713    dbuf.dptr = db_key;
2714    dbuf.dsize = strlen(db_key);
2715    if (tdb_store(pppdb, key, dbuf, TDB_REPLACE))
2716	error("tdb_store key failed: %s", tdb_error(pppdb));
2717}
2718
2719/*
2720 * delete_db_key - delete a key for looking up our database entry.
2721 */
2722static void
2723delete_db_key(str)
2724    const char *str;
2725{
2726    TDB_DATA key;
2727
2728    key.dptr = (char *) str;
2729    key.dsize = strlen(str);
2730    tdb_delete(pppdb, key);
2731}
2732
2733/*
2734 * cleanup_db - delete all the entries we put in the database.
2735 */
2736static void
2737cleanup_db()
2738{
2739    TDB_DATA key;
2740    int i;
2741    char *p;
2742
2743    key.dptr = db_key;
2744    key.dsize = strlen(db_key);
2745    tdb_delete(pppdb, key);
2746    for (i = 0; (p = script_env[i]) != 0; ++i)
2747	if (p[-1])
2748	    delete_db_key(p);
2749}
2750#endif /* USE_TDB */
2751