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 * 209c81b87dSBrian Somers * $Id: main.c,v 1.130 1998/06/06 20:50:57 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai */ 242764b86aSBrian Somers 251384bd27SBrian Somers #include <sys/types.h> 26af57ed9fSAtsushi Murai #include <sys/socket.h> 2775240ed1SBrian Somers #include <netinet/in.h> 28a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 29a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 30565e35e5SBrian Somers #include <sys/un.h> 31e43ebac1SBrian Somers #include <net/if_tun.h> 3275240ed1SBrian Somers 3375240ed1SBrian Somers #include <errno.h> 3475240ed1SBrian Somers #include <fcntl.h> 3575240ed1SBrian Somers #include <paths.h> 3675240ed1SBrian Somers #include <signal.h> 3775240ed1SBrian Somers #include <stdio.h> 3875240ed1SBrian Somers #include <string.h> 3975240ed1SBrian Somers #include <sys/time.h> 4075240ed1SBrian Somers #include <termios.h> 4175240ed1SBrian Somers #include <unistd.h> 4275240ed1SBrian Somers 4375240ed1SBrian Somers #include "mbuf.h" 4475240ed1SBrian Somers #include "log.h" 4575240ed1SBrian Somers #include "defs.h" 465106c671SBrian Somers #include "id.h" 4775240ed1SBrian Somers #include "timer.h" 4875240ed1SBrian Somers #include "fsm.h" 49879ed6faSBrian Somers #include "lqr.h" 50af57ed9fSAtsushi Murai #include "hdlc.h" 51af57ed9fSAtsushi Murai #include "lcp.h" 520053cc58SBrian Somers #include "ccp.h" 5329e275ceSBrian Somers #include "iplist.h" 5429e275ceSBrian Somers #include "throughput.h" 55eaa4df37SBrian Somers #include "slcompress.h" 56af57ed9fSAtsushi Murai #include "ipcp.h" 5784b8a6ebSAtsushi Murai #include "filter.h" 582f786681SBrian Somers #include "descriptor.h" 593b0f8d2eSBrian Somers #include "link.h" 603b0f8d2eSBrian Somers #include "mp.h" 615828db6dSBrian Somers #include "bundle.h" 621ae349f5Scvs2svn #include "loadalias.h" 631ae349f5Scvs2svn #include "auth.h" 64ed6a16c1SPoul-Henning Kamp #include "systems.h" 65ed6a16c1SPoul-Henning Kamp #include "ip.h" 66f5ff0f7cSBrian Somers #include "sig.h" 6775240ed1SBrian Somers #include "main.h" 686a6b4bbbSBrian Somers #include "tun.h" 6977ff88adSBrian Somers #include "server.h" 7085b542cfSBrian Somers #include "prompt.h" 71b6dec9f0SBrian Somers #include "chat.h" 72e2ebb036SBrian Somers #include "chap.h" 733006ec67SBrian Somers #include "datalink.h" 7453c9f6c0SAtsushi Murai 7553c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 7653c9f6c0SAtsushi Murai #ifdef O_NDELAY 7753c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 7853c9f6c0SAtsushi Murai #endif 7953c9f6c0SAtsushi Murai #endif 80af57ed9fSAtsushi Murai 810f78c7a7SBrian Somers static void DoLoop(struct bundle *); 8275240ed1SBrian Somers static void TerminalStop(int); 83b6e82f33SBrian Somers static const char *ex_desc(int); 8475240ed1SBrian Somers 8583d1af55SBrian Somers static struct bundle *SignalBundle; 86b6217683SBrian Somers static struct prompt *SignalPrompt; 87c3899f8dSAtsushi Murai 88c3899f8dSAtsushi Murai void 89944f7098SBrian Somers Cleanup(int excode) 90af57ed9fSAtsushi Murai { 91a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 923006ec67SBrian Somers if (bundle_Phase(SignalBundle) != PHASE_DEAD) 939c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 946e4959f0SBrian Somers } 95af57ed9fSAtsushi Murai 961afedc4bSBrian Somers void 971afedc4bSBrian Somers AbortProgram(int excode) 981afedc4bSBrian Somers { 99dd7e2610SBrian Somers server_Close(SignalBundle); 100dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 1019c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 10268a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 103dd7e2610SBrian Somers log_Close(); 104af57ed9fSAtsushi Murai exit(excode); 105af57ed9fSAtsushi Murai } 106af57ed9fSAtsushi Murai 107af57ed9fSAtsushi Murai static void 108944f7098SBrian Somers CloseConnection(int signo) 109af57ed9fSAtsushi Murai { 110368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 111dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 112dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 1131bc9b5baSBrian Somers bundle_Down(SignalBundle); 114dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1156d14e2a8SJordan K. Hubbard } 116af57ed9fSAtsushi Murai 117af57ed9fSAtsushi Murai static void 118944f7098SBrian Somers CloseSession(int signo) 119af57ed9fSAtsushi Murai { 120dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 121af57ed9fSAtsushi Murai Cleanup(EX_TERM); 122af57ed9fSAtsushi Murai } 123c3899f8dSAtsushi Murai 12475b8d283SBrian Somers static pid_t BGPid = 0; 12575b8d283SBrian Somers 12675b8d283SBrian Somers static void 12775b8d283SBrian Somers KillChild(int signo) 12875b8d283SBrian Somers { 129dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 13075b8d283SBrian Somers kill(BGPid, SIGINT); 13175b8d283SBrian Somers } 13275b8d283SBrian Somers 133c3899f8dSAtsushi Murai static void 134b6e82f33SBrian Somers TerminalCont(int signo) 135c3899f8dSAtsushi Murai { 136f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 137f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 138c3899f8dSAtsushi Murai } 139c3899f8dSAtsushi Murai 140c3899f8dSAtsushi Murai static void 141944f7098SBrian Somers TerminalStop(int signo) 142c3899f8dSAtsushi Murai { 143f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 144f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 145f91ad6b0SBrian Somers raise(SIGSTOP); 1464ef16f24SBrian Somers } 1474ef16f24SBrian Somers 1488ea8442cSBrian Somers static void 1498ea8442cSBrian Somers BringDownServer(int signo) 1508ea8442cSBrian Somers { 151b6217683SBrian Somers /* Drops all child prompts too ! */ 152dd7e2610SBrian Somers server_Close(SignalBundle); 1538ea8442cSBrian Somers } 1548ea8442cSBrian Somers 155b6e82f33SBrian Somers static const char * 1566efd9292SBrian Somers ex_desc(int ex) 1576efd9292SBrian Somers { 1586efd9292SBrian Somers static char num[12]; 159b6e82f33SBrian Somers static const char *desc[] = { 160b6e82f33SBrian Somers "normal", "start", "sock", "modem", "dial", "dead", "done", 161b6e82f33SBrian Somers "reboot", "errdead", "hangup", "term", "nodial", "nologin" 162b6e82f33SBrian Somers }; 1636efd9292SBrian Somers 16470ee81ffSBrian Somers if (ex >= 0 && ex < sizeof desc / sizeof *desc) 1656efd9292SBrian Somers return desc[ex]; 1666efd9292SBrian Somers snprintf(num, sizeof num, "%d", ex); 1676efd9292SBrian Somers return num; 1686efd9292SBrian Somers } 169c3899f8dSAtsushi Murai 17075240ed1SBrian Somers static void 171b6e82f33SBrian Somers Usage(void) 172af57ed9fSAtsushi Murai { 173680026d6SNate Williams fprintf(stderr, 174b6e82f33SBrian Somers "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 175b6e82f33SBrian Somers #ifndef NOALIAS 176b6e82f33SBrian Somers " [ -alias ]" 177b6e82f33SBrian Somers #endif 178b6e82f33SBrian Somers " [system]\n"); 179af57ed9fSAtsushi Murai exit(EX_START); 180af57ed9fSAtsushi Murai } 181af57ed9fSAtsushi Murai 18239f94eddSBrian Somers static char * 183565e35e5SBrian Somers ProcessArgs(int argc, char **argv, int *mode) 184af57ed9fSAtsushi Murai { 18581358fa3SBrian Somers int optc, labelrequired, newmode; 186af57ed9fSAtsushi Murai char *cp; 187af57ed9fSAtsushi Murai 188565e35e5SBrian Somers optc = labelrequired = 0; 18981358fa3SBrian Somers *mode = PHYS_INTERACTIVE; 190af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 191af57ed9fSAtsushi Murai cp = *argv + 1; 19281358fa3SBrian Somers newmode = Nam2mode(cp); 19381358fa3SBrian Somers switch (newmode) { 19481358fa3SBrian Somers case PHYS_NONE: 19581358fa3SBrian Somers if (strcmp(cp, "alias") == 0) { 196565e35e5SBrian Somers #ifndef NOALIAS 197dd7e2610SBrian Somers if (alias_Load() != 0) 198b6e82f33SBrian Somers #endif 199dd7e2610SBrian Somers log_Printf(LogWARN, "Cannot load alias library\n"); 2001ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 201944f7098SBrian Somers } else 202af57ed9fSAtsushi Murai Usage(); 20381358fa3SBrian Somers break; 20481358fa3SBrian Somers 20581358fa3SBrian Somers case PHYS_ALL: 20681358fa3SBrian Somers Usage(); 20781358fa3SBrian Somers break; 20881358fa3SBrian Somers 20981358fa3SBrian Somers case PHYS_AUTO: 21081358fa3SBrian Somers case PHYS_BACKGROUND: 21181358fa3SBrian Somers case PHYS_DDIAL: 21281358fa3SBrian Somers labelrequired = 1; 21381358fa3SBrian Somers /* fall through */ 21481358fa3SBrian Somers 21581358fa3SBrian Somers default: 21681358fa3SBrian Somers *mode = newmode; 21781358fa3SBrian Somers } 218af57ed9fSAtsushi Murai optc++; 219944f7098SBrian Somers argv++; 220944f7098SBrian Somers argc--; 221af57ed9fSAtsushi Murai } 22281358fa3SBrian Somers 223af57ed9fSAtsushi Murai if (argc > 1) { 22485602e52SBrian Somers fprintf(stderr, "You may specify only one system label.\n"); 225af57ed9fSAtsushi Murai exit(EX_START); 226af57ed9fSAtsushi Murai } 227af57ed9fSAtsushi Murai 228af57ed9fSAtsushi Murai if (optc > 1) { 22985602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2301ae349f5Scvs2svn exit(EX_START); 2311ae349f5Scvs2svn } 2321ae349f5Scvs2svn 233565e35e5SBrian Somers if (labelrequired && argc != 1) { 234565e35e5SBrian Somers fprintf(stderr, "Destination system must be specified in" 235565e35e5SBrian Somers " auto, background or ddial mode.\n"); 236af57ed9fSAtsushi Murai exit(EX_START); 237af57ed9fSAtsushi Murai } 23839f94eddSBrian Somers 23939f94eddSBrian Somers return argc == 1 ? *argv : NULL; /* Don't SetLabel yet ! */ 240af57ed9fSAtsushi Murai } 241af57ed9fSAtsushi Murai 2424ef16f24SBrian Somers int 243944f7098SBrian Somers main(int argc, char **argv) 244af57ed9fSAtsushi Murai { 24539f94eddSBrian Somers char *name, *label; 246565e35e5SBrian Somers int nfds, mode; 2477a6f8720SBrian Somers struct bundle *bundle; 248b6217683SBrian Somers struct prompt *prompt; 249e3b4c400SBrian Somers 250e3b4c400SBrian Somers nfds = getdtablesize(); 251e3b4c400SBrian Somers if (nfds >= FD_SETSIZE) 252e3b4c400SBrian Somers /* 253e3b4c400SBrian Somers * If we've got loads of file descriptors, make sure they're all 254e3b4c400SBrian Somers * closed. If they aren't, we may end up with a seg fault when our 255e3b4c400SBrian Somers * `fd_set's get too big when select()ing ! 256e3b4c400SBrian Somers */ 257e3b4c400SBrian Somers while (--nfds > 2) 258e3b4c400SBrian Somers close(nfds); 259af57ed9fSAtsushi Murai 26075240ed1SBrian Somers name = strrchr(argv[0], '/'); 261dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 2622a279fedSBrian Somers 2638e7b8599SBrian Somers label = ProcessArgs(argc - 1, argv + 1, &mode); 26485b542cfSBrian Somers 26585b542cfSBrian Somers #ifdef __FreeBSD__ 26685b542cfSBrian Somers /* 26785b542cfSBrian Somers * A FreeBSD hack to dodge a bug in the tty driver that drops output 26885b542cfSBrian Somers * occasionally.... I must find the real reason some time. To display 26985b542cfSBrian Somers * the dodgy behaviour, comment out this bit, make yourself a large 27085b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 27185b542cfSBrian Somers * command will drop chunks of data !!! 27285b542cfSBrian Somers */ 27381358fa3SBrian Somers if (mode == PHYS_INTERACTIVE) { 27485b542cfSBrian Somers close(STDIN_FILENO); 27585b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 27685b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 27785b542cfSBrian Somers return 2; 27885b542cfSBrian Somers } 27985b542cfSBrian Somers } 28085b542cfSBrian Somers #endif 28185b542cfSBrian Somers 282b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 2836f384573SBrian Somers if (mode == PHYS_DIRECT) 284b6217683SBrian Somers prompt = NULL; 28585602e52SBrian Somers else { 286b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 28781358fa3SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(mode)); 28885602e52SBrian Somers } 28912ef29a8SBrian Somers 2905106c671SBrian Somers ID0init(); 2914562be74SBrian Somers if (ID0realuid() != 0) { 2924562be74SBrian Somers char conf[200], *ptr; 2934562be74SBrian Somers 2944562be74SBrian Somers snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 2954562be74SBrian Somers do { 2964562be74SBrian Somers if (!access(conf, W_OK)) { 297dd7e2610SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", conf); 2984562be74SBrian Somers return -1; 2994562be74SBrian Somers } 3004562be74SBrian Somers ptr = conf + strlen(conf)-2; 3014562be74SBrian Somers while (ptr > conf && *ptr != '/') 3024562be74SBrian Somers *ptr-- = '\0'; 3034562be74SBrian Somers } while (ptr >= conf); 3044562be74SBrian Somers } 3054562be74SBrian Somers 306dd7e2610SBrian Somers if (!system_IsValid(label, prompt, mode)) { 30712ef29a8SBrian Somers fprintf(stderr, "You may not use ppp in this mode with this label\n"); 3086f384573SBrian Somers if (mode == PHYS_DIRECT) { 309815624cfSBrian Somers const char *l; 31039f94eddSBrian Somers l = label ? label : "default"; 311dd7e2610SBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection\n", l); 312815624cfSBrian Somers } 313dd7e2610SBrian Somers log_Close(); 31412ef29a8SBrian Somers return 1; 31512ef29a8SBrian Somers } 31612ef29a8SBrian Somers 3178e7b8599SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, mode, (const char **)argv)) == NULL) { 318dd7e2610SBrian Somers log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno)); 3194ef16f24SBrian Somers return EX_START; 320af57ed9fSAtsushi Murai } 3210f2f3eb3SBrian Somers if (prompt) { 3220f2f3eb3SBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 3230f2f3eb3SBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->ifp.Name); 3240f2f3eb3SBrian Somers } 32583d1af55SBrian Somers SignalBundle = bundle; 32612ef29a8SBrian Somers 327dd7e2610SBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt) < 0) 328565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3291ae349f5Scvs2svn 330dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 331dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 332dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 333dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 334dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 335e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 336565e35e5SBrian Somers 33781358fa3SBrian Somers if (mode == PHYS_INTERACTIVE) 338dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 339f91ad6b0SBrian Somers 340dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 341af57ed9fSAtsushi Murai 34239f94eddSBrian Somers if (label) { 34339f94eddSBrian Somers /* 344dd7e2610SBrian Somers * Set label both before and after system_Select ! 345dd7e2610SBrian Somers * This way, "set enddisc label" works during system_Select, and we 34649052c95SBrian Somers * also end up with the correct label if we have embedded load 34749052c95SBrian Somers * commands. 34839f94eddSBrian Somers */ 34949052c95SBrian Somers bundle_SetLabel(bundle, label); 350dd7e2610SBrian Somers if (system_Select(bundle, label, CONFFILE, prompt) < 0) { 351b6217683SBrian Somers prompt_Printf(prompt, "Destination system (%s) not found.\n", label); 3528390b576SBrian Somers AbortProgram(EX_START); 3531ae349f5Scvs2svn } 35449052c95SBrian Somers bundle_SetLabel(bundle, label); 35581358fa3SBrian Somers if (mode == PHYS_AUTO && 3565828db6dSBrian Somers bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 357565e35e5SBrian Somers prompt_Printf(prompt, "You must \"set ifaddr\" with a peer address " 358565e35e5SBrian Somers "in label %s for auto mode.\n", label); 3598390b576SBrian Somers AbortProgram(EX_START); 360af57ed9fSAtsushi Murai } 361af57ed9fSAtsushi Murai } 3626efd9292SBrian Somers 36381358fa3SBrian Somers if (mode != PHYS_INTERACTIVE) { 3646f384573SBrian Somers if (mode != PHYS_DIRECT) { 3655cf4388bSBrian Somers int bgpipe[2]; 3666d14e2a8SJordan K. Hubbard pid_t bgpid; 367a9c6b5dfSAtsushi Murai 36881358fa3SBrian Somers if (mode == PHYS_BACKGROUND && pipe(bgpipe)) { 369dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 3708390b576SBrian Somers AbortProgram(EX_SOCK); 3711ae349f5Scvs2svn } 3721ae349f5Scvs2svn 3736d14e2a8SJordan K. Hubbard bgpid = fork(); 3746d14e2a8SJordan K. Hubbard if (bgpid == -1) { 375dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 3768390b576SBrian Somers AbortProgram(EX_SOCK); 3776d14e2a8SJordan K. Hubbard } 3785cf4388bSBrian Somers 3796d14e2a8SJordan K. Hubbard if (bgpid) { 3806d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 381a9c6b5dfSAtsushi Murai 38281358fa3SBrian Somers if (mode == PHYS_BACKGROUND) { 3835cf4388bSBrian Somers close(bgpipe[1]); 3846d14e2a8SJordan K. Hubbard BGPid = bgpid; 38575b8d283SBrian Somers /* If we get a signal, kill the child */ 38675b8d283SBrian Somers signal(SIGHUP, KillChild); 38775b8d283SBrian Somers signal(SIGTERM, KillChild); 38875b8d283SBrian Somers signal(SIGINT, KillChild); 38975b8d283SBrian Somers signal(SIGQUIT, KillChild); 39075b8d283SBrian Somers 39175b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 3925cf4388bSBrian Somers if (read(bgpipe[0], &c, 1) != 1) { 393b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 394dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 3956efd9292SBrian Somers } else if (c == EX_NORMAL) { 396b6217683SBrian Somers prompt_Printf(prompt, "PPP enabled.\n"); 397dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled.\n"); 3986efd9292SBrian Somers } else { 399b6217683SBrian Somers prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c)); 400dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s).\n", 40180e37c72SBrian Somers ex_desc((int) c)); 4026efd9292SBrian Somers } 4035cf4388bSBrian Somers close(bgpipe[0]); 4046d14e2a8SJordan K. Hubbard } 4054ef16f24SBrian Somers return c; 40681358fa3SBrian Somers } else if (mode == PHYS_BACKGROUND) { 4075cf4388bSBrian Somers close(bgpipe[0]); 4085cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 409aefd026aSBrian Somers } 410aefd026aSBrian Somers 411da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 412da66dd13SBrian Somers 413565e35e5SBrian Somers /* -auto, -dedicated, -ddial & -background */ 414b6217683SBrian Somers prompt_Destroy(prompt, 0); 4152a279fedSBrian Somers close(STDOUT_FILENO); 4162a279fedSBrian Somers close(STDERR_FILENO); 4172a279fedSBrian Somers close(STDIN_FILENO); 418b6217683SBrian Somers setsid(); 419565e35e5SBrian Somers } else { 420565e35e5SBrian Somers /* -direct: STDIN_FILENO gets used by modem_Open */ 421565e35e5SBrian Somers prompt_TtyInit(NULL); 422565e35e5SBrian Somers close(STDOUT_FILENO); 423565e35e5SBrian Somers close(STDERR_FILENO); 424d656a4c5SBrian Somers } 425af57ed9fSAtsushi Murai } else { 426565e35e5SBrian Somers /* Interactive mode */ 4272a279fedSBrian Somers close(STDERR_FILENO); 428565e35e5SBrian Somers prompt_TtyInit(prompt); 429b6217683SBrian Somers prompt_TtyCommandMode(prompt); 430b6217683SBrian Somers prompt_Required(prompt); 431af57ed9fSAtsushi Murai } 43235495becSBrian Somers 433dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); 4340f78c7a7SBrian Somers DoLoop(bundle); 4351afedc4bSBrian Somers AbortProgram(EX_NORMAL); 436af57ed9fSAtsushi Murai 4371afedc4bSBrian Somers return EX_NORMAL; 438af57ed9fSAtsushi Murai } 439af57ed9fSAtsushi Murai 440af57ed9fSAtsushi Murai static void 4410f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 442af57ed9fSAtsushi Murai { 443af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 444078c562eSBrian Somers int i, nfds; 445c3899f8dSAtsushi Murai 446565e35e5SBrian Somers do { 447780700e5SAndrey A. Chernov nfds = 0; 448944f7098SBrian Somers FD_ZERO(&rfds); 449944f7098SBrian Somers FD_ZERO(&wfds); 450944f7098SBrian Somers FD_ZERO(&efds); 45184b8a6ebSAtsushi Murai 4520f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 4536f384573SBrian Somers descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds); 4540f2f3eb3SBrian Somers 4550f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 4560f2f3eb3SBrian Somers descriptor_UpdateSet(&server.desc, &rfds, NULL, NULL, &nfds); 45707030d97SBrian Somers 4583b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 459f4768038SBrian Somers /* Don't select - we'll be here forever */ 460f4768038SBrian Somers break; 4610706ff38SBrian Somers 4623006ec67SBrian Somers i = select(nfds, &rfds, &wfds, &efds, NULL); 463712ae387SBrian Somers 46454cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 465dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 46624989c68SBrian Somers if (log_IsKept(LogTIMER)) { 46724989c68SBrian Somers struct timeval t; 46824989c68SBrian Somers 46924989c68SBrian Somers for (i = 0; i <= nfds; i++) { 47024989c68SBrian Somers if (FD_ISSET(i, &rfds)) { 47124989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 47224989c68SBrian Somers FD_CLR(i, &rfds); 47324989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 47424989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 47524989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 476af57ed9fSAtsushi Murai break; 477af57ed9fSAtsushi Murai } 47824989c68SBrian Somers } 47924989c68SBrian Somers if (FD_ISSET(i, &wfds)) { 48024989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 48124989c68SBrian Somers FD_CLR(i, &wfds); 48224989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 48324989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 48424989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 485af57ed9fSAtsushi Murai break; 486af57ed9fSAtsushi Murai } 487e0d3e233SAndrey A. Chernov } 48824989c68SBrian Somers if (FD_ISSET(i, &efds)) { 48924989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 49024989c68SBrian Somers FD_CLR(i, &efds); 49124989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 49224989c68SBrian Somers if (select(nfds, &rfds, &wfds, &efds, &t) != -1) { 49324989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 49458f264e1SBrian Somers break; 49558f264e1SBrian Somers } 49624989c68SBrian Somers } 49724989c68SBrian Somers } 49824989c68SBrian Somers } 49958f264e1SBrian Somers break; 500de451c68SBrian Somers } 501de451c68SBrian Somers 50254cd8e13SBrian Somers sig_Handle(); 50354cd8e13SBrian Somers 50454cd8e13SBrian Somers if (i <= 0) 50554cd8e13SBrian Somers continue; 50654cd8e13SBrian Somers 5073006ec67SBrian Somers for (i = 0; i <= nfds; i++) 5083006ec67SBrian Somers if (FD_ISSET(i, &efds)) { 509dd7e2610SBrian Somers log_Printf(LogALERT, "Exception detected on descriptor %d\n", i); 5101ae349f5Scvs2svn break; 5111ae349f5Scvs2svn } 512c60f92caSBrian Somers 513b7c5748eSBrian Somers if (i <= nfds) 514b7c5748eSBrian Somers break; 515b7c5748eSBrian Somers 51677ff88adSBrian Somers if (descriptor_IsSet(&server.desc, &rfds)) 517b77776a7SBrian Somers descriptor_Read(&server.desc, bundle, &rfds); 51842d4d396SBrian Somers 5192f786681SBrian Somers if (descriptor_IsSet(&bundle->desc, &wfds)) 5202f786681SBrian Somers descriptor_Write(&bundle->desc, bundle, &wfds); 5212f786681SBrian Somers 5222f786681SBrian Somers if (descriptor_IsSet(&bundle->desc, &rfds)) 5232f786681SBrian Somers descriptor_Read(&bundle->desc, bundle, &rfds); 52454cd8e13SBrian Somers 525565e35e5SBrian Somers } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle)); 526565e35e5SBrian Somers 527dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 528af57ed9fSAtsushi Murai } 529