1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * User Process PPP 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 208fa6ebe4SBrian Somers * $Id: main.c,v 1.143 1998/09/17 00:45:27 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai */ 242764b86aSBrian Somers 251384bd27SBrian Somers #include <sys/types.h> 2675240ed1SBrian Somers #include <netinet/in.h> 27a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 28a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 29565e35e5SBrian Somers #include <sys/un.h> 3075240ed1SBrian Somers 3175240ed1SBrian Somers #include <errno.h> 3275240ed1SBrian Somers #include <fcntl.h> 3375240ed1SBrian Somers #include <paths.h> 3475240ed1SBrian Somers #include <signal.h> 3575240ed1SBrian Somers #include <stdio.h> 3675240ed1SBrian Somers #include <string.h> 3775240ed1SBrian Somers #include <sys/time.h> 3875240ed1SBrian Somers #include <termios.h> 3975240ed1SBrian Somers #include <unistd.h> 4075240ed1SBrian Somers 411595bacdSBrian Somers #ifndef NOALIAS 421595bacdSBrian Somers #ifdef __OpenBSD__ 431595bacdSBrian Somers #include "alias.h" 441595bacdSBrian Somers #else 451595bacdSBrian Somers #include <alias.h> 461595bacdSBrian Somers #endif 471595bacdSBrian Somers #endif 481af29a6eSBrian Somers #include "probe.h" 4975240ed1SBrian Somers #include "mbuf.h" 5075240ed1SBrian Somers #include "log.h" 5175240ed1SBrian Somers #include "defs.h" 525106c671SBrian Somers #include "id.h" 5375240ed1SBrian Somers #include "timer.h" 5475240ed1SBrian Somers #include "fsm.h" 55879ed6faSBrian Somers #include "lqr.h" 56af57ed9fSAtsushi Murai #include "hdlc.h" 57af57ed9fSAtsushi Murai #include "lcp.h" 580053cc58SBrian Somers #include "ccp.h" 5929e275ceSBrian Somers #include "iplist.h" 6029e275ceSBrian Somers #include "throughput.h" 61eaa4df37SBrian Somers #include "slcompress.h" 62af57ed9fSAtsushi Murai #include "ipcp.h" 6384b8a6ebSAtsushi Murai #include "filter.h" 642f786681SBrian Somers #include "descriptor.h" 653b0f8d2eSBrian Somers #include "link.h" 663b0f8d2eSBrian Somers #include "mp.h" 675828db6dSBrian Somers #include "bundle.h" 681ae349f5Scvs2svn #include "auth.h" 69ed6a16c1SPoul-Henning Kamp #include "systems.h" 70f5ff0f7cSBrian Somers #include "sig.h" 7175240ed1SBrian Somers #include "main.h" 7277ff88adSBrian Somers #include "server.h" 7385b542cfSBrian Somers #include "prompt.h" 74b6dec9f0SBrian Somers #include "chat.h" 75e2ebb036SBrian Somers #include "chap.h" 7692b09558SBrian Somers #include "cbcp.h" 773006ec67SBrian Somers #include "datalink.h" 788fa6ebe4SBrian Somers #include "iface.h" 7953c9f6c0SAtsushi Murai 8053c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 8153c9f6c0SAtsushi Murai #ifdef O_NDELAY 8253c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 8353c9f6c0SAtsushi Murai #endif 8453c9f6c0SAtsushi Murai #endif 85af57ed9fSAtsushi Murai 860f78c7a7SBrian Somers static void DoLoop(struct bundle *); 8775240ed1SBrian Somers static void TerminalStop(int); 88b6e82f33SBrian Somers static const char *ex_desc(int); 8975240ed1SBrian Somers 9083d1af55SBrian Somers static struct bundle *SignalBundle; 91b6217683SBrian Somers static struct prompt *SignalPrompt; 92c3899f8dSAtsushi Murai 93c3899f8dSAtsushi Murai void 94944f7098SBrian Somers Cleanup(int excode) 95af57ed9fSAtsushi Murai { 96a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 979c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 986e4959f0SBrian Somers } 99af57ed9fSAtsushi Murai 1001afedc4bSBrian Somers void 1011afedc4bSBrian Somers AbortProgram(int excode) 1021afedc4bSBrian Somers { 103dd7e2610SBrian Somers server_Close(SignalBundle); 104dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 1059c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 10668a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 107dd7e2610SBrian Somers log_Close(); 108af57ed9fSAtsushi Murai exit(excode); 109af57ed9fSAtsushi Murai } 110af57ed9fSAtsushi Murai 111af57ed9fSAtsushi Murai static void 112944f7098SBrian Somers CloseConnection(int signo) 113af57ed9fSAtsushi Murai { 114368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 115dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 116dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 117899011c4SBrian Somers bundle_Down(SignalBundle, CLOSE_STAYDOWN); 118dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1196d14e2a8SJordan K. Hubbard } 120af57ed9fSAtsushi Murai 121af57ed9fSAtsushi Murai static void 122944f7098SBrian Somers CloseSession(int signo) 123af57ed9fSAtsushi Murai { 124dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 125af57ed9fSAtsushi Murai Cleanup(EX_TERM); 126af57ed9fSAtsushi Murai } 127c3899f8dSAtsushi Murai 12875b8d283SBrian Somers static pid_t BGPid = 0; 12975b8d283SBrian Somers 13075b8d283SBrian Somers static void 13175b8d283SBrian Somers KillChild(int signo) 13275b8d283SBrian Somers { 133dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 13475b8d283SBrian Somers kill(BGPid, SIGINT); 13575b8d283SBrian Somers } 13675b8d283SBrian Somers 137c3899f8dSAtsushi Murai static void 138b6e82f33SBrian Somers TerminalCont(int signo) 139c3899f8dSAtsushi Murai { 140f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 141f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 142c3899f8dSAtsushi Murai } 143c3899f8dSAtsushi Murai 144c3899f8dSAtsushi Murai static void 145944f7098SBrian Somers TerminalStop(int signo) 146c3899f8dSAtsushi Murai { 147f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 148f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 149f91ad6b0SBrian Somers raise(SIGSTOP); 1504ef16f24SBrian Somers } 1514ef16f24SBrian Somers 1528ea8442cSBrian Somers static void 1538ea8442cSBrian Somers BringDownServer(int signo) 1548ea8442cSBrian Somers { 155b6217683SBrian Somers /* Drops all child prompts too ! */ 156dd7e2610SBrian Somers server_Close(SignalBundle); 1578ea8442cSBrian Somers } 1588ea8442cSBrian Somers 159b6e82f33SBrian Somers static const char * 1606efd9292SBrian Somers ex_desc(int ex) 1616efd9292SBrian Somers { 162d93d3a9cSBrian Somers static char num[12]; /* Used immediately if returned */ 163b6e82f33SBrian Somers static const char *desc[] = { 164b6e82f33SBrian Somers "normal", "start", "sock", "modem", "dial", "dead", "done", 165b6e82f33SBrian Somers "reboot", "errdead", "hangup", "term", "nodial", "nologin" 166b6e82f33SBrian Somers }; 1676efd9292SBrian Somers 16870ee81ffSBrian Somers if (ex >= 0 && ex < sizeof desc / sizeof *desc) 1696efd9292SBrian Somers return desc[ex]; 1706efd9292SBrian Somers snprintf(num, sizeof num, "%d", ex); 1716efd9292SBrian Somers return num; 1726efd9292SBrian Somers } 173c3899f8dSAtsushi Murai 17475240ed1SBrian Somers static void 175b6e82f33SBrian Somers Usage(void) 176af57ed9fSAtsushi Murai { 177680026d6SNate Williams fprintf(stderr, 178b6e82f33SBrian Somers "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 179b6e82f33SBrian Somers #ifndef NOALIAS 180b6e82f33SBrian Somers " [ -alias ]" 181b6e82f33SBrian Somers #endif 182b6e82f33SBrian Somers " [system]\n"); 183af57ed9fSAtsushi Murai exit(EX_START); 184af57ed9fSAtsushi Murai } 185af57ed9fSAtsushi Murai 18639f94eddSBrian Somers static char * 187615ad4f9SBrian Somers ProcessArgs(int argc, char **argv, int *mode, int *alias) 188af57ed9fSAtsushi Murai { 18981358fa3SBrian Somers int optc, labelrequired, newmode; 190af57ed9fSAtsushi Murai char *cp; 191af57ed9fSAtsushi Murai 192565e35e5SBrian Somers optc = labelrequired = 0; 19381358fa3SBrian Somers *mode = PHYS_INTERACTIVE; 194615ad4f9SBrian Somers *alias = 0; 195af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 196af57ed9fSAtsushi Murai cp = *argv + 1; 19781358fa3SBrian Somers newmode = Nam2mode(cp); 19881358fa3SBrian Somers switch (newmode) { 19981358fa3SBrian Somers case PHYS_NONE: 20081358fa3SBrian Somers if (strcmp(cp, "alias") == 0) { 201615ad4f9SBrian Somers #ifdef NOALIAS 202dd7e2610SBrian Somers log_Printf(LogWARN, "Cannot load alias library\n"); 203615ad4f9SBrian Somers #else 204615ad4f9SBrian Somers *alias = 1; 205615ad4f9SBrian Somers #endif 2061ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 207944f7098SBrian Somers } else 208af57ed9fSAtsushi Murai Usage(); 20981358fa3SBrian Somers break; 21081358fa3SBrian Somers 21181358fa3SBrian Somers case PHYS_ALL: 21281358fa3SBrian Somers Usage(); 21381358fa3SBrian Somers break; 21481358fa3SBrian Somers 21581358fa3SBrian Somers case PHYS_AUTO: 21681358fa3SBrian Somers case PHYS_BACKGROUND: 21781358fa3SBrian Somers case PHYS_DDIAL: 21881358fa3SBrian Somers labelrequired = 1; 21981358fa3SBrian Somers /* fall through */ 22081358fa3SBrian Somers 22181358fa3SBrian Somers default: 22281358fa3SBrian Somers *mode = newmode; 22381358fa3SBrian Somers } 224af57ed9fSAtsushi Murai optc++; 225944f7098SBrian Somers argv++; 226944f7098SBrian Somers argc--; 227af57ed9fSAtsushi Murai } 22881358fa3SBrian Somers 229af57ed9fSAtsushi Murai if (argc > 1) { 23085602e52SBrian Somers fprintf(stderr, "You may specify only one system label.\n"); 231af57ed9fSAtsushi Murai exit(EX_START); 232af57ed9fSAtsushi Murai } 233af57ed9fSAtsushi Murai 234af57ed9fSAtsushi Murai if (optc > 1) { 23585602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2361ae349f5Scvs2svn exit(EX_START); 2371ae349f5Scvs2svn } 2381ae349f5Scvs2svn 239565e35e5SBrian Somers if (labelrequired && argc != 1) { 240565e35e5SBrian Somers fprintf(stderr, "Destination system must be specified in" 241565e35e5SBrian Somers " auto, background or ddial mode.\n"); 242af57ed9fSAtsushi Murai exit(EX_START); 243af57ed9fSAtsushi Murai } 24439f94eddSBrian Somers 24539f94eddSBrian Somers return argc == 1 ? *argv : NULL; /* Don't SetLabel yet ! */ 246af57ed9fSAtsushi Murai } 247af57ed9fSAtsushi Murai 2484ef16f24SBrian Somers int 249944f7098SBrian Somers main(int argc, char **argv) 250af57ed9fSAtsushi Murai { 25139f94eddSBrian Somers char *name, *label; 252615ad4f9SBrian Somers int nfds, mode, alias; 2537a6f8720SBrian Somers struct bundle *bundle; 254b6217683SBrian Somers struct prompt *prompt; 255e3b4c400SBrian Somers 256e3b4c400SBrian Somers nfds = getdtablesize(); 257e3b4c400SBrian Somers if (nfds >= FD_SETSIZE) 258e3b4c400SBrian Somers /* 259e3b4c400SBrian Somers * If we've got loads of file descriptors, make sure they're all 260e3b4c400SBrian Somers * closed. If they aren't, we may end up with a seg fault when our 261e3b4c400SBrian Somers * `fd_set's get too big when select()ing ! 262e3b4c400SBrian Somers */ 263e3b4c400SBrian Somers while (--nfds > 2) 264e3b4c400SBrian Somers close(nfds); 265af57ed9fSAtsushi Murai 26675240ed1SBrian Somers name = strrchr(argv[0], '/'); 267dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 2682a279fedSBrian Somers 2692a630835SBrian Somers #ifndef NOALIAS 2702a630835SBrian Somers PacketAliasInit(); 2712a630835SBrian Somers #endif 272615ad4f9SBrian Somers label = ProcessArgs(argc - 1, argv + 1, &mode, &alias); 27385b542cfSBrian Somers 27485b542cfSBrian Somers #ifdef __FreeBSD__ 27585b542cfSBrian Somers /* 27685b542cfSBrian Somers * A FreeBSD hack to dodge a bug in the tty driver that drops output 27785b542cfSBrian Somers * occasionally.... I must find the real reason some time. To display 27885b542cfSBrian Somers * the dodgy behaviour, comment out this bit, make yourself a large 27985b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 28085b542cfSBrian Somers * command will drop chunks of data !!! 28185b542cfSBrian Somers */ 28281358fa3SBrian Somers if (mode == PHYS_INTERACTIVE) { 28385b542cfSBrian Somers close(STDIN_FILENO); 28485b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 28585b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 28685b542cfSBrian Somers return 2; 28785b542cfSBrian Somers } 28885b542cfSBrian Somers } 28985b542cfSBrian Somers #endif 29085b542cfSBrian Somers 291b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 2926f384573SBrian Somers if (mode == PHYS_DIRECT) 293b6217683SBrian Somers prompt = NULL; 29485602e52SBrian Somers else { 295b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 29681358fa3SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(mode)); 29785602e52SBrian Somers } 29812ef29a8SBrian Somers 2995106c671SBrian Somers ID0init(); 3004562be74SBrian Somers if (ID0realuid() != 0) { 3014562be74SBrian Somers char conf[200], *ptr; 3024562be74SBrian Somers 3034562be74SBrian Somers snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 3044562be74SBrian Somers do { 3054562be74SBrian Somers if (!access(conf, W_OK)) { 306a33b2ef7SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 307a33b2ef7SBrian Somers conf); 3084562be74SBrian Somers return -1; 3094562be74SBrian Somers } 3104562be74SBrian Somers ptr = conf + strlen(conf)-2; 3114562be74SBrian Somers while (ptr > conf && *ptr != '/') 3124562be74SBrian Somers *ptr-- = '\0'; 3134562be74SBrian Somers } while (ptr >= conf); 3144562be74SBrian Somers } 3154562be74SBrian Somers 316dd7e2610SBrian Somers if (!system_IsValid(label, prompt, mode)) { 31712ef29a8SBrian Somers fprintf(stderr, "You may not use ppp in this mode with this label\n"); 3186f384573SBrian Somers if (mode == PHYS_DIRECT) { 319815624cfSBrian Somers const char *l; 32039f94eddSBrian Somers l = label ? label : "default"; 321dd7e2610SBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection\n", l); 322815624cfSBrian Somers } 323dd7e2610SBrian Somers log_Close(); 32412ef29a8SBrian Somers return 1; 32512ef29a8SBrian Somers } 32612ef29a8SBrian Somers 3278e7b8599SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, mode, (const char **)argv)) == NULL) { 328dd7e2610SBrian Somers log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno)); 3294ef16f24SBrian Somers return EX_START; 330af57ed9fSAtsushi Murai } 3310f2f3eb3SBrian Somers if (prompt) { 3320f2f3eb3SBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 3338fa6ebe4SBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 3340f2f3eb3SBrian Somers } 33583d1af55SBrian Somers SignalBundle = bundle; 336615ad4f9SBrian Somers bundle->AliasEnabled = alias; 3378fa6ebe4SBrian Somers if (alias) 3388fa6ebe4SBrian Somers bundle->cfg.opt |= OPT_IFACEALIAS; 33912ef29a8SBrian Somers 34030291ffbSBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 341565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3421ae349f5Scvs2svn 343dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 344dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 345dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 346dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 347dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 348e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 349565e35e5SBrian Somers 35081358fa3SBrian Somers if (mode == PHYS_INTERACTIVE) 351dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 352f91ad6b0SBrian Somers 353dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 354af57ed9fSAtsushi Murai 35539f94eddSBrian Somers if (label) { 35639f94eddSBrian Somers /* 357dd7e2610SBrian Somers * Set label both before and after system_Select ! 358dd7e2610SBrian Somers * This way, "set enddisc label" works during system_Select, and we 35949052c95SBrian Somers * also end up with the correct label if we have embedded load 36049052c95SBrian Somers * commands. 36139f94eddSBrian Somers */ 36249052c95SBrian Somers bundle_SetLabel(bundle, label); 36330291ffbSBrian Somers if (system_Select(bundle, label, CONFFILE, prompt, NULL) < 0) { 364b6217683SBrian Somers prompt_Printf(prompt, "Destination system (%s) not found.\n", label); 3658390b576SBrian Somers AbortProgram(EX_START); 3661ae349f5Scvs2svn } 36749052c95SBrian Somers bundle_SetLabel(bundle, label); 36881358fa3SBrian Somers if (mode == PHYS_AUTO && 3695828db6dSBrian Somers bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 370565e35e5SBrian Somers prompt_Printf(prompt, "You must \"set ifaddr\" with a peer address " 371565e35e5SBrian Somers "in label %s for auto mode.\n", label); 3728390b576SBrian Somers AbortProgram(EX_START); 373af57ed9fSAtsushi Murai } 374af57ed9fSAtsushi Murai } 3756efd9292SBrian Somers 37681358fa3SBrian Somers if (mode != PHYS_INTERACTIVE) { 3776f384573SBrian Somers if (mode != PHYS_DIRECT) { 3785cf4388bSBrian Somers int bgpipe[2]; 3796d14e2a8SJordan K. Hubbard pid_t bgpid; 380a9c6b5dfSAtsushi Murai 38181358fa3SBrian Somers if (mode == PHYS_BACKGROUND && pipe(bgpipe)) { 382dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 3838390b576SBrian Somers AbortProgram(EX_SOCK); 3841ae349f5Scvs2svn } 3851ae349f5Scvs2svn 3866d14e2a8SJordan K. Hubbard bgpid = fork(); 3876d14e2a8SJordan K. Hubbard if (bgpid == -1) { 388dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 3898390b576SBrian Somers AbortProgram(EX_SOCK); 3906d14e2a8SJordan K. Hubbard } 3915cf4388bSBrian Somers 3926d14e2a8SJordan K. Hubbard if (bgpid) { 3936d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 394a9c6b5dfSAtsushi Murai 39581358fa3SBrian Somers if (mode == PHYS_BACKGROUND) { 3965cf4388bSBrian Somers close(bgpipe[1]); 3976d14e2a8SJordan K. Hubbard BGPid = bgpid; 39875b8d283SBrian Somers /* If we get a signal, kill the child */ 39975b8d283SBrian Somers signal(SIGHUP, KillChild); 40075b8d283SBrian Somers signal(SIGTERM, KillChild); 40175b8d283SBrian Somers signal(SIGINT, KillChild); 40275b8d283SBrian Somers signal(SIGQUIT, KillChild); 40375b8d283SBrian Somers 40475b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 4055cf4388bSBrian Somers if (read(bgpipe[0], &c, 1) != 1) { 406b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 407dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4086efd9292SBrian Somers } else if (c == EX_NORMAL) { 409b6217683SBrian Somers prompt_Printf(prompt, "PPP enabled.\n"); 410dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled.\n"); 4116efd9292SBrian Somers } else { 412b6217683SBrian Somers prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c)); 413dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s).\n", 41480e37c72SBrian Somers ex_desc((int) c)); 4156efd9292SBrian Somers } 4165cf4388bSBrian Somers close(bgpipe[0]); 4176d14e2a8SJordan K. Hubbard } 4184ef16f24SBrian Somers return c; 41981358fa3SBrian Somers } else if (mode == PHYS_BACKGROUND) { 4205cf4388bSBrian Somers close(bgpipe[0]); 4215cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 422aefd026aSBrian Somers } 423aefd026aSBrian Somers 424da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 425da66dd13SBrian Somers 426565e35e5SBrian Somers /* -auto, -dedicated, -ddial & -background */ 427b6217683SBrian Somers prompt_Destroy(prompt, 0); 4282a279fedSBrian Somers close(STDOUT_FILENO); 4292a279fedSBrian Somers close(STDERR_FILENO); 4302a279fedSBrian Somers close(STDIN_FILENO); 431b6217683SBrian Somers setsid(); 432565e35e5SBrian Somers } else { 433565e35e5SBrian Somers /* -direct: STDIN_FILENO gets used by modem_Open */ 434565e35e5SBrian Somers prompt_TtyInit(NULL); 435565e35e5SBrian Somers close(STDOUT_FILENO); 436565e35e5SBrian Somers close(STDERR_FILENO); 437d656a4c5SBrian Somers } 438af57ed9fSAtsushi Murai } else { 439565e35e5SBrian Somers /* Interactive mode */ 4402a279fedSBrian Somers close(STDERR_FILENO); 441565e35e5SBrian Somers prompt_TtyInit(prompt); 442b6217683SBrian Somers prompt_TtyCommandMode(prompt); 443b6217683SBrian Somers prompt_Required(prompt); 444af57ed9fSAtsushi Murai } 44535495becSBrian Somers 446dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); 4470f78c7a7SBrian Somers DoLoop(bundle); 4481afedc4bSBrian Somers AbortProgram(EX_NORMAL); 449af57ed9fSAtsushi Murai 4501afedc4bSBrian Somers return EX_NORMAL; 451af57ed9fSAtsushi Murai } 452af57ed9fSAtsushi Murai 453af57ed9fSAtsushi Murai static void 4540f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 455af57ed9fSAtsushi Murai { 456af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 4571af29a6eSBrian Somers int i, nfds, nothing_done; 4581af29a6eSBrian Somers struct probe probe; 4591af29a6eSBrian Somers 4601af29a6eSBrian Somers probe_Init(&probe); 461c3899f8dSAtsushi Murai 462565e35e5SBrian Somers do { 463780700e5SAndrey A. Chernov nfds = 0; 464944f7098SBrian Somers FD_ZERO(&rfds); 465944f7098SBrian Somers FD_ZERO(&wfds); 466944f7098SBrian Somers FD_ZERO(&efds); 46784b8a6ebSAtsushi Murai 4680f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 4696f384573SBrian Somers descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds); 4700f2f3eb3SBrian Somers 4710f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 4720f2f3eb3SBrian Somers descriptor_UpdateSet(&server.desc, &rfds, NULL, NULL, &nfds); 47307030d97SBrian Somers 4743b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 475f4768038SBrian Somers /* Don't select - we'll be here forever */ 476f4768038SBrian Somers break; 4770706ff38SBrian Somers 4783006ec67SBrian Somers i = select(nfds, &rfds, &wfds, &efds, NULL); 479712ae387SBrian Somers 48054cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 481dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 48224989c68SBrian Somers if (log_IsKept(LogTIMER)) { 48324989c68SBrian Somers struct timeval t; 48424989c68SBrian Somers 48524989c68SBrian Somers for (i = 0; i <= nfds; i++) { 48624989c68SBrian Somers if (FD_ISSET(i, &rfds)) { 48724989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 48824989c68SBrian Somers FD_CLR(i, &rfds); 48924989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 49024989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 49124989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 492af57ed9fSAtsushi Murai break; 493af57ed9fSAtsushi Murai } 49424989c68SBrian Somers } 49524989c68SBrian Somers if (FD_ISSET(i, &wfds)) { 49624989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 49724989c68SBrian Somers FD_CLR(i, &wfds); 49824989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 49924989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 50024989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 501af57ed9fSAtsushi Murai break; 502af57ed9fSAtsushi Murai } 503e0d3e233SAndrey A. Chernov } 50424989c68SBrian Somers if (FD_ISSET(i, &efds)) { 50524989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 50624989c68SBrian Somers FD_CLR(i, &efds); 50724989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 50824989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 50924989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 51058f264e1SBrian Somers break; 51158f264e1SBrian Somers } 51224989c68SBrian Somers } 51324989c68SBrian Somers } 51424989c68SBrian Somers } 51558f264e1SBrian Somers break; 516de451c68SBrian Somers } 517de451c68SBrian Somers 51854cd8e13SBrian Somers sig_Handle(); 51954cd8e13SBrian Somers 52054cd8e13SBrian Somers if (i <= 0) 52154cd8e13SBrian Somers continue; 52254cd8e13SBrian Somers 5233006ec67SBrian Somers for (i = 0; i <= nfds; i++) 5243006ec67SBrian Somers if (FD_ISSET(i, &efds)) { 525a33b2ef7SBrian Somers log_Printf(LogERROR, "Exception detected on descriptor %d\n", i); 5261ae349f5Scvs2svn break; 5271ae349f5Scvs2svn } 528c60f92caSBrian Somers 529b7c5748eSBrian Somers if (i <= nfds) 530b7c5748eSBrian Somers break; 531b7c5748eSBrian Somers 5321af29a6eSBrian Somers nothing_done = 1; 5331af29a6eSBrian Somers 5341af29a6eSBrian Somers if (descriptor_IsSet(&server.desc, &rfds)) { 535b77776a7SBrian Somers descriptor_Read(&server.desc, bundle, &rfds); 5361af29a6eSBrian Somers nothing_done = 0; 5371af29a6eSBrian Somers } 5381af29a6eSBrian Somers 5391af29a6eSBrian Somers if (descriptor_IsSet(&bundle->desc, &rfds)) { 5401af29a6eSBrian Somers descriptor_Read(&bundle->desc, bundle, &rfds); 5411af29a6eSBrian Somers nothing_done = 0; 5421af29a6eSBrian Somers } 54342d4d396SBrian Somers 5442f786681SBrian Somers if (descriptor_IsSet(&bundle->desc, &wfds)) 5451af29a6eSBrian Somers if (!descriptor_Write(&bundle->desc, bundle, &wfds) && nothing_done) { 5461af29a6eSBrian Somers /* 5471af29a6eSBrian Somers * This is disasterous. The OS has told us that something is 5481af29a6eSBrian Somers * writable, and all our write()s have failed. Rather than 5491af29a6eSBrian Somers * going back immediately to do our UpdateSet()s and select(), 5501af29a6eSBrian Somers * we sleep for a bit to avoid gobbling up all cpu time. 5511af29a6eSBrian Somers */ 5521af29a6eSBrian Somers struct timeval t; 5532f786681SBrian Somers 5541af29a6eSBrian Somers t.tv_sec = 0; 5551af29a6eSBrian Somers t.tv_usec = 100000; 5561af29a6eSBrian Somers select(0, NULL, NULL, NULL, &t); 5571af29a6eSBrian Somers } 55854cd8e13SBrian Somers 559565e35e5SBrian Somers } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle)); 560565e35e5SBrian Somers 561dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 562af57ed9fSAtsushi Murai } 563