main.c revision 1.9
1/* $OpenBSD: main.c,v 1.9 1996/07/20 12:02:11 joshd Exp $ */ 2 3/* 4 * main.c - Point-to-Point Protocol main module 5 * 6 * Copyright (c) 1989 Carnegie Mellon University. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms are permitted 10 * provided that the above copyright notice and this paragraph are 11 * duplicated in all such forms and that any documentation, 12 * advertising materials, and other materials related to such 13 * distribution and use acknowledge that the software was developed 14 * by Carnegie Mellon University. The name of the 15 * University may not be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22#ifndef lint 23static char rcsid[] = "$OpenBSD: main.c,v 1.9 1996/07/20 12:02:11 joshd Exp $"; 24#endif 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include <unistd.h> 30#include <signal.h> 31#include <errno.h> 32#include <fcntl.h> 33#include <syslog.h> 34#include <netdb.h> 35#include <utmp.h> 36#include <pwd.h> 37#include <sys/param.h> 38#include <sys/types.h> 39#include <sys/wait.h> 40#include <sys/time.h> 41#include <sys/resource.h> 42#include <sys/stat.h> 43#include <sys/socket.h> 44#include <net/if.h> 45 46#include "pppd.h" 47#include "magic.h" 48#include "fsm.h" 49#include "lcp.h" 50#include "ipcp.h" 51#include "upap.h" 52#include "chap.h" 53#include "ccp.h" 54#include "pathnames.h" 55#include "patchlevel.h" 56 57#ifdef IPX_CHANGE 58#include "ipxcp.h" 59#endif /* IPX_CHANGE */ 60 61/* 62 * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless 63 * /etc/ppp/options exists. 64 */ 65#ifndef REQ_SYSOPTIONS 66#define REQ_SYSOPTIONS 1 67#endif 68 69/* interface vars */ 70char ifname[IFNAMSIZ]; /* Interface name */ 71int ifunit; /* Interface unit number */ 72 73char *progname; /* Name of this program */ 74char hostname[MAXNAMELEN]; /* Our hostname */ 75static char pidfilename[MAXPATHLEN]; /* name of pid file */ 76static char default_devnam[MAXPATHLEN]; /* name of default device */ 77static pid_t pid; /* Our pid */ 78static uid_t uid; /* Our real user-id */ 79 80int ttyfd = -1; /* Serial port file descriptor */ 81mode_t tty_mode = -1; /* Original access permissions to tty */ 82int baud_rate; /* Actual bits/second for serial device */ 83int hungup; /* terminal has been hung up */ 84 85 86int phase; /* where the link is at */ 87int kill_link; 88int open_ccp_flag; 89int redirect_stderr; /* Connector's stderr should go to file */ 90 91u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */ 92u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ 93 94int hungup; /* terminal has been hung up */ 95static int n_children; /* # child processes still running */ 96 97int baud_rate; /* Actual bits/second for serial device */ 98 99static int locked; /* lock() has succeeded */ 100 101char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; 102 103/* Prototypes for procedures local to this file. */ 104 105static void cleanup __P((void)); 106static void close_tty __P((void)); 107static void get_input __P((void)); 108static void connect_time_expired __P((caddr_t)); 109static void calltimeout __P((void)); 110static struct timeval *timeleft __P((struct timeval *)); 111static void hup __P((int)); 112static void term __P((int)); 113static void chld __P((int)); 114static void toggle_debug __P((int)); 115static void open_ccp __P((int)); 116static void bad_signal __P((int)); 117static void holdoff_end __P((void *)); 118static int device_script __P((char *, int, int)); 119static void reap_kids __P((void)); 120static void pr_log __P((void *, char *, ...)); 121 122extern char *ttyname __P((int)); 123extern char *getlogin __P((void)); 124 125#ifdef ultrix 126#undef O_NONBLOCK 127#define O_NONBLOCK O_NDELAY 128#endif 129 130#ifdef PRIMITIVE_SYSLOG 131#define setlogmask(x) 132#endif 133 134/* 135 * PPP Data Link Layer "protocol" table. 136 * One entry per supported protocol. 137 * The last entry must be NULL. 138 */ 139struct protent *protocols[] = { 140 &lcp_protent, 141 &pap_protent, 142 &chap_protent, 143 &ipcp_protent, 144 &ccp_protent, 145#ifdef IPX_CHANGE 146 &ipxcp_protent, 147#endif 148 NULL 149}; 150 151int 152main(argc, argv) 153 int argc; 154 char *argv[]; 155{ 156 int i, nonblock, fdflags; 157 struct sigaction sa; 158 FILE *pidfile; 159 char *p; 160 struct passwd *pw; 161 struct timeval timo; 162 sigset_t mask; 163 struct protent *protp; 164 struct stat statbuf; 165 166 phase = PHASE_INITIALIZE; 167 p = ttyname(0); 168 if (p) 169 strcpy(devnam, p); 170 strcpy(default_devnam, devnam); 171 172 /* Initialize syslog facilities */ 173#ifdef PRIMITIVE_SYSLOG 174 openlog("pppd", LOG_PID); 175#else 176 openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); 177 setlogmask(LOG_UPTO(LOG_INFO)); 178#endif 179 180 if (gethostname(hostname, MAXNAMELEN) < 0 ) { 181 syslog(LOG_ERR, "couldn't get hostname: %m"); 182 die(1); 183 } 184 hostname[MAXNAMELEN-1] = 0; 185 186 uid = getuid(); 187 188 /* 189 * Initialize to the standard option set, then parse, in order, 190 * the system options file, the user's options file, 191 * the tty's options file, and the command line arguments. 192 */ 193 for (i = 0; (protp = protocols[i]) != NULL; ++i) 194 (*protp->init)(0); 195 196 progname = *argv; 197 198 if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) 199 || !options_from_user()) 200 exit(1); 201 scan_args(argc-1, argv+1); /* look for tty name on command line */ 202 if (!options_for_tty() 203 || !parse_args(argc-1, argv+1)) 204 exit(1); 205 206 if (!ppp_available()) { 207 fprintf(stderr, no_ppp_msg); 208 exit(1); 209 } 210 211 /* 212 * Check that the options given are valid and consistent. 213 */ 214 sys_check_options(); 215 auth_check_options(); 216 for (i = 0; (protp = protocols[i]) != NULL; ++i) 217 if (protp->check_options != NULL) 218 (*protp->check_options)(); 219 if (demand && connector == 0) { 220 fprintf(stderr, "%s: connect script required for demand-dialling\n", 221 progname); 222 exit(1); 223 } 224 225 /* 226 * If the user has specified the default device name explicitly, 227 * pretend they hadn't. 228 */ 229 if (!default_device && strcmp(devnam, default_devnam) == 0) 230 default_device = 1; 231 redirect_stderr = !nodetach || default_device; 232 233 234 /* 235 * Initialize system-dependent stuff and magic number package. 236 */ 237 sys_init(); 238 magic_init(); 239 if (debug) 240 setlogmask(LOG_UPTO(LOG_DEBUG)); 241 242 243 /* 244 * Detach ourselves from the terminal, if required, 245 * and identify who is running us. 246 */ 247 if (!default_device && !nodetach && daemon(0, 0) < 0) { 248 perror("Couldn't detach from controlling terminal"); 249 exit(1); 250 } 251 pid = getpid(); 252 p = getlogin(); 253 if (p == NULL) { 254 pw = getpwuid(uid); 255 if (pw != NULL && pw->pw_name != NULL) 256 p = pw->pw_name; 257 else 258 p = "(unknown)"; 259 } 260 syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d", 261 VERSION, PATCHLEVEL, p, uid); 262 263 /* 264 * Compute mask of all interesting signals and install signal handlers 265 * for each. Only one signal handler may be active at a time. Therefore, 266 * all other signals should be masked when any handler is executing. 267 */ 268 sigemptyset(&mask); 269 sigaddset(&mask, SIGHUP); 270 sigaddset(&mask, SIGINT); 271 sigaddset(&mask, SIGTERM); 272 sigaddset(&mask, SIGCHLD); 273 274#define SIGNAL(s, handler) { \ 275 sa.sa_handler = handler; \ 276 if (sigaction(s, &sa, NULL) < 0) { \ 277 syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \ 278 die(1); \ 279 } \ 280 } 281 282 sa.sa_mask = mask; 283 sa.sa_flags = 0; 284 SIGNAL(SIGHUP, hup); /* Hangup */ 285 SIGNAL(SIGINT, term); /* Interrupt */ 286 SIGNAL(SIGTERM, term); /* Terminate */ 287 SIGNAL(SIGCHLD, chld); 288 289 SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */ 290 SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */ 291 292 /* 293 * Install a handler for other signals which would otherwise 294 * cause pppd to exit without cleaning up. 295 */ 296 SIGNAL(SIGABRT, bad_signal); 297 SIGNAL(SIGALRM, bad_signal); 298 SIGNAL(SIGFPE, bad_signal); 299 SIGNAL(SIGILL, bad_signal); 300 SIGNAL(SIGPIPE, bad_signal); 301 SIGNAL(SIGQUIT, bad_signal); 302 SIGNAL(SIGSEGV, bad_signal); 303#ifdef SIGBUS 304 SIGNAL(SIGBUS, bad_signal); 305#endif 306#ifdef SIGEMT 307 SIGNAL(SIGEMT, bad_signal); 308#endif 309#ifdef SIGPOLL 310 SIGNAL(SIGPOLL, bad_signal); 311#endif 312#ifdef SIGPROF 313 SIGNAL(SIGPROF, bad_signal); 314#endif 315#ifdef SIGSYS 316 SIGNAL(SIGSYS, bad_signal); 317#endif 318#ifdef SIGTRAP 319 SIGNAL(SIGTRAP, bad_signal); 320#endif 321#ifdef SIGVTALRM 322 SIGNAL(SIGVTALRM, bad_signal); 323#endif 324#ifdef SIGXCPU 325 SIGNAL(SIGXCPU, bad_signal); 326#endif 327#ifdef SIGXFSZ 328 SIGNAL(SIGXFSZ, bad_signal); 329#endif 330 331 /* 332 * Apparently we can get a SIGPIPE when we call syslog, if 333 * syslogd has died and been restarted. Ignoring it seems 334 * be sufficient. 335 */ 336 signal(SIGPIPE, SIG_IGN); 337 338 /* 339 * If we're doing dial-on-demand, set up the interface now. 340 */ 341 if (demand) { 342 /* 343 * Open the loopback channel and set it up to be the ppp interface. 344 */ 345 open_ppp_loopback(); 346 347 syslog(LOG_INFO, "Using interface ppp%d", ifunit); 348 (void) sprintf(ifname, "ppp%d", ifunit); 349 350 /* write pid to file */ 351 (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); 352 if ((pidfile = fopen(pidfilename, "w")) != NULL) { 353 fprintf(pidfile, "%d\n", pid); 354 (void) fclose(pidfile); 355 } else { 356 syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); 357 pidfilename[0] = 0; 358 } 359 360 /* 361 * Configure the interface and mark it up, etc. 362 */ 363 demand_conf(); 364 } 365 366 for (;;) { 367 368 if (demand) { 369 /* 370 * Don't do anything until we see some activity. 371 */ 372 phase = PHASE_DORMANT; 373 kill_link = 0; 374 demand_unblock(); 375 for (;;) { 376 wait_loop_output(timeleft(&timo)); 377 calltimeout(); 378 if (kill_link) { 379 if (!persist) 380 die(0); 381 kill_link = 0; 382 } 383 if (get_loop_output()) 384 break; 385 reap_kids(); 386 } 387 388 /* 389 * Now we want to bring up the link. 390 */ 391 demand_block(); 392 syslog(LOG_INFO, "Starting link"); 393 } 394 395 /* 396 * Lock the device if we've been asked to. 397 */ 398 if (lockflag && !default_device) { 399 if (lock(devnam) < 0) 400 goto fail; 401 locked = 1; 402 } 403 404 /* 405 * Open the serial device and set it up to be the ppp interface. 406 * If we're dialling out, or we don't want to use the modem lines, 407 * we open it in non-blocking mode, but then we need to clear 408 * the non-blocking I/O bit. 409 */ 410 nonblock = (connector || !modem)? O_NONBLOCK: 0; 411 if ((ttyfd = open(devnam, nonblock | O_RDWR, 0)) < 0) { 412 syslog(LOG_ERR, "Failed to open %s: %m", devnam); 413 goto fail; 414 } 415 if (nonblock) { 416 if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 417 || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) 418 syslog(LOG_WARNING, 419 "Couldn't reset non-blocking mode on device: %m"); 420 } 421 hungup = 0; 422 kill_link = 0; 423 424 /* 425 * Do the equivalent of `mesg n' to stop broadcast messages. 426 */ 427 if (fstat(ttyfd, &statbuf) < 0 428 || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) { 429 syslog(LOG_WARNING, 430 "Couldn't restrict write permissions to %s: %m", devnam); 431 } else 432 tty_mode = statbuf.st_mode; 433 434 /* run connection script */ 435 if (connector && connector[0]) { 436 MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); 437 438 /* set line speed, flow control, etc.; set CLOCAL for now */ 439 set_up_tty(ttyfd, 1); 440 441 /* drop dtr to hang up in case modem is off hook */ 442 if (!default_device && modem) { 443 setdtr(ttyfd, FALSE); 444 sleep(1); 445 setdtr(ttyfd, TRUE); 446 } 447 448 if (device_script(connector, ttyfd, ttyfd) < 0) { 449 syslog(LOG_ERR, "Connect script failed"); 450 setdtr(ttyfd, FALSE); 451 goto fail; 452 } 453 454 syslog(LOG_INFO, "Serial connection established."); 455 sleep(1); /* give it time to set up its terminal */ 456 } 457 458 /* set line speed, flow control, etc.; clear CLOCAL if modem option */ 459 set_up_tty(ttyfd, 0); 460 461 /* run welcome script, if any */ 462 if (welcomer && welcomer[0]) { 463 if (device_script(welcomer, ttyfd, ttyfd) < 0) 464 syslog(LOG_WARNING, "Welcome script failed"); 465 } 466 467 /* set up the serial device as a ppp interface */ 468 establish_ppp(ttyfd); 469 470 if (!demand) { 471 472 syslog(LOG_INFO, "Using interface ppp%d", ifunit); 473 (void) sprintf(ifname, "ppp%d", ifunit); 474 475 /* write pid to file */ 476 (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); 477 if ((pidfile = fopen(pidfilename, "w")) != NULL) { 478 fprintf(pidfile, "%d\n", pid); 479 (void) fclose(pidfile); 480 } else { 481 syslog(LOG_ERR, "Failed to create pid file %s: %m", 482 pidfilename); 483 pidfilename[0] = 0; 484 } 485 } 486 487 /* 488 * Set a timeout to close the connection once the maximum 489 * connect time has expired. 490 */ 491 if (maxconnect > 0) 492 TIMEOUT(connect_time_expired, 0, maxconnect); 493 494 /* 495 * Start opening the connection and wait for 496 * incoming events (reply, timeout, etc.). 497 */ 498 syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); 499 lcp_lowerup(0); 500 lcp_open(0); /* Start protocol */ 501 for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { 502 wait_input(timeleft(&timo)); 503 calltimeout(); 504 get_input(); 505 if (kill_link) { 506 lcp_close(0, "User request"); 507 phase = PHASE_TERMINATE; 508 kill_link = 0; 509 } 510 if (open_ccp_flag) { 511 if (phase == PHASE_NETWORK) { 512 ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ 513 (*ccp_protent.open)(0); 514 } 515 open_ccp_flag = 0; 516 } 517 reap_kids(); /* Don't leave dead kids lying around */ 518 } 519 520 /* 521 * If we may want to bring the link up again, transfer 522 * the ppp unit back to the loopback. Set the 523 * real serial device back to its normal mode of operation. 524 */ 525 clean_check(); 526 if (demand) 527 restore_loop(); 528 disestablish_ppp(ttyfd); 529 530 /* 531 * Run disconnector script, if requested. 532 * XXX we may not be able to do this if the line has hung up! 533 */ 534 if (disconnector && !hungup) { 535 set_up_tty(ttyfd, 1); 536 if (device_script(disconnector, ttyfd, ttyfd) < 0) { 537 syslog(LOG_WARNING, "disconnect script failed"); 538 } else { 539 syslog(LOG_INFO, "Serial link disconnected."); 540 } 541 } 542 543 fail: 544 close_tty(); 545 if (locked) { 546 unlock(); 547 locked = 0; 548 } 549 550 if (!demand) { 551 if (pidfilename[0] != 0 552 && unlink(pidfilename) < 0 && errno != ENOENT) 553 syslog(LOG_WARNING, "unable to delete pid file: %m"); 554 pidfilename[0] = 0; 555 } 556 557 if (!persist) 558 break; 559 560 if (demand) 561 demand_discard(); 562 if (holdoff > 0) { 563 phase = PHASE_HOLDOFF; 564 TIMEOUT(holdoff_end, NULL, holdoff); 565 do { 566 wait_time(timeleft(&timo)); 567 calltimeout(); 568 if (kill_link) { 569 if (!persist) 570 die(0); 571 kill_link = 0; 572 phase = PHASE_DORMANT; /* allow signal to end holdoff */ 573 } 574 reap_kids(); 575 } while (phase == PHASE_HOLDOFF); 576 } 577 } 578 579 die(0); 580} 581 582/* 583 * holdoff_end - called via a timeout when the holdoff period ends. 584 */ 585static void 586holdoff_end(arg) 587 void *arg; 588{ 589 phase = PHASE_DORMANT; 590} 591 592/* 593 * get_input - called when incoming data is available. 594 */ 595static void 596get_input() 597{ 598 int len, i; 599 u_char *p; 600 u_short protocol; 601 struct protent *protp; 602 603 p = inpacket_buf; /* point to beginning of packet buffer */ 604 605 len = read_packet(inpacket_buf); 606 if (len < 0) 607 return; 608 609 if (len == 0) { 610 syslog(LOG_NOTICE, "Modem hangup"); 611 hungup = 1; 612 lcp_lowerdown(0); /* serial link is no longer available */ 613 link_terminated(0); 614 return; 615 } 616 617 if (debug /*&& (debugflags & DBG_INPACKET)*/) 618 log_packet(p, len, "rcvd "); 619 620 if (len < PPP_HDRLEN) { 621 MAINDEBUG((LOG_INFO, "io(): Received short packet.")); 622 return; 623 } 624 625 p += 2; /* Skip address and control */ 626 GETSHORT(protocol, p); 627 len -= PPP_HDRLEN; 628 629 /* 630 * Toss all non-LCP packets unless LCP is OPEN. 631 */ 632 if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) { 633 MAINDEBUG((LOG_INFO, 634 "io(): Received non-LCP packet when LCP not open.")); 635 return; 636 } 637 638 /* 639 * Upcall the proper protocol input routine. 640 */ 641 for (i = 0; (protp = protocols[i]) != NULL; ++i) { 642 if (protp->protocol == protocol && protp->enabled_flag) { 643 (*protp->input)(0, p, len); 644 return; 645 } 646 if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag 647 && protp->datainput != NULL) { 648 (*protp->datainput)(0, p, len); 649 return; 650 } 651 } 652 653 if (debug) 654 syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol); 655 lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); 656} 657 658 659/* 660 * quit - Clean up state and exit (with an error indication). 661 */ 662void 663quit() 664{ 665 die(1); 666} 667 668/* 669 * die - like quit, except we can specify an exit status. 670 */ 671void 672die(status) 673 int status; 674{ 675 cleanup(); 676 syslog(LOG_INFO, "Exit."); 677 exit(status); 678} 679 680/* 681 * connect_time_expired - log a message and close the connection. 682 */ 683static void 684connect_time_expired(arg) 685 caddr_t arg; 686{ 687 syslog(LOG_INFO, "Connect time expired"); 688 689 phase = PHASE_TERMINATE; 690 lcp_close(0, "Connect time expired"); /* Close connection */ 691} 692 693/* 694 * cleanup - restore anything which needs to be restored before we exit 695 */ 696/* ARGSUSED */ 697static void 698cleanup() 699{ 700 sys_cleanup(); 701 702 if (ttyfd >= 0) 703 close_tty(); 704 705 if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 706 syslog(LOG_WARNING, "unable to delete pid file: %m"); 707 pidfilename[0] = 0; 708 709 if (locked) 710 unlock(); 711} 712 713/* 714 * close_tty - restore the terminal device and close it. 715 */ 716static void 717close_tty() 718{ 719 disestablish_ppp(ttyfd); 720 721 /* drop dtr to hang up */ 722 if (modem) { 723 setdtr(ttyfd, FALSE); 724 /* 725 * This sleep is in case the serial port has CLOCAL set by default, 726 * and consequently will reassert DTR when we close the device. 727 */ 728 sleep(1); 729 } 730 731 restore_tty(ttyfd); 732 733 if (tty_mode != (mode_t) -1) 734 chmod(devnam, tty_mode); 735 736 close(ttyfd); 737 ttyfd = -1; 738} 739 740 741struct callout { 742 struct timeval c_time; /* time at which to call routine */ 743 caddr_t c_arg; /* argument to routine */ 744 void (*c_func)(); /* routine */ 745 struct callout *c_next; 746}; 747 748static struct callout *callout = NULL; /* Callout list */ 749static struct timeval timenow; /* Current time */ 750 751/* 752 * timeout - Schedule a timeout. 753 * 754 * Note that this timeout takes the number of seconds, NOT hz (as in 755 * the kernel). 756 */ 757void 758timeout(func, arg, time) 759 void (*func)(); 760 caddr_t arg; 761 int time; 762{ 763 struct callout *newp, *p, **pp; 764 765 MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.", 766 (long) func, (long) arg, time)); 767 768 /* 769 * Allocate timeout. 770 */ 771 if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) { 772 syslog(LOG_ERR, "Out of memory in timeout()!"); 773 die(1); 774 } 775 newp->c_arg = arg; 776 newp->c_func = func; 777 gettimeofday(&timenow, NULL); 778 newp->c_time.tv_sec = timenow.tv_sec + time; 779 newp->c_time.tv_usec = timenow.tv_usec; 780 781 /* 782 * Find correct place and link it in. 783 */ 784 for (pp = &callout; (p = *pp); pp = &p->c_next) 785 if (newp->c_time.tv_sec < p->c_time.tv_sec 786 || (newp->c_time.tv_sec == p->c_time.tv_sec 787 && newp->c_time.tv_usec < p->c_time.tv_sec)) 788 break; 789 newp->c_next = p; 790 *pp = newp; 791} 792 793 794/* 795 * untimeout - Unschedule a timeout. 796 */ 797void 798untimeout(func, arg) 799 void (*func)(); 800 caddr_t arg; 801{ 802 struct callout **copp, *freep; 803 804 MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); 805 806 /* 807 * Find first matching timeout and remove it from the list. 808 */ 809 for (copp = &callout; (freep = *copp); copp = &freep->c_next) 810 if (freep->c_func == func && freep->c_arg == arg) { 811 *copp = freep->c_next; 812 (void) free((char *) freep); 813 break; 814 } 815} 816 817 818/* 819 * calltimeout - Call any timeout routines which are now due. 820 */ 821static void 822calltimeout() 823{ 824 struct callout *p; 825 826 while (callout != NULL) { 827 p = callout; 828 829 if (gettimeofday(&timenow, NULL) < 0) { 830 syslog(LOG_ERR, "Failed to get time of day: %m"); 831 die(1); 832 } 833 if (!(p->c_time.tv_sec < timenow.tv_sec 834 || (p->c_time.tv_sec == timenow.tv_sec 835 && p->c_time.tv_usec <= timenow.tv_usec))) 836 break; /* no, it's not time yet */ 837 838 callout = p->c_next; 839 (*p->c_func)(p->c_arg); 840 841 free((char *) p); 842 } 843} 844 845 846/* 847 * timeleft - return the length of time until the next timeout is due. 848 */ 849static struct timeval * 850timeleft(tvp) 851 struct timeval *tvp; 852{ 853 if (callout == NULL) 854 return NULL; 855 856 gettimeofday(&timenow, NULL); 857 tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec; 858 tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec; 859 if (tvp->tv_usec < 0) { 860 tvp->tv_usec += 1000000; 861 tvp->tv_sec -= 1; 862 } 863 if (tvp->tv_sec < 0) 864 tvp->tv_sec = tvp->tv_usec = 0; 865 866 return tvp; 867} 868 869 870/* 871 * hup - Catch SIGHUP signal. 872 * 873 * Indicates that the physical layer has been disconnected. 874 * We don't rely on this indication; if the user has sent this 875 * signal, we just take the link down. 876 */ 877static void 878hup(sig) 879 int sig; 880{ 881 syslog(LOG_INFO, "Hangup (SIGHUP)"); 882 kill_link = 1; 883} 884 885 886/* 887 * term - Catch SIGTERM signal and SIGINT signal (^C/del). 888 * 889 * Indicates that we should initiate a graceful disconnect and exit. 890 */ 891/*ARGSUSED*/ 892static void 893term(sig) 894 int sig; 895{ 896 syslog(LOG_INFO, "Terminating on signal %d.", sig); 897 persist = 0; /* don't try to restart */ 898 kill_link = 1; 899} 900 901 902/* 903 * chld - Catch SIGCHLD signal. 904 * Calls reap_kids to get status for any dead kids. 905 */ 906static void 907chld(sig) 908 int sig; 909{ 910 reap_kids(); 911} 912 913 914/* 915 * toggle_debug - Catch SIGUSR1 signal. 916 * 917 * Toggle debug flag. 918 */ 919/*ARGSUSED*/ 920static void 921toggle_debug(sig) 922 int sig; 923{ 924 debug = !debug; 925 if (debug) { 926 setlogmask(LOG_UPTO(LOG_DEBUG)); 927 } else { 928 setlogmask(LOG_UPTO(LOG_WARNING)); 929 } 930} 931 932 933/* 934 * open_ccp - Catch SIGUSR2 signal. 935 * 936 * Try to (re)negotiate compression. 937 */ 938/*ARGSUSED*/ 939static void 940open_ccp(sig) 941 int sig; 942{ 943 open_ccp_flag = 1; 944} 945 946 947/* 948 * bad_signal - We've caught a fatal signal. Clean up state and exit. 949 */ 950static void 951bad_signal(sig) 952 int sig; 953{ 954 syslog(LOG_ERR, "Fatal signal %d", sig); 955 die(1); 956} 957 958 959/* 960 * device_script - run a program to connect or disconnect the 961 * serial device. 962 */ 963static int 964device_script(program, in, out) 965 char *program; 966 int in, out; 967{ 968 int pid; 969 int status; 970 int errfd; 971 972 pid = fork(); 973 974 if (pid < 0) { 975 syslog(LOG_ERR, "Failed to create child process: %m"); 976 die(1); 977 } 978 979 if (pid == 0) { 980 sys_close(); 981 closelog(); 982 if (in == out) { 983 if (in != 0) { 984 dup2(in, 0); 985 close(in); 986 } 987 dup2(0, 1); 988 } else { 989 if (out == 0) 990 out = dup(out); 991 if (in != 0) { 992 dup2(in, 0); 993 close(in); 994 } 995 if (out != 1) { 996 dup2(out, 1); 997 close(out); 998 } 999 } 1000 if (redirect_stderr) { 1001 close(2); 1002 errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); 1003 if (errfd >= 0 && errfd != 2) { 1004 dup2(errfd, 2); 1005 close(errfd); 1006 } 1007 } 1008 setuid(getuid()); 1009 setgid(getgid()); 1010 execl("/bin/sh", "sh", "-c", program, (char *)0); 1011 syslog(LOG_ERR, "could not exec /bin/sh: %m"); 1012 _exit(99); 1013 /* NOTREACHED */ 1014 } 1015 1016 while (waitpid(pid, &status, 0) < 0) { 1017 if (errno == EINTR) 1018 continue; 1019 syslog(LOG_ERR, "error waiting for (dis)connection process: %m"); 1020 die(1); 1021 } 1022 1023 return (status == 0 ? 0 : -1); 1024} 1025 1026 1027/* 1028 * run-program - execute a program with given arguments, 1029 * but don't wait for it. 1030 * If the program can't be executed, logs an error unless 1031 * must_exist is 0 and the program file doesn't exist. 1032 */ 1033int 1034run_program(prog, args, must_exist) 1035 char *prog; 1036 char **args; 1037 int must_exist; 1038{ 1039 int pid; 1040 char *nullenv[1]; 1041 1042 1043 pid = fork(); 1044 if (pid == -1) { 1045 syslog(LOG_ERR, "Failed to create child process for %s: %m", prog); 1046 return -1; 1047 } 1048 if (pid == 0) { 1049 int new_fd; 1050 1051 /* Leave the current location */ 1052 (void) setsid(); /* No controlling tty. */ 1053 (void) umask (S_IRWXG|S_IRWXO); 1054 (void) chdir ("/"); /* no current directory. */ 1055 setuid(geteuid()); 1056 setgid(getegid()); 1057 1058 /* Ensure that nothing of our device environment is inherited. */ 1059 sys_close(); 1060 closelog(); 1061 close (0); 1062 close (1); 1063 close (2); 1064 close (ttyfd); /* tty interface to the ppp device */ 1065 1066 /* Don't pass handles to the PPP device, even by accident. */ 1067 new_fd = open (_PATH_DEVNULL, O_RDWR); 1068 if (new_fd >= 0) { 1069 if (new_fd != 0) { 1070 dup2 (new_fd, 0); /* stdin <- /dev/null */ 1071 close (new_fd); 1072 } 1073 dup2 (0, 1); /* stdout -> /dev/null */ 1074 dup2 (0, 2); /* stderr -> /dev/null */ 1075 } 1076 1077#ifdef BSD 1078 /* Force the priority back to zero if pppd is running higher. */ 1079 if (setpriority (PRIO_PROCESS, 0, 0) < 0) 1080 syslog (LOG_WARNING, "can't reset priority to 0: %m"); 1081#endif 1082 1083 /* SysV recommends a second fork at this point. */ 1084 1085 /* run the program; give it a null environment */ 1086 nullenv[0] = NULL; 1087 execve(prog, args, nullenv); 1088 if (must_exist || errno != ENOENT) 1089 syslog(LOG_WARNING, "Can't execute %s: %m", prog); 1090 _exit(-1); 1091 } 1092 MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid)); 1093 ++n_children; 1094 return 0; 1095} 1096 1097 1098/* 1099 * reap_kids - get status from any dead child processes, 1100 * and log a message for abnormal terminations. 1101 */ 1102static void 1103reap_kids() 1104{ 1105 int pid, status; 1106 1107 if (n_children == 0) 1108 return; 1109 if ((pid = waitpid(-1, &status, WNOHANG)) == -1) { 1110 if (errno != ECHILD) 1111 syslog(LOG_ERR, "Error waiting for child process: %m"); 1112 return; 1113 } 1114 if (pid > 0) { 1115 --n_children; 1116 if (WIFSIGNALED(status)) { 1117 syslog(LOG_WARNING, "Child process %d terminated with signal %d", 1118 pid, WTERMSIG(status)); 1119 } 1120 } 1121} 1122 1123 1124/* 1125 * log_packet - format a packet and log it. 1126 */ 1127 1128char line[256]; /* line to be logged accumulated here */ 1129char *linep; 1130 1131void 1132log_packet(p, len, prefix) 1133 u_char *p; 1134 int len; 1135 char *prefix; 1136{ 1137 strcpy(line, prefix); 1138 linep = line + strlen(line); 1139 format_packet(p, len, pr_log, NULL); 1140 if (linep != line) 1141 syslog(LOG_DEBUG, "%s", line); 1142} 1143 1144/* 1145 * format_packet - make a readable representation of a packet, 1146 * calling `printer(arg, format, ...)' to output it. 1147 */ 1148void 1149format_packet(p, len, printer, arg) 1150 u_char *p; 1151 int len; 1152 void (*printer) __P((void *, char *, ...)); 1153 void *arg; 1154{ 1155 int i, n; 1156 u_short proto; 1157 u_char x; 1158 struct protent *protp; 1159 1160 if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { 1161 p += 2; 1162 GETSHORT(proto, p); 1163 len -= PPP_HDRLEN; 1164 for (i = 0; (protp = protocols[i]) != NULL; ++i) 1165 if (proto == protp->protocol) 1166 break; 1167 if (protp != NULL) { 1168 printer(arg, "[%s", protp->name); 1169 n = (*protp->printpkt)(p, len, printer, arg); 1170 printer(arg, "]"); 1171 p += n; 1172 len -= n; 1173 } else { 1174 printer(arg, "[proto=0x%x]", proto); 1175 } 1176 } 1177 1178 for (; len > 0; --len) { 1179 GETCHAR(x, p); 1180 printer(arg, " %.2x", x); 1181 } 1182} 1183 1184static void 1185pr_log __V((void *arg, char *fmt, ...)) 1186{ 1187 int n; 1188 va_list pvar; 1189 char buf[256]; 1190 1191#if __STDC__ 1192 va_start(pvar, fmt); 1193#else 1194 void *arg; 1195 char *fmt; 1196 va_start(pvar); 1197 arg = va_arg(pvar, void *); 1198 fmt = va_arg(pvar, char *); 1199#endif 1200 1201 vsprintf(buf, fmt, pvar); 1202 va_end(pvar); 1203 1204 n = strlen(buf); 1205 if (linep + n + 1 > line + sizeof(line)) { 1206 syslog(LOG_DEBUG, "%s", line); 1207 linep = line; 1208 } 1209 strcpy(linep, buf); 1210 linep += n; 1211} 1212 1213/* 1214 * print_string - print a readable representation of a string using 1215 * printer. 1216 */ 1217void 1218print_string(p, len, printer, arg) 1219 char *p; 1220 int len; 1221 void (*printer) __P((void *, char *, ...)); 1222 void *arg; 1223{ 1224 int c; 1225 1226 printer(arg, "\""); 1227 for (; len > 0; --len) { 1228 c = *p++; 1229 if (' ' <= c && c <= '~') { 1230 if (c == '\\' || c == '"') 1231 printer(arg, "\\"); 1232 printer(arg, "%c", c); 1233 } else { 1234 switch (c) { 1235 case '\n': 1236 printer(arg, "\\n"); 1237 break; 1238 case '\r': 1239 printer(arg, "\\r"); 1240 break; 1241 case '\t': 1242 printer(arg, "\\t"); 1243 break; 1244 default: 1245 printer(arg, "\\%.3o", c); 1246 } 1247 } 1248 } 1249 1250 printer(arg, "\""); 1251} 1252 1253/* 1254 * novm - log an error message saying we ran out of memory, and die. 1255 */ 1256void 1257novm(msg) 1258 char *msg; 1259{ 1260 syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg); 1261 die(1); 1262} 1263 1264/* 1265 * fmtmsg - format a message into a buffer. Like sprintf except we 1266 * also specify the length of the output buffer, and we handle 1267 * %r (recursive format), %m (error message) and %I (IP address) formats. 1268 * Doesn't do floating-point formats. 1269 * Returns the number of chars put into buf. 1270 */ 1271int 1272fmtmsg __V((char *buf, int buflen, char *fmt, ...)) 1273{ 1274 va_list args; 1275 int n; 1276 1277#if __STDC__ 1278 va_start(args, fmt); 1279#else 1280 char *buf; 1281 int buflen; 1282 char *fmt; 1283 va_start(args); 1284 buf = va_arg(args, char *); 1285 buflen = va_arg(args, int); 1286 fmt = va_arg(args, char *); 1287#endif 1288 n = vfmtmsg(buf, buflen, fmt, args); 1289 va_end(args); 1290 return n; 1291} 1292 1293/* 1294 * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args. 1295 */ 1296#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) 1297 1298int 1299vfmtmsg(char *buf, int buflen, char *fmt, va_list args) 1300{ 1301 int c, i, n; 1302 int width, prec, fillch; 1303 int base, len, neg, quoted; 1304 unsigned long val; 1305 char *str, *f, *buf0; 1306 unsigned char *p; 1307 va_list a; 1308 char num[32]; 1309 time_t t; 1310 static char hexchars[16] = "0123456789abcdef"; 1311 1312 buf0 = buf; 1313 --buflen; 1314 while (buflen > 0) { 1315 for (f = fmt; *f != '%' && *f != 0; ++f) 1316 ; 1317 if (f > fmt) { 1318 len = f - fmt; 1319 if (len > buflen) 1320 len = buflen; 1321 memcpy(buf, fmt, len); 1322 buf += len; 1323 buflen -= len; 1324 fmt = f; 1325 } 1326 if (*fmt == 0) 1327 break; 1328 c = *++fmt; 1329 width = prec = 0; 1330 fillch = ' '; 1331 if (c == '0') { 1332 fillch = '0'; 1333 c = *++fmt; 1334 } 1335 if (c == '*') { 1336 width = va_arg(args, int); 1337 c = *++fmt; 1338 } else { 1339 while (isdigit(c)) { 1340 width = width * 10 + c - '0'; 1341 c = *++fmt; 1342 } 1343 } 1344 if (c == '.') { 1345 c = *++fmt; 1346 if (c == '*') { 1347 prec = va_arg(args, int); 1348 c = *++fmt; 1349 } else { 1350 while (isdigit(c)) { 1351 prec = prec * 10 + c - '0'; 1352 c = *++fmt; 1353 } 1354 } 1355 } 1356 str = 0; 1357 base = 0; 1358 neg = 0; 1359 ++fmt; 1360 switch (c) { 1361 case 'd': 1362 i = va_arg(args, int); 1363 if (i < 0) { 1364 neg = 1; 1365 val = -i; 1366 } else 1367 val = i; 1368 base = 10; 1369 break; 1370 case 'o': 1371 val = va_arg(args, unsigned int); 1372 base = 8; 1373 break; 1374 case 'x': 1375 val = va_arg(args, unsigned int); 1376 base = 16; 1377 break; 1378 case 'p': 1379 val = (unsigned long) va_arg(args, void *); 1380 base = 16; 1381 neg = 2; 1382 break; 1383 case 's': 1384 str = va_arg(args, char *); 1385 break; 1386 case 'c': 1387 num[0] = va_arg(args, int); 1388 num[1] = 0; 1389 str = num; 1390 break; 1391 case 'm': 1392 str = strerror(errno); 1393 break; 1394 case 'I': 1395 str = ip_ntoa(va_arg(args, u_int32_t)); 1396 break; 1397 case 'r': 1398 f = va_arg(args, char *); 1399 a = va_arg(args, va_list); 1400 n = vfmtmsg(buf, buflen + 1, f, a); 1401 buf += n; 1402 buflen -= n; 1403 continue; 1404 case 't': 1405 time(&t); 1406 str = ctime(&t); 1407 str += 4; /* chop off the day name */ 1408 str[15] = 0; /* chop off year and newline */ 1409 break; 1410 case 'v': /* "visible" string */ 1411 case 'q': /* quoted string */ 1412 quoted = c == 'q'; 1413 p = va_arg(args, unsigned char *); 1414 if (fillch == '0' && prec > 0) { 1415 n = prec; 1416 } else { 1417 n = strlen((char *)p); 1418 if (prec > 0 && prec < n) 1419 n = prec; 1420 } 1421 while (n > 0 && buflen > 0) { 1422 c = *p++; 1423 --n; 1424 if (!quoted && c >= 0x80) { 1425 OUTCHAR('M'); 1426 OUTCHAR('-'); 1427 c -= 0x80; 1428 } 1429 if (quoted && (c == '"' || c == '\\')) 1430 OUTCHAR('\\'); 1431 if (c < 0x20 || 0x7f <= c && c < 0xa0) { 1432 if (quoted) { 1433 OUTCHAR('\\'); 1434 switch (c) { 1435 case '\t': OUTCHAR('t'); break; 1436 case '\n': OUTCHAR('n'); break; 1437 case '\b': OUTCHAR('b'); break; 1438 case '\f': OUTCHAR('f'); break; 1439 default: 1440 OUTCHAR('x'); 1441 OUTCHAR(hexchars[c >> 4]); 1442 OUTCHAR(hexchars[c & 0xf]); 1443 } 1444 } else { 1445 if (c == '\t') 1446 OUTCHAR(c); 1447 else { 1448 OUTCHAR('^'); 1449 OUTCHAR(c ^ 0x40); 1450 } 1451 } 1452 } else 1453 OUTCHAR(c); 1454 } 1455 continue; 1456 default: 1457 *buf++ = '%'; 1458 if (c != '%') 1459 --fmt; /* so %z outputs %z etc. */ 1460 --buflen; 1461 continue; 1462 } 1463 if (base != 0) { 1464 str = num + sizeof(num); 1465 *--str = 0; 1466 while (str > num + neg) { 1467 *--str = hexchars[val % base]; 1468 val = val / base; 1469 if (--prec <= 0 && val == 0) 1470 break; 1471 } 1472 switch (neg) { 1473 case 1: 1474 *--str = '-'; 1475 break; 1476 case 2: 1477 *--str = 'x'; 1478 *--str = '0'; 1479 break; 1480 } 1481 len = num + sizeof(num) - 1 - str; 1482 } else { 1483 len = strlen(str); 1484 if (prec > 0 && len > prec) 1485 len = prec; 1486 } 1487 if (width > 0) { 1488 if (width > buflen) 1489 width = buflen; 1490 if ((n = width - len) > 0) { 1491 buflen -= n; 1492 for (; n > 0; --n) 1493 *buf++ = fillch; 1494 } 1495 } 1496 if (len > buflen) 1497 len = buflen; 1498 memcpy(buf, str, len); 1499 buf += len; 1500 buflen -= len; 1501 } 1502 *buf = 0; 1503 return buf - buf0; 1504} 1505 1506