Home | History | Annotate | Download | only in pppd
      1 /*
      2  * tty.c - code for handling serial ports in pppd.
      3  *
      4  * Copyright (C) 2000-2004 Paul Mackerras. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  *
     13  * 2. The name(s) of the authors of this software must not be used to
     14  *    endorse or promote products derived from this software without
     15  *    prior written permission.
     16  *
     17  * 3. Redistributions of any form whatsoever must retain the following
     18  *    acknowledgment:
     19  *    "This product includes software developed by Paul Mackerras
     20  *     <paulus (at) samba.org>".
     21  *
     22  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
     23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     24  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
     25  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     26  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     27  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     28  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     29  *
     30  * Portions derived from main.c, which is:
     31  *
     32  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
     33  *
     34  * Redistribution and use in source and binary forms, with or without
     35  * modification, are permitted provided that the following conditions
     36  * are met:
     37  *
     38  * 1. Redistributions of source code must retain the above copyright
     39  *    notice, this list of conditions and the following disclaimer.
     40  *
     41  * 2. Redistributions in binary form must reproduce the above copyright
     42  *    notice, this list of conditions and the following disclaimer in
     43  *    the documentation and/or other materials provided with the
     44  *    distribution.
     45  *
     46  * 3. The name "Carnegie Mellon University" must not be used to
     47  *    endorse or promote products derived from this software without
     48  *    prior written permission. For permission or any legal
     49  *    details, please contact
     50  *      Office of Technology Transfer
     51  *      Carnegie Mellon University
     52  *      5000 Forbes Avenue
     53  *      Pittsburgh, PA  15213-3890
     54  *      (412) 268-4387, fax: (412) 268-7395
     55  *      tech-transfer (at) andrew.cmu.edu
     56  *
     57  * 4. Redistributions of any form whatsoever must retain the following
     58  *    acknowledgment:
     59  *    "This product includes software developed by Computing Services
     60  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
     61  *
     62  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
     63  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     64  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
     65  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     66  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
     67  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     68  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     69  */
     70 
     71 #define RCSID	"$Id: tty.c,v 1.22 2004/11/13 12:07:29 paulus Exp $"
     72 
     73 #include <stdio.h>
     74 #include <ctype.h>
     75 #include <stdlib.h>
     76 #include <string.h>
     77 #include <unistd.h>
     78 #include <signal.h>
     79 #include <errno.h>
     80 #include <fcntl.h>
     81 #include <syslog.h>
     82 #include <netdb.h>
     83 #include <utmp.h>
     84 #include <pwd.h>
     85 #include <setjmp.h>
     86 #include <sys/param.h>
     87 #include <sys/types.h>
     88 #include <sys/wait.h>
     89 #include <sys/time.h>
     90 #include <sys/resource.h>
     91 #include <sys/stat.h>
     92 #include <sys/socket.h>
     93 #include <netinet/in.h>
     94 #include <arpa/inet.h>
     95 
     96 #include "pppd.h"
     97 #include "fsm.h"
     98 #include "lcp.h"
     99 
    100 void tty_process_extra_options __P((void));
    101 void tty_check_options __P((void));
    102 int  connect_tty __P((void));
    103 void disconnect_tty __P((void));
    104 void tty_close_fds __P((void));
    105 void cleanup_tty __P((void));
    106 void tty_do_send_config __P((int, u_int32_t, int, int));
    107 
    108 static int setdevname __P((char *, char **, int));
    109 static int setspeed __P((char *, char **, int));
    110 static int setxonxoff __P((char **));
    111 static int setescape __P((char **));
    112 static void printescape __P((option_t *, void (*)(void *, char *,...),void *));
    113 static void finish_tty __P((void));
    114 static int start_charshunt __P((int, int));
    115 static void stop_charshunt __P((void *, int));
    116 static void charshunt_done __P((void *));
    117 static void charshunt __P((int, int, char *));
    118 static int record_write __P((FILE *, int code, u_char *buf, int nb,
    119 			     struct timeval *));
    120 static int open_socket __P((char *));
    121 static void maybe_relock __P((void *, int));
    122 
    123 static int pty_master;		/* fd for master side of pty */
    124 static int pty_slave;		/* fd for slave side of pty */
    125 static int real_ttyfd;		/* fd for actual serial port (not pty) */
    126 static int ttyfd;		/* Serial port file descriptor */
    127 static char speed_str[16];	/* Serial port speed as string */
    128 
    129 mode_t tty_mode = (mode_t)-1;	/* Original access permissions to tty */
    130 int baud_rate;			/* Actual bits/second for serial device */
    131 char *callback_script;		/* script for doing callback */
    132 int charshunt_pid;		/* Process ID for charshunt */
    133 int locked;			/* lock() has succeeded */
    134 struct stat devstat;		/* result of stat() on devnam */
    135 
    136 /* option variables */
    137 int	crtscts = 0;		/* Use hardware flow control */
    138 bool	modem = 1;		/* Use modem control lines */
    139 int	inspeed = 0;		/* Input/Output speed requested */
    140 bool	lockflag = 0;		/* Create lock file to lock the serial dev */
    141 char	*initializer = NULL;	/* Script to initialize physical link */
    142 char	*connect_script = NULL;	/* Script to establish physical link */
    143 char	*disconnect_script = NULL; /* Script to disestablish physical link */
    144 char	*welcomer = NULL;	/* Script to run after phys link estab. */
    145 char	*ptycommand = NULL;	/* Command to run on other side of pty */
    146 bool	notty = 0;		/* Stdin/out is not a tty */
    147 char	*record_file = NULL;	/* File to record chars sent/received */
    148 int	max_data_rate;		/* max bytes/sec through charshunt */
    149 bool	sync_serial = 0;	/* Device is synchronous serial device */
    150 char	*pty_socket = NULL;	/* Socket to connect to pty */
    151 int	using_pty = 0;		/* we're allocating a pty as the device */
    152 
    153 extern uid_t uid;
    154 extern int kill_link;
    155 extern int asked_to_quit;
    156 extern int got_sigterm;
    157 
    158 /* XXX */
    159 extern int privopen;		/* don't lock, open device as root */
    160 
    161 u_int32_t xmit_accm[8];		/* extended transmit ACCM */
    162 
    163 /* option descriptors */
    164 option_t tty_options[] = {
    165     /* device name must be first, or change connect_tty() below! */
    166     { "device name", o_wild, (void *) &setdevname,
    167       "Serial port device name",
    168       OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG  | OPT_A2STRVAL | OPT_STATIC,
    169       devnam},
    170 
    171     { "tty speed", o_wild, (void *) &setspeed,
    172       "Baud rate for serial port",
    173       OPT_PRIO | OPT_NOARG | OPT_A2STRVAL | OPT_STATIC, speed_str },
    174 
    175     { "lock", o_bool, &lockflag,
    176       "Lock serial device with UUCP-style lock file", OPT_PRIO | 1 },
    177     { "nolock", o_bool, &lockflag,
    178       "Don't lock serial device", OPT_PRIOSUB | OPT_PRIV },
    179 
    180     { "init", o_string, &initializer,
    181       "A program to initialize the device", OPT_PRIO | OPT_PRIVFIX },
    182 
    183     { "connect", o_string, &connect_script,
    184       "A program to set up a connection", OPT_PRIO | OPT_PRIVFIX },
    185 
    186     { "disconnect", o_string, &disconnect_script,
    187       "Program to disconnect serial device", OPT_PRIO | OPT_PRIVFIX },
    188 
    189     { "welcome", o_string, &welcomer,
    190       "Script to welcome client", OPT_PRIO | OPT_PRIVFIX },
    191 
    192     { "pty", o_string, &ptycommand,
    193       "Script to run on pseudo-tty master side",
    194       OPT_PRIO | OPT_PRIVFIX | OPT_DEVNAM },
    195 
    196     { "notty", o_bool, &notty,
    197       "Input/output is not a tty", OPT_DEVNAM | 1 },
    198 
    199     { "socket", o_string, &pty_socket,
    200       "Send and receive over socket, arg is host:port",
    201       OPT_PRIO | OPT_DEVNAM },
    202 
    203     { "record", o_string, &record_file,
    204       "Record characters sent/received to file", OPT_PRIO },
    205 
    206     { "crtscts", o_int, &crtscts,
    207       "Set hardware (RTS/CTS) flow control",
    208       OPT_PRIO | OPT_NOARG | OPT_VAL(1) },
    209     { "cdtrcts", o_int, &crtscts,
    210       "Set alternate hardware (DTR/CTS) flow control",
    211       OPT_PRIOSUB | OPT_NOARG | OPT_VAL(2) },
    212     { "nocrtscts", o_int, &crtscts,
    213       "Disable hardware flow control",
    214       OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) },
    215     { "-crtscts", o_int, &crtscts,
    216       "Disable hardware flow control",
    217       OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) },
    218     { "nocdtrcts", o_int, &crtscts,
    219       "Disable hardware flow control",
    220       OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) },
    221     { "xonxoff", o_special_noarg, (void *)setxonxoff,
    222       "Set software (XON/XOFF) flow control", OPT_PRIOSUB },
    223 
    224     { "modem", o_bool, &modem,
    225       "Use modem control lines", OPT_PRIO | 1 },
    226     { "local", o_bool, &modem,
    227       "Don't use modem control lines", OPT_PRIOSUB | 0 },
    228 
    229     { "sync", o_bool, &sync_serial,
    230       "Use synchronous HDLC serial encoding", 1 },
    231 
    232     { "datarate", o_int, &max_data_rate,
    233       "Maximum data rate in bytes/sec (with pty, notty or record option)",
    234       OPT_PRIO },
    235 
    236     { "escape", o_special, (void *)setescape,
    237       "List of character codes to escape on transmission",
    238       OPT_A2PRINTER, (void *)printescape },
    239 
    240     { NULL }
    241 };
    242 
    243 
    244 struct channel tty_channel = {
    245 	tty_options,
    246 	&tty_process_extra_options,
    247 	&tty_check_options,
    248 	&connect_tty,
    249 	&disconnect_tty,
    250 	&tty_establish_ppp,
    251 	&tty_disestablish_ppp,
    252 	&tty_do_send_config,
    253 	&tty_recv_config,
    254 	&cleanup_tty,
    255 	&tty_close_fds
    256 };
    257 
    258 /*
    259  * setspeed - Set the serial port baud rate.
    260  * If doit is 0, the call is to check whether this option is
    261  * potentially a speed value.
    262  */
    263 static int
    264 setspeed(arg, argv, doit)
    265     char *arg;
    266     char **argv;
    267     int doit;
    268 {
    269 	char *ptr;
    270 	int spd;
    271 
    272 	spd = strtol(arg, &ptr, 0);
    273 	if (ptr == arg || *ptr != 0 || spd == 0)
    274 		return 0;
    275 	if (doit) {
    276 		inspeed = spd;
    277 		slprintf(speed_str, sizeof(speed_str), "%d", spd);
    278 	}
    279 	return 1;
    280 }
    281 
    282 
    283 /*
    284  * setdevname - Set the device name.
    285  * If doit is 0, the call is to check whether this option is
    286  * potentially a device name.
    287  */
    288 static int
    289 setdevname(cp, argv, doit)
    290     char *cp;
    291     char **argv;
    292     int doit;
    293 {
    294 	struct stat statbuf;
    295 	char dev[MAXPATHLEN];
    296 
    297 	if (*cp == 0)
    298 		return 0;
    299 
    300 	if (*cp != '/') {
    301 		strlcpy(dev, "/dev/", sizeof(dev));
    302 		strlcat(dev, cp, sizeof(dev));
    303 		cp = dev;
    304 	}
    305 
    306 	/*
    307 	 * Check if there is a character device by this name.
    308 	 */
    309 	if (stat(cp, &statbuf) < 0) {
    310 		if (!doit)
    311 			return errno != ENOENT;
    312 		option_error("Couldn't stat %s: %m", cp);
    313 		return 0;
    314 	}
    315 	if (!S_ISCHR(statbuf.st_mode)) {
    316 		if (doit)
    317 			option_error("%s is not a character device", cp);
    318 		return 0;
    319 	}
    320 
    321 	if (doit) {
    322 		strlcpy(devnam, cp, sizeof(devnam));
    323 		devstat = statbuf;
    324 		default_device = 0;
    325 	}
    326 
    327 	return 1;
    328 }
    329 
    330 static int
    331 setxonxoff(argv)
    332     char **argv;
    333 {
    334 	lcp_wantoptions[0].asyncmap |= 0x000A0000;	/* escape ^S and ^Q */
    335 	lcp_wantoptions[0].neg_asyncmap = 1;
    336 
    337 	crtscts = -2;
    338 	return 1;
    339 }
    340 
    341 /*
    342  * setescape - add chars to the set we escape on transmission.
    343  */
    344 static int
    345 setescape(argv)
    346     char **argv;
    347 {
    348     int n, ret;
    349     char *p, *endp;
    350 
    351     p = *argv;
    352     ret = 1;
    353     while (*p) {
    354 	n = strtol(p, &endp, 16);
    355 	if (p == endp) {
    356 	    option_error("escape parameter contains invalid hex number '%s'",
    357 			 p);
    358 	    return 0;
    359 	}
    360 	p = endp;
    361 	if (n < 0 || n == 0x5E || n > 0xFF) {
    362 	    option_error("can't escape character 0x%x", n);
    363 	    ret = 0;
    364 	} else
    365 	    xmit_accm[n >> 5] |= 1 << (n & 0x1F);
    366 	while (*p == ',' || *p == ' ')
    367 	    ++p;
    368     }
    369     lcp_allowoptions[0].asyncmap = xmit_accm[0];
    370     return ret;
    371 }
    372 
    373 static void
    374 printescape(opt, printer, arg)
    375     option_t *opt;
    376     void (*printer) __P((void *, char *, ...));
    377     void *arg;
    378 {
    379 	int n;
    380 	int first = 1;
    381 
    382 	for (n = 0; n < 256; ++n) {
    383 		if (n == 0x7d)
    384 			n += 2;		/* skip 7d, 7e */
    385 		if (xmit_accm[n >> 5] & (1 << (n & 0x1f))) {
    386 			if (!first)
    387 				printer(arg, ",");
    388 			else
    389 				first = 0;
    390 			printer(arg, "%x", n);
    391 		}
    392 	}
    393 	if (first)
    394 		printer(arg, "oops # nothing escaped");
    395 }
    396 
    397 /*
    398  * tty_init - do various tty-related initializations.
    399  */
    400 void tty_init()
    401 {
    402     add_notifier(&pidchange, maybe_relock, 0);
    403     the_channel = &tty_channel;
    404     xmit_accm[3] = 0x60000000;
    405 }
    406 
    407 /*
    408  * tty_process_extra_options - work out which tty device we are using
    409  * and read its options file.
    410  */
    411 void tty_process_extra_options()
    412 {
    413 	using_pty = notty || ptycommand != NULL || pty_socket != NULL;
    414 	if (using_pty)
    415 		return;
    416 	if (default_device) {
    417 		char *p;
    418 		if (!isatty(0) || (p = ttyname(0)) == NULL) {
    419 			option_error("no device specified and stdin is not a tty");
    420 			exit(EXIT_OPTION_ERROR);
    421 		}
    422 		strlcpy(devnam, p, sizeof(devnam));
    423 		if (stat(devnam, &devstat) < 0)
    424 			fatal("Couldn't stat default device %s: %m", devnam);
    425 	}
    426 
    427 
    428 	/*
    429 	 * Parse the tty options file.
    430 	 * The per-tty options file should not change
    431 	 * ptycommand, pty_socket, notty or devnam.
    432 	 * options_for_tty doesn't override options set on the command line,
    433 	 * except for some privileged options.
    434 	 */
    435 	if (!options_for_tty())
    436 		exit(EXIT_OPTION_ERROR);
    437 }
    438 
    439 /*
    440  * tty_check_options - do consistency checks on the options we were given.
    441  */
    442 void
    443 tty_check_options()
    444 {
    445 	struct stat statbuf;
    446 	int fdflags;
    447 
    448 	if (demand && notty) {
    449 		option_error("demand-dialling is incompatible with notty");
    450 		exit(EXIT_OPTION_ERROR);
    451 	}
    452 	if (demand && connect_script == 0 && ptycommand == NULL
    453 	    && pty_socket == NULL) {
    454 		option_error("connect script is required for demand-dialling\n");
    455 		exit(EXIT_OPTION_ERROR);
    456 	}
    457 	/* default holdoff to 0 if no connect script has been given */
    458 	if (connect_script == 0 && !holdoff_specified)
    459 		holdoff = 0;
    460 
    461 	if (using_pty) {
    462 		if (!default_device) {
    463 			option_error("%s option precludes specifying device name",
    464 				     pty_socket? "socket": notty? "notty": "pty");
    465 			exit(EXIT_OPTION_ERROR);
    466 		}
    467 		if (ptycommand != NULL && notty) {
    468 			option_error("pty option is incompatible with notty option");
    469 			exit(EXIT_OPTION_ERROR);
    470 		}
    471 		if (pty_socket != NULL && (ptycommand != NULL || notty)) {
    472 			option_error("socket option is incompatible with pty and notty");
    473 			exit(EXIT_OPTION_ERROR);
    474 		}
    475 		default_device = notty;
    476 		lockflag = 0;
    477 		modem = 0;
    478 		if (notty && log_to_fd <= 1)
    479 			log_to_fd = -1;
    480 	} else {
    481 		/*
    482 		 * If the user has specified a device which is the same as
    483 		 * the one on stdin, pretend they didn't specify any.
    484 		 * If the device is already open read/write on stdin,
    485 		 * we assume we don't need to lock it, and we can open it
    486 		 * as root.
    487 		 */
    488 		if (fstat(0, &statbuf) >= 0 && S_ISCHR(statbuf.st_mode)
    489 		    && statbuf.st_rdev == devstat.st_rdev) {
    490 			default_device = 1;
    491 			fdflags = fcntl(0, F_GETFL);
    492 			if (fdflags != -1 && (fdflags & O_ACCMODE) == O_RDWR)
    493 				privopen = 1;
    494 		}
    495 	}
    496 	if (default_device)
    497 		nodetach = 1;
    498 
    499 	/*
    500 	 * Don't send log messages to the serial port, it tends to
    501 	 * confuse the peer. :-)
    502 	 */
    503 	if (log_to_fd >= 0 && fstat(log_to_fd, &statbuf) >= 0
    504 	    && S_ISCHR(statbuf.st_mode) && statbuf.st_rdev == devstat.st_rdev)
    505 		log_to_fd = -1;
    506 }
    507 
    508 /*
    509  * connect_tty - get the serial port ready to start doing PPP.
    510  * That is, open the serial port, set its speed and mode, and run
    511  * the connector and/or welcomer.
    512  */
    513 int connect_tty()
    514 {
    515 	char *connector;
    516 	int fdflags;
    517 #ifndef __linux__
    518 	struct stat statbuf;
    519 #endif
    520 	char numbuf[16];
    521 
    522 	/*
    523 	 * Get a pty master/slave pair if the pty, notty, socket,
    524 	 * or record options were specified.
    525 	 */
    526 	strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
    527 	pty_master = -1;
    528 	pty_slave = -1;
    529 	real_ttyfd = -1;
    530 	if (using_pty || record_file != NULL) {
    531 		if (!get_pty(&pty_master, &pty_slave, ppp_devnam, uid)) {
    532 			error("Couldn't allocate pseudo-tty");
    533 			status = EXIT_FATAL_ERROR;
    534 			return -1;
    535 		}
    536 		set_up_tty(pty_slave, 1);
    537 	}
    538 
    539 	/*
    540 	 * Lock the device if we've been asked to.
    541 	 */
    542 	status = EXIT_LOCK_FAILED;
    543 	if (lockflag && !privopen) {
    544 		if (lock(devnam) < 0)
    545 			goto errret;
    546 		locked = 1;
    547 	}
    548 
    549 	/*
    550 	 * Open the serial device and set it up to be the ppp interface.
    551 	 * First we open it in non-blocking mode so we can set the
    552 	 * various termios flags appropriately.  If we aren't dialling
    553 	 * out and we want to use the modem lines, we reopen it later
    554 	 * in order to wait for the carrier detect signal from the modem.
    555 	 */
    556 	hungup = 0;
    557 	got_sigterm = 0;
    558 	connector = doing_callback? callback_script: connect_script;
    559 	if (devnam[0] != 0) {
    560 		for (;;) {
    561 			/* If the user specified the device name, become the
    562 			   user before opening it. */
    563 			int err, prio;
    564 
    565 			prio = privopen? OPRIO_ROOT: tty_options[0].priority;
    566 			if (prio < OPRIO_ROOT)
    567 				seteuid(uid);
    568 			real_ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
    569 			err = errno;
    570 			if (prio < OPRIO_ROOT)
    571 				seteuid(0);
    572 			if (real_ttyfd >= 0)
    573 				break;
    574 			errno = err;
    575 			if (err != EINTR) {
    576 				error("Failed to open %s: %m", devnam);
    577 				status = EXIT_OPEN_FAILED;
    578 			}
    579 			if (!persist || err != EINTR)
    580 				goto errret;
    581 		}
    582 		ttyfd = real_ttyfd;
    583 		if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
    584 		    || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
    585 			warn("Couldn't reset non-blocking mode on device: %m");
    586 
    587 #ifndef __linux__
    588 		/*
    589 		 * Linux 2.4 and above blocks normal writes to the tty
    590 		 * when it is in PPP line discipline, so this isn't needed.
    591 		 */
    592 		/*
    593 		 * Do the equivalent of `mesg n' to stop broadcast messages.
    594 		 */
    595 		if (fstat(ttyfd, &statbuf) < 0
    596 		    || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
    597 			warn("Couldn't restrict write permissions to %s: %m", devnam);
    598 		} else
    599 			tty_mode = statbuf.st_mode;
    600 #endif /* __linux__ */
    601 
    602 		/*
    603 		 * Set line speed, flow control, etc.
    604 		 * If we have a non-null connection or initializer script,
    605 		 * on most systems we set CLOCAL for now so that we can talk
    606 		 * to the modem before carrier comes up.  But this has the
    607 		 * side effect that we might miss it if CD drops before we
    608 		 * get to clear CLOCAL below.  On systems where we can talk
    609 		 * successfully to the modem with CLOCAL clear and CD down,
    610 		 * we could clear CLOCAL at this point.
    611 		 */
    612 		set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
    613 				   || initializer != NULL));
    614 	}
    615 
    616 	/*
    617 	 * If the pty, socket, notty and/or record option was specified,
    618 	 * start up the character shunt now.
    619 	 */
    620 	status = EXIT_PTYCMD_FAILED;
    621 	if (ptycommand != NULL) {
    622 		if (record_file != NULL) {
    623 			int ipipe[2], opipe[2], ok;
    624 
    625 			if (pipe(ipipe) < 0 || pipe(opipe) < 0)
    626 				fatal("Couldn't create pipes for record option: %m");
    627 
    628 			/* don't leak these to the ptycommand */
    629 			(void) fcntl(ipipe[0], F_SETFD, FD_CLOEXEC);
    630 			(void) fcntl(opipe[1], F_SETFD, FD_CLOEXEC);
    631 
    632 			ok = device_script(ptycommand, opipe[0], ipipe[1], 1) == 0
    633 				&& start_charshunt(ipipe[0], opipe[1]);
    634 			close(ipipe[0]);
    635 			close(ipipe[1]);
    636 			close(opipe[0]);
    637 			close(opipe[1]);
    638 			if (!ok)
    639 				goto errret;
    640 		} else {
    641 			if (device_script(ptycommand, pty_master, pty_master, 1) < 0)
    642 				goto errret;
    643 		}
    644 	} else if (pty_socket != NULL) {
    645 		int fd = open_socket(pty_socket);
    646 		if (fd < 0)
    647 			goto errret;
    648 		if (!start_charshunt(fd, fd))
    649 			goto errret;
    650 		close(fd);
    651 	} else if (notty) {
    652 		if (!start_charshunt(0, 1))
    653 			goto errret;
    654 		dup2(fd_devnull, 0);
    655 		dup2(fd_devnull, 1);
    656 		if (log_to_fd == 1)
    657 			log_to_fd = -1;
    658 		if (log_to_fd != 2)
    659 			dup2(fd_devnull, 2);
    660 	} else if (record_file != NULL) {
    661 		int fd = dup(ttyfd);
    662 		if (!start_charshunt(fd, fd))
    663 			goto errret;
    664 	}
    665 
    666 	if (using_pty || record_file != NULL) {
    667 		ttyfd = pty_slave;
    668 		close(pty_master);
    669 		pty_master = -1;
    670 	}
    671 
    672 	/* run connection script */
    673 	if ((connector && connector[0]) || initializer) {
    674 		if (real_ttyfd != -1) {
    675 			/* XXX do this if doing_callback == CALLBACK_DIALIN? */
    676 			if (!default_device && modem) {
    677 				setdtr(real_ttyfd, 0);	/* in case modem is off hook */
    678 				sleep(1);
    679 				setdtr(real_ttyfd, 1);
    680 			}
    681 		}
    682 
    683 		if (initializer && initializer[0]) {
    684 			if (device_script(initializer, ttyfd, ttyfd, 0) < 0) {
    685 				error("Initializer script failed");
    686 				status = EXIT_INIT_FAILED;
    687 				goto errret;
    688 			}
    689 			if (got_sigterm) {
    690 				disconnect_tty();
    691 				goto errret;
    692 			}
    693 			info("Serial port initialized.");
    694 		}
    695 
    696 		if (connector && connector[0]) {
    697 			if (device_script(connector, ttyfd, ttyfd, 0) < 0) {
    698 				error("Connect script failed");
    699 				status = EXIT_CONNECT_FAILED;
    700 				goto errret;
    701 			}
    702 			if (got_sigterm) {
    703 				disconnect_tty();
    704 				goto errret;
    705 			}
    706 			info("Serial connection established.");
    707 		}
    708 
    709 		/* set line speed, flow control, etc.;
    710 		   clear CLOCAL if modem option */
    711 		if (real_ttyfd != -1)
    712 			set_up_tty(real_ttyfd, 0);
    713 
    714 		if (doing_callback == CALLBACK_DIALIN)
    715 			connector = NULL;
    716 	}
    717 
    718 	/* reopen tty if necessary to wait for carrier */
    719 	if (connector == NULL && modem && devnam[0] != 0) {
    720 		int i;
    721 		for (;;) {
    722 			if ((i = open(devnam, O_RDWR)) >= 0)
    723 				break;
    724 			if (errno != EINTR) {
    725 				error("Failed to reopen %s: %m", devnam);
    726 				status = EXIT_OPEN_FAILED;
    727 			}
    728 			if (!persist || errno != EINTR || hungup || got_sigterm)
    729 				goto errret;
    730 		}
    731 		close(i);
    732 	}
    733 
    734 	slprintf(numbuf, sizeof(numbuf), "%d", baud_rate);
    735 	script_setenv("SPEED", numbuf, 0);
    736 
    737 	/* run welcome script, if any */
    738 	if (welcomer && welcomer[0]) {
    739 		if (device_script(welcomer, ttyfd, ttyfd, 0) < 0)
    740 			warn("Welcome script failed");
    741 	}
    742 
    743 	/*
    744 	 * If we are initiating this connection, wait for a short
    745 	 * time for something from the peer.  This can avoid bouncing
    746 	 * our packets off his tty before he has it set up.
    747 	 */
    748 	if (connector != NULL || ptycommand != NULL || pty_socket != NULL)
    749 		listen_time = connect_delay;
    750 
    751 	return ttyfd;
    752 
    753  errret:
    754 	if (pty_master >= 0) {
    755 		close(pty_master);
    756 		pty_master = -1;
    757 	}
    758 	if (pty_slave >= 0) {
    759 		close(pty_slave);
    760 		pty_slave = -1;
    761 	}
    762 	if (real_ttyfd >= 0) {
    763 		close(real_ttyfd);
    764 		real_ttyfd = -1;
    765 	}
    766 	ttyfd = -1;
    767 	if (got_sigterm)
    768 		asked_to_quit = 1;
    769 	return -1;
    770 }
    771 
    772 
    773 void disconnect_tty()
    774 {
    775 	if (disconnect_script == NULL || hungup)
    776 		return;
    777 	if (real_ttyfd >= 0)
    778 		set_up_tty(real_ttyfd, 1);
    779 	if (device_script(disconnect_script, ttyfd, ttyfd, 0) < 0) {
    780 		warn("disconnect script failed");
    781 	} else {
    782 		info("Serial link disconnected.");
    783 	}
    784 }
    785 
    786 void tty_close_fds()
    787 {
    788 	if (pty_slave >= 0)
    789 		close(pty_slave);
    790 	if (real_ttyfd >= 0) {
    791 		close(real_ttyfd);
    792 		real_ttyfd = -1;
    793 	}
    794 	/* N.B. ttyfd will == either pty_slave or real_ttyfd */
    795 }
    796 
    797 void cleanup_tty()
    798 {
    799 	if (real_ttyfd >= 0)
    800 		finish_tty();
    801 	tty_close_fds();
    802 	if (locked) {
    803 		unlock();
    804 		locked = 0;
    805 	}
    806 }
    807 
    808 /*
    809  * tty_do_send_config - set transmit-side PPP configuration.
    810  * We set the extended transmit ACCM here as well.
    811  */
    812 void
    813 tty_do_send_config(mtu, accm, pcomp, accomp)
    814     int mtu;
    815     u_int32_t accm;
    816     int pcomp, accomp;
    817 {
    818 	tty_set_xaccm(xmit_accm);
    819 	tty_send_config(mtu, accm, pcomp, accomp);
    820 }
    821 
    822 /*
    823  * finish_tty - restore the terminal device to its original settings
    824  */
    825 static void
    826 finish_tty()
    827 {
    828 	/* drop dtr to hang up */
    829 	if (!default_device && modem) {
    830 		setdtr(real_ttyfd, 0);
    831 		/*
    832 		 * This sleep is in case the serial port has CLOCAL set by default,
    833 		 * and consequently will reassert DTR when we close the device.
    834 		 */
    835 		sleep(1);
    836 	}
    837 
    838 	restore_tty(real_ttyfd);
    839 
    840 #ifndef __linux__
    841 	if (tty_mode != (mode_t) -1) {
    842 		if (fchmod(real_ttyfd, tty_mode) != 0)
    843 			error("Couldn't restore tty permissions");
    844 	}
    845 #endif /* __linux__ */
    846 
    847 	close(real_ttyfd);
    848 	real_ttyfd = -1;
    849 }
    850 
    851 /*
    852  * maybe_relock - our PID has changed, maybe update the lock file.
    853  */
    854 static void
    855 maybe_relock(arg, pid)
    856     void *arg;
    857     int pid;
    858 {
    859     if (locked)
    860 	relock(pid);
    861 }
    862 
    863 /*
    864  * open_socket - establish a stream socket connection to the nominated
    865  * host and port.
    866  */
    867 static int
    868 open_socket(dest)
    869     char *dest;
    870 {
    871     char *sep, *endp = NULL;
    872     int sock, port = -1;
    873     u_int32_t host;
    874     struct hostent *hent;
    875     struct sockaddr_in sad;
    876 
    877     /* parse host:port and resolve host to an IP address */
    878     sep = strchr(dest, ':');
    879     if (sep != NULL)
    880 	port = strtol(sep+1, &endp, 10);
    881     if (port < 0 || endp == sep+1 || sep == dest) {
    882 	error("Can't parse host:port for socket destination");
    883 	return -1;
    884     }
    885     *sep = 0;
    886     host = inet_addr(dest);
    887     if (host == (u_int32_t) -1) {
    888 	hent = gethostbyname(dest);
    889 	if (hent == NULL) {
    890 	    error("%s: unknown host in socket option", dest);
    891 	    *sep = ':';
    892 	    return -1;
    893 	}
    894 	host = *(u_int32_t *)(hent->h_addr_list[0]);
    895     }
    896     *sep = ':';
    897 
    898     /* get a socket and connect it to the other end */
    899     sock = socket(PF_INET, SOCK_STREAM, 0);
    900     if (sock < 0) {
    901 	error("Can't create socket: %m");
    902 	return -1;
    903     }
    904     memset(&sad, 0, sizeof(sad));
    905     sad.sin_family = AF_INET;
    906     sad.sin_port = htons(port);
    907     sad.sin_addr.s_addr = host;
    908     if (connect(sock, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
    909 	error("Can't connect to %s: %m", dest);
    910 	close(sock);
    911 	return -1;
    912     }
    913 
    914     return sock;
    915 }
    916 
    917 
    918 /*
    919  * start_charshunt - create a child process to run the character shunt.
    920  */
    921 static int
    922 start_charshunt(ifd, ofd)
    923     int ifd, ofd;
    924 {
    925     int cpid;
    926 
    927     cpid = safe_fork(ifd, ofd, (log_to_fd >= 0? log_to_fd: 2));
    928     if (cpid == -1) {
    929 	error("Can't fork process for character shunt: %m");
    930 	return 0;
    931     }
    932     if (cpid == 0) {
    933 	/* child */
    934 	reopen_log();
    935 	if (!nodetach)
    936 	    log_to_fd = -1;
    937 	else if (log_to_fd >= 0)
    938 	    log_to_fd = 2;
    939 	setgid(getgid());
    940 	setuid(uid);
    941 	if (getuid() != uid)
    942 	    fatal("setuid failed");
    943 	charshunt(0, 1, record_file);
    944 	exit(0);
    945     }
    946     charshunt_pid = cpid;
    947     add_notifier(&sigreceived, stop_charshunt, 0);
    948     record_child(cpid, "pppd (charshunt)", charshunt_done, NULL);
    949     return 1;
    950 }
    951 
    952 static void
    953 charshunt_done(arg)
    954     void *arg;
    955 {
    956 	charshunt_pid = 0;
    957 }
    958 
    959 static void
    960 stop_charshunt(arg, sig)
    961     void *arg;
    962     int sig;
    963 {
    964 	if (charshunt_pid)
    965 		kill(charshunt_pid, (sig == SIGINT? sig: SIGTERM));
    966 }
    967 
    968 /*
    969  * charshunt - the character shunt, which passes characters between
    970  * the pty master side and the serial port (or stdin/stdout).
    971  * This runs as the user (not as root).
    972  * (We assume ofd >= ifd which is true the way this gets called. :-).
    973  */
    974 static void
    975 charshunt(ifd, ofd, record_file)
    976     int ifd, ofd;
    977     char *record_file;
    978 {
    979     int n, nfds;
    980     fd_set ready, writey;
    981     u_char *ibufp, *obufp;
    982     int nibuf, nobuf;
    983     int flags;
    984     int pty_readable, stdin_readable;
    985     struct timeval lasttime;
    986     FILE *recordf = NULL;
    987     int ilevel, olevel, max_level;
    988     struct timeval levelt, tout, *top;
    989     extern u_char inpacket_buf[];
    990 
    991     /*
    992      * Reset signal handlers.
    993      */
    994     signal(SIGHUP, SIG_IGN);		/* Hangup */
    995     signal(SIGINT, SIG_DFL);		/* Interrupt */
    996     signal(SIGTERM, SIG_DFL);		/* Terminate */
    997     signal(SIGCHLD, SIG_DFL);
    998     signal(SIGUSR1, SIG_DFL);
    999     signal(SIGUSR2, SIG_DFL);
   1000     signal(SIGABRT, SIG_DFL);
   1001     signal(SIGALRM, SIG_DFL);
   1002     signal(SIGFPE, SIG_DFL);
   1003     signal(SIGILL, SIG_DFL);
   1004     signal(SIGPIPE, SIG_DFL);
   1005     signal(SIGQUIT, SIG_DFL);
   1006     signal(SIGSEGV, SIG_DFL);
   1007 #ifdef SIGBUS
   1008     signal(SIGBUS, SIG_DFL);
   1009 #endif
   1010 #ifdef SIGEMT
   1011     signal(SIGEMT, SIG_DFL);
   1012 #endif
   1013 #ifdef SIGPOLL
   1014     signal(SIGPOLL, SIG_DFL);
   1015 #endif
   1016 #ifdef SIGPROF
   1017     signal(SIGPROF, SIG_DFL);
   1018 #endif
   1019 #ifdef SIGSYS
   1020     signal(SIGSYS, SIG_DFL);
   1021 #endif
   1022 #ifdef SIGTRAP
   1023     signal(SIGTRAP, SIG_DFL);
   1024 #endif
   1025 #ifdef SIGVTALRM
   1026     signal(SIGVTALRM, SIG_DFL);
   1027 #endif
   1028 #ifdef SIGXCPU
   1029     signal(SIGXCPU, SIG_DFL);
   1030 #endif
   1031 #ifdef SIGXFSZ
   1032     signal(SIGXFSZ, SIG_DFL);
   1033 #endif
   1034 
   1035     /*
   1036      * Check that the fds won't overrun the fd_sets
   1037      */
   1038     if (ifd >= FD_SETSIZE || ofd >= FD_SETSIZE || pty_master >= FD_SETSIZE)
   1039 	fatal("internal error: file descriptor too large (%d, %d, %d)",
   1040 	      ifd, ofd, pty_master);
   1041 
   1042     /*
   1043      * Open the record file if required.
   1044      */
   1045     if (record_file != NULL) {
   1046 	recordf = fopen(record_file, "a");
   1047 	if (recordf == NULL)
   1048 	    error("Couldn't create record file %s: %m", record_file);
   1049     }
   1050 
   1051     /* set all the fds to non-blocking mode */
   1052     flags = fcntl(pty_master, F_GETFL);
   1053     if (flags == -1
   1054 	|| fcntl(pty_master, F_SETFL, flags | O_NONBLOCK) == -1)
   1055 	warn("couldn't set pty master to nonblock: %m");
   1056     flags = fcntl(ifd, F_GETFL);
   1057     if (flags == -1
   1058 	|| fcntl(ifd, F_SETFL, flags | O_NONBLOCK) == -1)
   1059 	warn("couldn't set %s to nonblock: %m", (ifd==0? "stdin": "tty"));
   1060     if (ofd != ifd) {
   1061 	flags = fcntl(ofd, F_GETFL);
   1062 	if (flags == -1
   1063 	    || fcntl(ofd, F_SETFL, flags | O_NONBLOCK) == -1)
   1064 	    warn("couldn't set stdout to nonblock: %m");
   1065     }
   1066 
   1067     nibuf = nobuf = 0;
   1068     ibufp = obufp = NULL;
   1069     pty_readable = stdin_readable = 1;
   1070 
   1071     ilevel = olevel = 0;
   1072     gettimeofday(&levelt, NULL);
   1073     if (max_data_rate) {
   1074 	max_level = max_data_rate / 10;
   1075 	if (max_level < 100)
   1076 	    max_level = 100;
   1077     } else
   1078 	max_level = PPP_MRU + PPP_HDRLEN + 1;
   1079 
   1080     nfds = (ofd > pty_master? ofd: pty_master) + 1;
   1081     if (recordf != NULL) {
   1082 	gettimeofday(&lasttime, NULL);
   1083 	putc(7, recordf);	/* put start marker */
   1084 	putc(lasttime.tv_sec >> 24, recordf);
   1085 	putc(lasttime.tv_sec >> 16, recordf);
   1086 	putc(lasttime.tv_sec >> 8, recordf);
   1087 	putc(lasttime.tv_sec, recordf);
   1088 	lasttime.tv_usec = 0;
   1089     }
   1090 
   1091     while (nibuf != 0 || nobuf != 0 || pty_readable || stdin_readable) {
   1092 	top = 0;
   1093 	tout.tv_sec = 0;
   1094 	tout.tv_usec = 10000;
   1095 	FD_ZERO(&ready);
   1096 	FD_ZERO(&writey);
   1097 	if (nibuf != 0) {
   1098 	    if (ilevel >= max_level)
   1099 		top = &tout;
   1100 	    else
   1101 		FD_SET(pty_master, &writey);
   1102 	} else if (stdin_readable)
   1103 	    FD_SET(ifd, &ready);
   1104 	if (nobuf != 0) {
   1105 	    if (olevel >= max_level)
   1106 		top = &tout;
   1107 	    else
   1108 		FD_SET(ofd, &writey);
   1109 	} else if (pty_readable)
   1110 	    FD_SET(pty_master, &ready);
   1111 	if (select(nfds, &ready, &writey, NULL, top) < 0) {
   1112 	    if (errno != EINTR)
   1113 		fatal("select");
   1114 	    continue;
   1115 	}
   1116 	if (max_data_rate) {
   1117 	    double dt;
   1118 	    int nbt;
   1119 	    struct timeval now;
   1120 
   1121 	    gettimeofday(&now, NULL);
   1122 	    dt = (now.tv_sec - levelt.tv_sec
   1123 		  + (now.tv_usec - levelt.tv_usec) / 1e6);
   1124 	    nbt = (int)(dt * max_data_rate);
   1125 	    ilevel = (nbt < 0 || nbt > ilevel)? 0: ilevel - nbt;
   1126 	    olevel = (nbt < 0 || nbt > olevel)? 0: olevel - nbt;
   1127 	    levelt = now;
   1128 	} else
   1129 	    ilevel = olevel = 0;
   1130 	if (FD_ISSET(ifd, &ready)) {
   1131 	    ibufp = inpacket_buf;
   1132 	    nibuf = read(ifd, ibufp, PPP_MRU + PPP_HDRLEN);
   1133 	    if (nibuf < 0 && errno == EIO)
   1134 		nibuf = 0;
   1135 	    if (nibuf < 0) {
   1136 		if (!(errno == EINTR || errno == EAGAIN)) {
   1137 		    error("Error reading standard input: %m");
   1138 		    break;
   1139 		}
   1140 		nibuf = 0;
   1141 	    } else if (nibuf == 0) {
   1142 		/* end of file from stdin */
   1143 		stdin_readable = 0;
   1144 		if (recordf)
   1145 		    if (!record_write(recordf, 4, NULL, 0, &lasttime))
   1146 			recordf = NULL;
   1147 	    } else {
   1148 		FD_SET(pty_master, &writey);
   1149 		if (recordf)
   1150 		    if (!record_write(recordf, 2, ibufp, nibuf, &lasttime))
   1151 			recordf = NULL;
   1152 	    }
   1153 	}
   1154 	if (FD_ISSET(pty_master, &ready)) {
   1155 	    obufp = outpacket_buf;
   1156 	    nobuf = read(pty_master, obufp, PPP_MRU + PPP_HDRLEN);
   1157 	    if (nobuf < 0 && errno == EIO)
   1158 		nobuf = 0;
   1159 	    if (nobuf < 0) {
   1160 		if (!(errno == EINTR || errno == EAGAIN)) {
   1161 		    error("Error reading pseudo-tty master: %m");
   1162 		    break;
   1163 		}
   1164 		nobuf = 0;
   1165 	    } else if (nobuf == 0) {
   1166 		/* end of file from the pty - slave side has closed */
   1167 		pty_readable = 0;
   1168 		stdin_readable = 0;	/* pty is not writable now */
   1169 		nibuf = 0;
   1170 		close(ofd);
   1171 		if (recordf)
   1172 		    if (!record_write(recordf, 3, NULL, 0, &lasttime))
   1173 			recordf = NULL;
   1174 	    } else {
   1175 		FD_SET(ofd, &writey);
   1176 		if (recordf)
   1177 		    if (!record_write(recordf, 1, obufp, nobuf, &lasttime))
   1178 			recordf = NULL;
   1179 	    }
   1180 	} else if (!stdin_readable)
   1181 	    pty_readable = 0;
   1182 	if (FD_ISSET(ofd, &writey)) {
   1183 	    n = nobuf;
   1184 	    if (olevel + n > max_level)
   1185 		n = max_level - olevel;
   1186 	    n = write(ofd, obufp, n);
   1187 	    if (n < 0) {
   1188 		if (errno == EIO) {
   1189 		    pty_readable = 0;
   1190 		    nobuf = 0;
   1191 		} else if (errno != EAGAIN && errno != EINTR) {
   1192 		    error("Error writing standard output: %m");
   1193 		    break;
   1194 		}
   1195 	    } else {
   1196 		obufp += n;
   1197 		nobuf -= n;
   1198 		olevel += n;
   1199 	    }
   1200 	}
   1201 	if (FD_ISSET(pty_master, &writey)) {
   1202 	    n = nibuf;
   1203 	    if (ilevel + n > max_level)
   1204 		n = max_level - ilevel;
   1205 	    n = write(pty_master, ibufp, n);
   1206 	    if (n < 0) {
   1207 		if (errno == EIO) {
   1208 		    stdin_readable = 0;
   1209 		    nibuf = 0;
   1210 		} else if (errno != EAGAIN && errno != EINTR) {
   1211 		    error("Error writing pseudo-tty master: %m");
   1212 		    break;
   1213 		}
   1214 	    } else {
   1215 		ibufp += n;
   1216 		nibuf -= n;
   1217 		ilevel += n;
   1218 	    }
   1219 	}
   1220     }
   1221     exit(0);
   1222 }
   1223 
   1224 static int
   1225 record_write(f, code, buf, nb, tp)
   1226     FILE *f;
   1227     int code;
   1228     u_char *buf;
   1229     int nb;
   1230     struct timeval *tp;
   1231 {
   1232     struct timeval now;
   1233     int diff;
   1234 
   1235     gettimeofday(&now, NULL);
   1236     now.tv_usec /= 100000;	/* actually 1/10 s, not usec now */
   1237     diff = (now.tv_sec - tp->tv_sec) * 10 + (now.tv_usec - tp->tv_usec);
   1238     if (diff > 0) {
   1239 	if (diff > 255) {
   1240 	    putc(5, f);
   1241 	    putc(diff >> 24, f);
   1242 	    putc(diff >> 16, f);
   1243 	    putc(diff >> 8, f);
   1244 	    putc(diff, f);
   1245 	} else {
   1246 	    putc(6, f);
   1247 	    putc(diff, f);
   1248 	}
   1249 	*tp = now;
   1250     }
   1251     putc(code, f);
   1252     if (buf != NULL) {
   1253 	putc(nb >> 8, f);
   1254 	putc(nb, f);
   1255 	fwrite(buf, nb, 1, f);
   1256     }
   1257     fflush(f);
   1258     if (ferror(f)) {
   1259 	error("Error writing record file: %m");
   1260 	return 0;
   1261     }
   1262     return 1;
   1263 }
   1264