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 * 201080ea25SBrian Somers * $Id: main.c,v 1.155 1999/05/13 16:34:57 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai */ 242764b86aSBrian Somers 25972a1bcfSBrian Somers #include <sys/param.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> 401080ea25SBrian Somers #include <sys/stat.h> 4175240ed1SBrian Somers 421595bacdSBrian Somers #ifndef NOALIAS 437884358fSBrian Somers #ifdef __FreeBSD__ 441595bacdSBrian Somers #include <alias.h> 457884358fSBrian Somers #else 467884358fSBrian Somers #include "alias.h" 471595bacdSBrian Somers #endif 481595bacdSBrian Somers #endif 495d9e6103SBrian Somers #include "layer.h" 501af29a6eSBrian Somers #include "probe.h" 5175240ed1SBrian Somers #include "mbuf.h" 5275240ed1SBrian Somers #include "log.h" 5375240ed1SBrian Somers #include "defs.h" 545106c671SBrian Somers #include "id.h" 5575240ed1SBrian Somers #include "timer.h" 5675240ed1SBrian Somers #include "fsm.h" 57879ed6faSBrian Somers #include "lqr.h" 58af57ed9fSAtsushi Murai #include "hdlc.h" 59af57ed9fSAtsushi Murai #include "lcp.h" 600053cc58SBrian Somers #include "ccp.h" 6129e275ceSBrian Somers #include "iplist.h" 6229e275ceSBrian Somers #include "throughput.h" 63eaa4df37SBrian Somers #include "slcompress.h" 64af57ed9fSAtsushi Murai #include "ipcp.h" 6584b8a6ebSAtsushi Murai #include "filter.h" 662f786681SBrian Somers #include "descriptor.h" 673b0f8d2eSBrian Somers #include "link.h" 683b0f8d2eSBrian Somers #include "mp.h" 69972a1bcfSBrian Somers #ifndef NORADIUS 70972a1bcfSBrian Somers #include "radius.h" 71972a1bcfSBrian Somers #endif 725828db6dSBrian Somers #include "bundle.h" 731ae349f5Scvs2svn #include "auth.h" 74ed6a16c1SPoul-Henning Kamp #include "systems.h" 75f5ff0f7cSBrian Somers #include "sig.h" 7675240ed1SBrian Somers #include "main.h" 7777ff88adSBrian Somers #include "server.h" 7885b542cfSBrian Somers #include "prompt.h" 79b6dec9f0SBrian Somers #include "chat.h" 80e2ebb036SBrian Somers #include "chap.h" 8192b09558SBrian Somers #include "cbcp.h" 823006ec67SBrian Somers #include "datalink.h" 838fa6ebe4SBrian Somers #include "iface.h" 8453c9f6c0SAtsushi Murai 8553c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 8653c9f6c0SAtsushi Murai #ifdef O_NDELAY 8753c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 8853c9f6c0SAtsushi Murai #endif 8953c9f6c0SAtsushi Murai #endif 90af57ed9fSAtsushi Murai 910f78c7a7SBrian Somers static void DoLoop(struct bundle *); 9275240ed1SBrian Somers static void TerminalStop(int); 93b6e82f33SBrian Somers static const char *ex_desc(int); 9475240ed1SBrian Somers 9583d1af55SBrian Somers static struct bundle *SignalBundle; 96b6217683SBrian Somers static struct prompt *SignalPrompt; 97c3899f8dSAtsushi Murai 98c3899f8dSAtsushi Murai void 99944f7098SBrian Somers Cleanup(int excode) 100af57ed9fSAtsushi Murai { 101a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 1029c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 1036e4959f0SBrian Somers } 104af57ed9fSAtsushi Murai 1051afedc4bSBrian Somers void 1061afedc4bSBrian Somers AbortProgram(int excode) 1071afedc4bSBrian Somers { 108dd7e2610SBrian Somers server_Close(SignalBundle); 109dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 1109c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 11168a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 112dd7e2610SBrian Somers log_Close(); 113af57ed9fSAtsushi Murai exit(excode); 114af57ed9fSAtsushi Murai } 115af57ed9fSAtsushi Murai 116af57ed9fSAtsushi Murai static void 117944f7098SBrian Somers CloseConnection(int signo) 118af57ed9fSAtsushi Murai { 119368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 120dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 121dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 122899011c4SBrian Somers bundle_Down(SignalBundle, CLOSE_STAYDOWN); 123dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1246d14e2a8SJordan K. Hubbard } 125af57ed9fSAtsushi Murai 126af57ed9fSAtsushi Murai static void 127944f7098SBrian Somers CloseSession(int signo) 128af57ed9fSAtsushi Murai { 129dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 130af57ed9fSAtsushi Murai Cleanup(EX_TERM); 131af57ed9fSAtsushi Murai } 132c3899f8dSAtsushi Murai 13375b8d283SBrian Somers static pid_t BGPid = 0; 13475b8d283SBrian Somers 13575b8d283SBrian Somers static void 13675b8d283SBrian Somers KillChild(int signo) 13775b8d283SBrian Somers { 138ac37ab22SBrian Somers signal(signo, SIG_IGN); 139dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 14075b8d283SBrian Somers kill(BGPid, SIGINT); 14175b8d283SBrian Somers } 14275b8d283SBrian Somers 143c3899f8dSAtsushi Murai static void 144b6e82f33SBrian Somers TerminalCont(int signo) 145c3899f8dSAtsushi Murai { 146f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 147f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 148c3899f8dSAtsushi Murai } 149c3899f8dSAtsushi Murai 150c3899f8dSAtsushi Murai static void 151944f7098SBrian Somers TerminalStop(int signo) 152c3899f8dSAtsushi Murai { 153f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 154f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 155f91ad6b0SBrian Somers raise(SIGSTOP); 1564ef16f24SBrian Somers } 1574ef16f24SBrian Somers 1588ea8442cSBrian Somers static void 1598ea8442cSBrian Somers BringDownServer(int signo) 1608ea8442cSBrian Somers { 161b6217683SBrian Somers /* Drops all child prompts too ! */ 162dd7e2610SBrian Somers server_Close(SignalBundle); 1638ea8442cSBrian Somers } 1648ea8442cSBrian Somers 165b6e82f33SBrian Somers static const char * 1666efd9292SBrian Somers ex_desc(int ex) 1676efd9292SBrian Somers { 168d93d3a9cSBrian Somers static char num[12]; /* Used immediately if returned */ 169b6e82f33SBrian Somers static const char *desc[] = { 170b6e82f33SBrian Somers "normal", "start", "sock", "modem", "dial", "dead", "done", 171b6e82f33SBrian Somers "reboot", "errdead", "hangup", "term", "nodial", "nologin" 172b6e82f33SBrian Somers }; 1736efd9292SBrian Somers 17470ee81ffSBrian Somers if (ex >= 0 && ex < sizeof desc / sizeof *desc) 1756efd9292SBrian Somers return desc[ex]; 1766efd9292SBrian Somers snprintf(num, sizeof num, "%d", ex); 1776efd9292SBrian Somers return num; 1786efd9292SBrian Somers } 179c3899f8dSAtsushi Murai 18075240ed1SBrian Somers static void 181b6e82f33SBrian Somers Usage(void) 182af57ed9fSAtsushi Murai { 183680026d6SNate Williams fprintf(stderr, 184b6e82f33SBrian Somers "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 185b6e82f33SBrian Somers #ifndef NOALIAS 186b6e82f33SBrian Somers " [ -alias ]" 187b6e82f33SBrian Somers #endif 1887cf368ebSBrian Somers " [system ...]\n"); 189af57ed9fSAtsushi Murai exit(EX_START); 190af57ed9fSAtsushi Murai } 191af57ed9fSAtsushi Murai 1927cf368ebSBrian Somers static int 193615ad4f9SBrian Somers ProcessArgs(int argc, char **argv, int *mode, int *alias) 194af57ed9fSAtsushi Murai { 1957cf368ebSBrian Somers int optc, newmode, arg; 196af57ed9fSAtsushi Murai char *cp; 197af57ed9fSAtsushi Murai 1987cf368ebSBrian Somers optc = 0; 19981358fa3SBrian Somers *mode = PHYS_INTERACTIVE; 200615ad4f9SBrian Somers *alias = 0; 2017cf368ebSBrian Somers for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 2027cf368ebSBrian Somers cp = argv[arg] + 1; 20381358fa3SBrian Somers newmode = Nam2mode(cp); 20481358fa3SBrian Somers switch (newmode) { 20581358fa3SBrian Somers case PHYS_NONE: 20681358fa3SBrian Somers if (strcmp(cp, "alias") == 0) { 207615ad4f9SBrian Somers #ifdef NOALIAS 2087cf368ebSBrian Somers log_Printf(LogWARN, "Cannot load alias library (compiled out)\n"); 209615ad4f9SBrian Somers #else 210615ad4f9SBrian Somers *alias = 1; 211615ad4f9SBrian Somers #endif 2121ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 213944f7098SBrian Somers } else 214af57ed9fSAtsushi Murai Usage(); 21581358fa3SBrian Somers break; 21681358fa3SBrian Somers 21781358fa3SBrian Somers case PHYS_ALL: 21881358fa3SBrian Somers Usage(); 21981358fa3SBrian Somers break; 22081358fa3SBrian Somers 22181358fa3SBrian Somers default: 22281358fa3SBrian Somers *mode = newmode; 22381358fa3SBrian Somers } 224af57ed9fSAtsushi Murai } 225af57ed9fSAtsushi Murai 226af57ed9fSAtsushi Murai if (optc > 1) { 22785602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2281ae349f5Scvs2svn exit(EX_START); 2291ae349f5Scvs2svn } 2301ae349f5Scvs2svn 2317cf368ebSBrian Somers if (*mode == PHYS_AUTO && arg == argc) { 2327cf368ebSBrian Somers fprintf(stderr, "A system must be specified in auto mode.\n"); 233af57ed9fSAtsushi Murai exit(EX_START); 234af57ed9fSAtsushi Murai } 23539f94eddSBrian Somers 2367cf368ebSBrian Somers return arg; /* Don't SetLabel yet ! */ 237af57ed9fSAtsushi Murai } 238af57ed9fSAtsushi Murai 2397cf368ebSBrian Somers static void 2407cf368ebSBrian Somers CheckLabel(const char *label, struct prompt *prompt, int mode) 2417cf368ebSBrian Somers { 2427cf368ebSBrian Somers const char *err; 2437cf368ebSBrian Somers 2447cf368ebSBrian Somers if ((err = system_IsValid(label, prompt, mode)) != NULL) { 2457cf368ebSBrian Somers fprintf(stderr, "%s: %s\n", label, err); 2467cf368ebSBrian Somers if (mode == PHYS_DIRECT) 2477cf368ebSBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 2487cf368ebSBrian Somers label, err); 2497cf368ebSBrian Somers log_Close(); 2507cf368ebSBrian Somers exit(1); 2517cf368ebSBrian Somers } 2527cf368ebSBrian Somers } 2537cf368ebSBrian Somers 2547cf368ebSBrian Somers 2554ef16f24SBrian Somers int 256944f7098SBrian Somers main(int argc, char **argv) 257af57ed9fSAtsushi Murai { 2587cf368ebSBrian Somers char *name; 259756783fcSBrian Somers const char *lastlabel; 2607cf368ebSBrian Somers int nfds, mode, alias, label, arg; 2617a6f8720SBrian Somers struct bundle *bundle; 262b6217683SBrian Somers struct prompt *prompt; 263e3b4c400SBrian Somers 264e3b4c400SBrian Somers nfds = getdtablesize(); 265e3b4c400SBrian Somers if (nfds >= FD_SETSIZE) 266e3b4c400SBrian Somers /* 267e3b4c400SBrian Somers * If we've got loads of file descriptors, make sure they're all 268e3b4c400SBrian Somers * closed. If they aren't, we may end up with a seg fault when our 269e3b4c400SBrian Somers * `fd_set's get too big when select()ing ! 270e3b4c400SBrian Somers */ 271e3b4c400SBrian Somers while (--nfds > 2) 272e3b4c400SBrian Somers close(nfds); 273af57ed9fSAtsushi Murai 27475240ed1SBrian Somers name = strrchr(argv[0], '/'); 275dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 2762a279fedSBrian Somers 2772a630835SBrian Somers #ifndef NOALIAS 2782a630835SBrian Somers PacketAliasInit(); 2792a630835SBrian Somers #endif 2807cf368ebSBrian Somers label = ProcessArgs(argc, argv, &mode, &alias); 28185b542cfSBrian Somers 28285b542cfSBrian Somers /* 283a611383fSBrian Somers * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 284a611383fSBrian Somers * output occasionally.... I must find the real reason some time. To 285a611383fSBrian Somers * display the dodgy behaviour, comment out this bit, make yourself a large 28685b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 28785b542cfSBrian Somers * command will drop chunks of data !!! 28885b542cfSBrian Somers */ 28981358fa3SBrian Somers if (mode == PHYS_INTERACTIVE) { 29085b542cfSBrian Somers close(STDIN_FILENO); 29185b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 29285b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 29385b542cfSBrian Somers return 2; 29485b542cfSBrian Somers } 29585b542cfSBrian Somers } 29685b542cfSBrian Somers 297b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 2986f384573SBrian Somers if (mode == PHYS_DIRECT) 299b6217683SBrian Somers prompt = NULL; 300ed0e9269SBrian Somers else 301b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 30212ef29a8SBrian Somers 3035106c671SBrian Somers ID0init(); 3044562be74SBrian Somers if (ID0realuid() != 0) { 3054562be74SBrian Somers char conf[200], *ptr; 3064562be74SBrian Somers 3074562be74SBrian Somers snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 3084562be74SBrian Somers do { 3091080ea25SBrian Somers struct stat sb; 3101080ea25SBrian Somers 3111080ea25SBrian Somers if (stat(conf, &sb) == 0 && sb.st_mode & S_IWOTH) { 312a33b2ef7SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 313a33b2ef7SBrian Somers conf); 3144562be74SBrian Somers return -1; 3154562be74SBrian Somers } 3164562be74SBrian Somers ptr = conf + strlen(conf)-2; 3174562be74SBrian Somers while (ptr > conf && *ptr != '/') 3184562be74SBrian Somers *ptr-- = '\0'; 3194562be74SBrian Somers } while (ptr >= conf); 3204562be74SBrian Somers } 3214562be74SBrian Somers 3227cf368ebSBrian Somers if (label < argc) 3237cf368ebSBrian Somers for (arg = label; arg < argc; arg++) 3247cf368ebSBrian Somers CheckLabel(argv[arg], prompt, mode); 3257cf368ebSBrian Somers else 3267cf368ebSBrian Somers CheckLabel("default", prompt, mode); 32712ef29a8SBrian Somers 328ed0e9269SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(mode)); 329ed0e9269SBrian Somers 3308e7b8599SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, mode, (const char **)argv)) == NULL) { 331dd7e2610SBrian Somers log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno)); 3324ef16f24SBrian Somers return EX_START; 333af57ed9fSAtsushi Murai } 334756783fcSBrian Somers 335756783fcSBrian Somers /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 336756783fcSBrian Somers 3370f2f3eb3SBrian Somers if (prompt) { 3380f2f3eb3SBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 3398fa6ebe4SBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 3400f2f3eb3SBrian Somers } 34183d1af55SBrian Somers SignalBundle = bundle; 342615ad4f9SBrian Somers bundle->AliasEnabled = alias; 3438fa6ebe4SBrian Somers if (alias) 3448fa6ebe4SBrian Somers bundle->cfg.opt |= OPT_IFACEALIAS; 34512ef29a8SBrian Somers 34630291ffbSBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 347565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3481ae349f5Scvs2svn 349dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 350dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 351dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 352dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 353dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 354e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 355565e35e5SBrian Somers 35681358fa3SBrian Somers if (mode == PHYS_INTERACTIVE) 357dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 358f91ad6b0SBrian Somers 359dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 360af57ed9fSAtsushi Murai 361756783fcSBrian Somers lastlabel = argc == 2 ? bundle->argv1 : argv[argc - 1]; 3627cf368ebSBrian Somers for (arg = label; arg < argc; arg++) { 3637cf368ebSBrian Somers /* In case we use LABEL or ``set enddisc label'' */ 364756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 365756783fcSBrian Somers system_Select(bundle, arg == 1 ? bundle->argv1 : argv[arg], 366756783fcSBrian Somers CONFFILE, prompt, NULL); 3671ae349f5Scvs2svn } 3687cf368ebSBrian Somers 3697cf368ebSBrian Somers if (label < argc) 3707cf368ebSBrian Somers /* In case the last label did a ``load'' */ 371756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 3727cf368ebSBrian Somers 37381358fa3SBrian Somers if (mode == PHYS_AUTO && 3745828db6dSBrian Somers bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 3757cf368ebSBrian Somers prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 3767cf368ebSBrian Somers "in auto mode.\n"); 3778390b576SBrian Somers AbortProgram(EX_START); 378af57ed9fSAtsushi Murai } 3796efd9292SBrian Somers 38081358fa3SBrian Somers if (mode != PHYS_INTERACTIVE) { 3816f384573SBrian Somers if (mode != PHYS_DIRECT) { 3825cf4388bSBrian Somers int bgpipe[2]; 3836d14e2a8SJordan K. Hubbard pid_t bgpid; 384a9c6b5dfSAtsushi Murai 38581358fa3SBrian Somers if (mode == PHYS_BACKGROUND && pipe(bgpipe)) { 386dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 3878390b576SBrian Somers AbortProgram(EX_SOCK); 3881ae349f5Scvs2svn } 3891ae349f5Scvs2svn 3906d14e2a8SJordan K. Hubbard bgpid = fork(); 3916d14e2a8SJordan K. Hubbard if (bgpid == -1) { 392dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 3938390b576SBrian Somers AbortProgram(EX_SOCK); 3946d14e2a8SJordan K. Hubbard } 3955cf4388bSBrian Somers 3966d14e2a8SJordan K. Hubbard if (bgpid) { 3976d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 398a9c6b5dfSAtsushi Murai 39981358fa3SBrian Somers if (mode == PHYS_BACKGROUND) { 4005cf4388bSBrian Somers close(bgpipe[1]); 4016d14e2a8SJordan K. Hubbard BGPid = bgpid; 40275b8d283SBrian Somers /* If we get a signal, kill the child */ 40375b8d283SBrian Somers signal(SIGHUP, KillChild); 40475b8d283SBrian Somers signal(SIGTERM, KillChild); 40575b8d283SBrian Somers signal(SIGINT, KillChild); 40675b8d283SBrian Somers signal(SIGQUIT, KillChild); 40775b8d283SBrian Somers 40875b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 4095cf4388bSBrian Somers if (read(bgpipe[0], &c, 1) != 1) { 410b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 411dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4126efd9292SBrian Somers } else if (c == EX_NORMAL) { 413b6217683SBrian Somers prompt_Printf(prompt, "PPP enabled.\n"); 414dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled.\n"); 4156efd9292SBrian Somers } else { 416b6217683SBrian Somers prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c)); 417dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s).\n", 41880e37c72SBrian Somers ex_desc((int) c)); 4196efd9292SBrian Somers } 4205cf4388bSBrian Somers close(bgpipe[0]); 4216d14e2a8SJordan K. Hubbard } 4224ef16f24SBrian Somers return c; 42381358fa3SBrian Somers } else if (mode == PHYS_BACKGROUND) { 4245cf4388bSBrian Somers close(bgpipe[0]); 4255cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 426aefd026aSBrian Somers } 427aefd026aSBrian Somers 428da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 429da66dd13SBrian Somers 430565e35e5SBrian Somers /* -auto, -dedicated, -ddial & -background */ 431b6217683SBrian Somers prompt_Destroy(prompt, 0); 4322a279fedSBrian Somers close(STDOUT_FILENO); 4332a279fedSBrian Somers close(STDERR_FILENO); 4342a279fedSBrian Somers close(STDIN_FILENO); 435b6217683SBrian Somers setsid(); 436565e35e5SBrian Somers } else { 437565e35e5SBrian Somers /* -direct: STDIN_FILENO gets used by modem_Open */ 438565e35e5SBrian Somers prompt_TtyInit(NULL); 439565e35e5SBrian Somers close(STDOUT_FILENO); 440565e35e5SBrian Somers close(STDERR_FILENO); 441d656a4c5SBrian Somers } 442af57ed9fSAtsushi Murai } else { 443565e35e5SBrian Somers /* Interactive mode */ 4442a279fedSBrian Somers close(STDERR_FILENO); 445565e35e5SBrian Somers prompt_TtyInit(prompt); 446b6217683SBrian Somers prompt_TtyCommandMode(prompt); 447b6217683SBrian Somers prompt_Required(prompt); 448af57ed9fSAtsushi Murai } 44935495becSBrian Somers 450dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); 4510f78c7a7SBrian Somers DoLoop(bundle); 4521afedc4bSBrian Somers AbortProgram(EX_NORMAL); 453af57ed9fSAtsushi Murai 4541afedc4bSBrian Somers return EX_NORMAL; 455af57ed9fSAtsushi Murai } 456af57ed9fSAtsushi Murai 457af57ed9fSAtsushi Murai static void 4580f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 459af57ed9fSAtsushi Murai { 460af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 4611af29a6eSBrian Somers int i, nfds, nothing_done; 4621af29a6eSBrian Somers struct probe probe; 4631af29a6eSBrian Somers 4641af29a6eSBrian Somers probe_Init(&probe); 465c3899f8dSAtsushi Murai 466565e35e5SBrian Somers do { 467780700e5SAndrey A. Chernov nfds = 0; 468944f7098SBrian Somers FD_ZERO(&rfds); 469944f7098SBrian Somers FD_ZERO(&wfds); 470944f7098SBrian Somers FD_ZERO(&efds); 47184b8a6ebSAtsushi Murai 4720f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 4736f384573SBrian Somers descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds); 4740f2f3eb3SBrian Somers 4750f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 4760f2f3eb3SBrian Somers descriptor_UpdateSet(&server.desc, &rfds, NULL, NULL, &nfds); 47707030d97SBrian Somers 4783b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 479f4768038SBrian Somers /* Don't select - we'll be here forever */ 480f4768038SBrian Somers break; 4810706ff38SBrian Somers 482486105bcSBrian Somers /* 483486105bcSBrian Somers * It's possible that we've had a signal since we last checked. If 484486105bcSBrian Somers * we don't check again before calling select(), we may end up stuck 485486105bcSBrian Somers * after having missed the event.... sig_Handle() tries to be as 486486105bcSBrian Somers * quick as possible if nothing is likely to have happened. 487486105bcSBrian Somers * This is only really likely if we block in open(... O_NONBLOCK) 488486105bcSBrian Somers * which will happen with a misconfigured device. 489486105bcSBrian Somers */ 490486105bcSBrian Somers if (sig_Handle()) 491486105bcSBrian Somers continue; 492486105bcSBrian Somers 4933006ec67SBrian Somers i = select(nfds, &rfds, &wfds, &efds, NULL); 494712ae387SBrian Somers 49554cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 496dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 49724989c68SBrian Somers if (log_IsKept(LogTIMER)) { 49824989c68SBrian Somers struct timeval t; 49924989c68SBrian Somers 50024989c68SBrian Somers for (i = 0; i <= nfds; i++) { 50124989c68SBrian Somers if (FD_ISSET(i, &rfds)) { 50224989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 50324989c68SBrian Somers FD_CLR(i, &rfds); 50424989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 50524989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 50624989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 507af57ed9fSAtsushi Murai break; 508af57ed9fSAtsushi Murai } 50924989c68SBrian Somers } 51024989c68SBrian Somers if (FD_ISSET(i, &wfds)) { 51124989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 51224989c68SBrian Somers FD_CLR(i, &wfds); 51324989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 51424989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 51524989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 516af57ed9fSAtsushi Murai break; 517af57ed9fSAtsushi Murai } 518e0d3e233SAndrey A. Chernov } 51924989c68SBrian Somers if (FD_ISSET(i, &efds)) { 52024989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 52124989c68SBrian Somers FD_CLR(i, &efds); 52224989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 52324989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 52424989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 52558f264e1SBrian Somers break; 52658f264e1SBrian Somers } 52724989c68SBrian Somers } 52824989c68SBrian Somers } 52924989c68SBrian Somers } 53058f264e1SBrian Somers break; 531de451c68SBrian Somers } 532de451c68SBrian Somers 533f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Select returns %d\n", i); 534f0cdd9c0SBrian Somers 53554cd8e13SBrian Somers sig_Handle(); 53654cd8e13SBrian Somers 53754cd8e13SBrian Somers if (i <= 0) 53854cd8e13SBrian Somers continue; 53954cd8e13SBrian Somers 5403006ec67SBrian Somers for (i = 0; i <= nfds; i++) 5413006ec67SBrian Somers if (FD_ISSET(i, &efds)) { 542991c2a7bSBrian Somers log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 543991c2a7bSBrian Somers /* We deal gracefully with link descriptor exceptions */ 544991c2a7bSBrian Somers if (!bundle_Exception(bundle, i)) { 545991c2a7bSBrian Somers log_Printf(LogERROR, "Exception cannot be handled !\n"); 5461ae349f5Scvs2svn break; 5471ae349f5Scvs2svn } 548991c2a7bSBrian Somers } 549c60f92caSBrian Somers 550b7c5748eSBrian Somers if (i <= nfds) 551b7c5748eSBrian Somers break; 552b7c5748eSBrian Somers 5531af29a6eSBrian Somers nothing_done = 1; 5541af29a6eSBrian Somers 5551af29a6eSBrian Somers if (descriptor_IsSet(&server.desc, &rfds)) { 556b77776a7SBrian Somers descriptor_Read(&server.desc, bundle, &rfds); 5571af29a6eSBrian Somers nothing_done = 0; 5581af29a6eSBrian Somers } 5591af29a6eSBrian Somers 5601af29a6eSBrian Somers if (descriptor_IsSet(&bundle->desc, &rfds)) { 5611af29a6eSBrian Somers descriptor_Read(&bundle->desc, bundle, &rfds); 5621af29a6eSBrian Somers nothing_done = 0; 5631af29a6eSBrian Somers } 56442d4d396SBrian Somers 5652f786681SBrian Somers if (descriptor_IsSet(&bundle->desc, &wfds)) 5661af29a6eSBrian Somers if (!descriptor_Write(&bundle->desc, bundle, &wfds) && nothing_done) { 5671af29a6eSBrian Somers /* 5681af29a6eSBrian Somers * This is disasterous. The OS has told us that something is 5691af29a6eSBrian Somers * writable, and all our write()s have failed. Rather than 5701af29a6eSBrian Somers * going back immediately to do our UpdateSet()s and select(), 5711af29a6eSBrian Somers * we sleep for a bit to avoid gobbling up all cpu time. 5721af29a6eSBrian Somers */ 5731af29a6eSBrian Somers struct timeval t; 5742f786681SBrian Somers 5751af29a6eSBrian Somers t.tv_sec = 0; 5761af29a6eSBrian Somers t.tv_usec = 100000; 5771af29a6eSBrian Somers select(0, NULL, NULL, NULL, &t); 5781af29a6eSBrian Somers } 579565e35e5SBrian Somers } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle)); 580565e35e5SBrian Somers 581dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 582af57ed9fSAtsushi Murai } 583