From: Paul Mackerras Date: Mon, 13 Mar 2000 23:39:58 +0000 (+0000) Subject: add socket and datarate options X-Git-Tag: ppp-2.4.7~563 X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=deb02ea79306c28c58538561bde38da17bd2bd4d add socket and datarate options fix n_children bug --- diff --git a/pppd/main.c b/pppd/main.c index 954fc2b..2e0604b 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: main.c,v 1.89 2000/01/18 19:49:52 masputra Exp $" +#define RCSID "$Id: main.c,v 1.90 2000/03/13 23:39:58 paulus Exp $" #include #include @@ -40,6 +40,7 @@ #include #include #include +#include #include "pppd.h" #include "magic.h" @@ -171,6 +172,7 @@ static void holdoff_end __P((void *)); static int device_script __P((char *, int, int, int)); static int reap_kids __P((int waitfor)); static void record_child __P((int, char *, void (*) (void *), void *)); +static int open_socket __P((char *)); static int start_charshunt __P((int, int)); static void charshunt_done __P((void *)); static void charshunt __P((int, int, char *)); @@ -295,7 +297,7 @@ main(argc, argv) /* * Work out the device name, if it hasn't already been specified. */ - using_pty = notty || ptycommand != NULL; + using_pty = notty || ptycommand != NULL || pty_socket != NULL; if (!using_pty && default_device) { char *p; if (!isatty(0) || (p = ttyname(0)) == NULL) { @@ -310,7 +312,7 @@ main(argc, argv) /* * Parse the tty options file and the command line. * The per-tty options file should not change - * ptycommand, notty or devnam. + * ptycommand, pty_socket, notty or devnam. */ devnam_fixed = 1; if (!using_pty) { @@ -363,6 +365,10 @@ main(argc, argv) option_error("pty option is incompatible with notty option"); exit(EXIT_OPTION_ERROR); } + if (pty_socket != NULL && (ptycommand != NULL || notty)) { + option_error("socket option is incompatible with pty and notty"); + exit(EXIT_OPTION_ERROR); + } default_device = notty; lockflag = 0; modem = 0; @@ -576,13 +582,13 @@ main(argc, argv) new_phase(PHASE_SERIALCONN); /* - * Get a pty master/slave pair if the pty, notty, or record - * options were specified. + * Get a pty master/slave pair if the pty, notty, socket, + * or record options were specified. */ strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); pty_master = -1; pty_slave = -1; - if (ptycommand != NULL || notty || record_file != NULL) { + if (using_pty || record_file != NULL) { if (!get_pty(&pty_master, &pty_slave, ppp_devnam, uid)) { error("Couldn't allocate pseudo-tty"); status = EXIT_FATAL_ERROR; @@ -661,7 +667,7 @@ main(argc, argv) } /* - * If the notty and/or record option was specified, + * If the pty, socket, notty and/or record option was specified, * start up the character shunt now. */ status = EXIT_PTYCMD_FAILED; @@ -686,6 +692,12 @@ main(argc, argv) close(pty_master); pty_master = -1; } + } else if (pty_socket != NULL) { + int fd = open_socket(pty_socket); + if (fd < 0) + goto fail; + if (!start_charshunt(fd, fd)) + goto fail; } else if (notty) { if (!start_charshunt(0, 1)) goto fail; @@ -1826,9 +1838,9 @@ reap_kids(waitfor) return 0; while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1 && pid != 0) { - --n_children; for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) { if (chp->pid == pid) { + --n_children; *prevp = chp->next; break; } @@ -1938,6 +1950,60 @@ script_unsetenv(var) } } +/* + * open_socket - establish a stream socket connection to the nominated + * host and port. + */ +static int +open_socket(dest) + char *dest; +{ + char *sep, *endp = NULL; + int sock, port = -1; + u_int32_t host; + struct hostent *hent; + struct sockaddr_in sad; + + /* parse host:port and resolve host to an IP address */ + sep = strchr(dest, ':'); + if (sep != NULL) + port = strtol(sep+1, &endp, 10); + if (port < 0 || endp == sep+1 || sep == dest) { + error("Can't parse host:port for socket destination"); + return -1; + } + *sep = 0; + host = inet_addr(dest); + if (host == (u_int32_t) -1) { + hent = gethostbyname(dest); + if (hent == NULL) { + error("%s: unknown host in socket option", dest); + *sep = ':'; + return -1; + } + host = *(u_int32_t *)(hent->h_addr_list[0]); + } + *sep = ':'; + + /* get a socket and connect it to the other end */ + sock = socket(PF_INET, SOCK_STREAM, 0); + if (sock < 0) { + error("Can't create socket: %m"); + return -1; + } + memset(&sad, 0, sizeof(sad)); + sad.sin_family = AF_INET; + sad.sin_port = htons(port); + sad.sin_addr.s_addr = host; + if (connect(sock, &sad, sizeof(sad)) < 0) { + error("Can't connect to %s: %m", dest); + close(sock); + return -1; + } + + return sock; +} + /* * start_charshunt - create a child process to run the character shunt. */ @@ -1998,6 +2064,8 @@ charshunt(ifd, ofd, record_file) int pty_readable, stdin_readable; struct timeval lasttime; FILE *recordf = NULL; + int ilevel, olevel, max_level; + struct timeval levelt, tout, *top; /* * Reset signal handlers. @@ -2071,6 +2139,16 @@ charshunt(ifd, ofd, record_file) nibuf = nobuf = 0; ibufp = obufp = NULL; pty_readable = stdin_readable = 1; + + ilevel = olevel = 0; + gettimeofday(&levelt, NULL); + if (max_data_rate) { + max_level = max_data_rate / 10; + if (max_level < 100) + max_level = 100; + } else + max_level = sizeof(inpacket_buf) + 1; + nfds = (ofd > pty_master? ofd: pty_master) + 1; if (recordf != NULL) { gettimeofday(&lasttime, NULL); @@ -2083,21 +2161,44 @@ charshunt(ifd, ofd, record_file) } while (nibuf != 0 || nobuf != 0 || pty_readable || stdin_readable) { + top = 0; + tout.tv_sec = 0; + tout.tv_usec = 10000; FD_ZERO(&ready); FD_ZERO(&writey); - if (nibuf != 0) - FD_SET(pty_master, &writey); - else if (stdin_readable) + if (nibuf != 0) { + if (ilevel >= max_level) + top = &tout; + else + FD_SET(pty_master, &writey); + } else if (stdin_readable) FD_SET(ifd, &ready); - if (nobuf != 0) - FD_SET(ofd, &writey); - else if (pty_readable) + if (nobuf != 0) { + if (olevel >= max_level) + top = &tout; + else + FD_SET(ofd, &writey); + } else if (pty_readable) FD_SET(pty_master, &ready); - if (select(nfds, &ready, &writey, NULL, NULL) < 0) { + if (select(nfds, &ready, &writey, NULL, top) < 0) { if (errno != EINTR) fatal("select"); continue; } + if (max_data_rate) { + double dt; + int nbt; + struct timeval now; + + gettimeofday(&now, NULL); + dt = (now.tv_sec - levelt.tv_sec + + (now.tv_usec - levelt.tv_usec) / 1e6); + nbt = (int)(dt * max_data_rate); + ilevel = (nbt < 0 || nbt > ilevel)? 0: ilevel - nbt; + olevel = (nbt < 0 || nbt > olevel)? 0: olevel - nbt; + levelt = now; + } else + ilevel = olevel = 0; if (FD_ISSET(ifd, &ready)) { ibufp = inpacket_buf; nibuf = read(ifd, ibufp, sizeof(inpacket_buf)); @@ -2153,7 +2254,10 @@ charshunt(ifd, ofd, record_file) } } if (FD_ISSET(ofd, &writey)) { - n = write(ofd, obufp, nobuf); + n = nobuf; + if (olevel + n > max_level) + n = max_level - olevel; + n = write(ofd, obufp, n); if (n < 0) { if (errno != EIO) { error("Error writing standard output: %m"); @@ -2164,10 +2268,14 @@ charshunt(ifd, ofd, record_file) } else { obufp += n; nobuf -= n; + olevel += n; } } if (FD_ISSET(pty_master, &writey)) { - n = write(pty_master, ibufp, nibuf); + n = nibuf; + if (ilevel + n > max_level) + n = max_level - ilevel; + n = write(pty_master, ibufp, n); if (n < 0) { if (errno != EIO) { error("Error writing pseudo-tty master: %m"); @@ -2178,6 +2286,7 @@ charshunt(ifd, ofd, record_file) } else { ibufp += n; nibuf -= n; + ilevel += n; } } } diff --git a/pppd/options.c b/pppd/options.c index af2116d..d9e794b 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: options.c,v 1.69 1999/12/23 01:28:52 paulus Exp $" +#define RCSID "$Id: options.c,v 1.70 2000/03/13 23:39:58 paulus Exp $" #include #include @@ -93,6 +93,7 @@ int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ int holdoff = 30; /* # seconds to pause before reconnecting */ bool holdoff_specified; /* true if a holdoff value has been given */ bool notty = 0; /* Stdin/out is not a tty */ +char *pty_socket = NULL; /* Socket to connect to pty */ char *record_file = NULL; /* File to record chars sent/received */ int using_pty = 0; bool sync_serial = 0; /* Device is synchronous serial device */ @@ -101,6 +102,7 @@ int maxfail = 10; /* max # of unsuccessful connection attempts */ char linkname[MAXPATHLEN]; /* logical name for link */ bool tune_kernel; /* may alter kernel settings */ int connect_delay = 1000; /* wait this many ms after connect script */ +int max_data_rate; /* max bytes/sec through charshunt */ extern option_t auth_options[]; extern struct stat devstat; @@ -205,6 +207,8 @@ option_t general_options[] = { OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info }, { "notty", o_bool, ¬ty, "Input/output is not a tty", OPT_DEVNAM | 1 }, + { "socket", o_string, &pty_socket, + "Send and receive over socket, arg is host:port", OPT_DEVNAM }, { "record", o_string, &record_file, "Record characters sent/received to file" }, { "maxconnect", o_int, &maxconnect, @@ -270,6 +274,8 @@ option_t general_options[] = { "Don't alter kernel settings", 0 }, { "connect-delay", o_int, &connect_delay, "Maximum time (in ms) to wait after connect script finishes" }, + { "datarate", o_int, &max_data_rate, + "Maximum data rate in bytes/sec (with pty, notty or record option)" }, #ifdef PLUGIN { "plugin", o_special, loadplugin, "Load a plug-in module into pppd", OPT_PRIV }, diff --git a/pppd/pppd.h b/pppd/pppd.h index 4e094c8..5dfe83b 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: pppd.h,v 1.49 1999/12/23 01:29:42 paulus Exp $ + * $Id: pppd.h,v 1.50 2000/03/13 23:39:58 paulus Exp $ */ /* @@ -209,12 +209,14 @@ extern int idle_time_limit;/* Shut down link if idle for this long */ extern int holdoff; /* Dead time before restarting */ extern bool holdoff_specified; /* true if user gave a holdoff value */ extern bool notty; /* Stdin/out is not a tty */ +extern char *pty_socket; /* Socket to connect to pty */ extern char *record_file; /* File to record chars sent/received */ extern bool sync_serial; /* Device is synchronous serial device */ extern int maxfail; /* Max # of unsuccessful connection attempts */ extern char linkname[MAXPATHLEN]; /* logical name for link */ extern bool tune_kernel; /* May alter kernel settings as necessary */ extern int connect_delay; /* Time to delay after connect script */ +extern int max_data_rate; /* max bytes/sec through charshunt */ #ifdef PPP_FILTER extern struct bpf_program pass_filter; /* Filter for pkts to pass */