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