165309e5cSBrian Somers /*- 265309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 365309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 465309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 565309e5cSBrian Somers * All rights reserved. 6af57ed9fSAtsushi Murai * 765309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 865309e5cSBrian Somers * modification, are permitted provided that the following conditions 965309e5cSBrian Somers * are met: 1065309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1165309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1265309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1465309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 15af57ed9fSAtsushi Murai * 1665309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1765309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1865309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1965309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2065309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2165309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2265309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2365309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2465309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2565309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2665309e5cSBrian Somers * SUCH DAMAGE. 27af57ed9fSAtsushi Murai * 2897d92980SPeter Wemm * $FreeBSD$ 29af57ed9fSAtsushi Murai */ 302764b86aSBrian Somers 31972a1bcfSBrian Somers #include <sys/param.h> 3275240ed1SBrian Somers #include <netinet/in.h> 33a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 34a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 35565e35e5SBrian Somers #include <sys/un.h> 366b457978SBrian Somers #include <sys/socket.h> 376b457978SBrian Somers #include <net/route.h> 3875240ed1SBrian Somers 3975240ed1SBrian Somers #include <errno.h> 4075240ed1SBrian Somers #include <fcntl.h> 4175240ed1SBrian Somers #include <paths.h> 4275240ed1SBrian Somers #include <signal.h> 436eafd353SBrian Somers #include <stdarg.h> 4475240ed1SBrian Somers #include <stdio.h> 45c0593e34SBrian Somers #include <stdlib.h> 4675240ed1SBrian Somers #include <string.h> 47b08bf2deSBrian Somers #include <sys/time.h> 4875240ed1SBrian Somers #include <termios.h> 4975240ed1SBrian Somers #include <unistd.h> 501080ea25SBrian Somers #include <sys/stat.h> 5175240ed1SBrian Somers 5267b072f7SBrian Somers #ifndef NONAT 5310e629b9SBrian Somers #ifdef LOCALNAT 547884358fSBrian Somers #include "alias.h" 5510e629b9SBrian Somers #else 5610e629b9SBrian Somers #include <alias.h> 571595bacdSBrian Somers #endif 581595bacdSBrian Somers #endif 5910e629b9SBrian Somers 605d9e6103SBrian Somers #include "layer.h" 611af29a6eSBrian Somers #include "probe.h" 6275240ed1SBrian Somers #include "mbuf.h" 6375240ed1SBrian Somers #include "log.h" 6475240ed1SBrian Somers #include "defs.h" 655106c671SBrian Somers #include "id.h" 6675240ed1SBrian Somers #include "timer.h" 6775240ed1SBrian Somers #include "fsm.h" 68879ed6faSBrian Somers #include "lqr.h" 69af57ed9fSAtsushi Murai #include "hdlc.h" 70af57ed9fSAtsushi Murai #include "lcp.h" 710053cc58SBrian Somers #include "ccp.h" 7229e275ceSBrian Somers #include "iplist.h" 7329e275ceSBrian Somers #include "throughput.h" 74eaa4df37SBrian Somers #include "slcompress.h" 7530949fd4SBrian Somers #include "ncpaddr.h" 76af57ed9fSAtsushi Murai #include "ipcp.h" 7784b8a6ebSAtsushi Murai #include "filter.h" 782f786681SBrian Somers #include "descriptor.h" 793b0f8d2eSBrian Somers #include "link.h" 803b0f8d2eSBrian Somers #include "mp.h" 81972a1bcfSBrian Somers #ifndef NORADIUS 82972a1bcfSBrian Somers #include "radius.h" 83972a1bcfSBrian Somers #endif 8430949fd4SBrian Somers #include "ipv6cp.h" 8530949fd4SBrian Somers #include "ncp.h" 865828db6dSBrian Somers #include "bundle.h" 871ae349f5Scvs2svn #include "auth.h" 88ed6a16c1SPoul-Henning Kamp #include "systems.h" 89f5ff0f7cSBrian Somers #include "sig.h" 9075240ed1SBrian Somers #include "main.h" 9177ff88adSBrian Somers #include "server.h" 9285b542cfSBrian Somers #include "prompt.h" 93b6dec9f0SBrian Somers #include "chat.h" 94e2ebb036SBrian Somers #include "chap.h" 9592b09558SBrian Somers #include "cbcp.h" 963006ec67SBrian Somers #include "datalink.h" 978fa6ebe4SBrian Somers #include "iface.h" 9853c9f6c0SAtsushi Murai 9953c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 10053c9f6c0SAtsushi Murai #ifdef O_NDELAY 10153c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 10253c9f6c0SAtsushi Murai #endif 10353c9f6c0SAtsushi Murai #endif 104af57ed9fSAtsushi Murai 1050f78c7a7SBrian Somers static void DoLoop(struct bundle *); 10675240ed1SBrian Somers static void TerminalStop(int); 10775240ed1SBrian Somers 10883d1af55SBrian Somers static struct bundle *SignalBundle; 109b6217683SBrian Somers static struct prompt *SignalPrompt; 110c3899f8dSAtsushi Murai 111c3899f8dSAtsushi Murai void 112057f1760SBrian Somers Cleanup() 113af57ed9fSAtsushi Murai { 114a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 1159c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 1166e4959f0SBrian Somers } 117af57ed9fSAtsushi Murai 1181afedc4bSBrian Somers void 1191afedc4bSBrian Somers AbortProgram(int excode) 1201afedc4bSBrian Somers { 12123ddebe2SBrian Somers if (SignalBundle) 122dd7e2610SBrian Somers server_Close(SignalBundle); 123dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 12423ddebe2SBrian Somers if (SignalBundle) { 1259c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 12668a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 12723ddebe2SBrian Somers } 128dd7e2610SBrian Somers log_Close(); 129af57ed9fSAtsushi Murai exit(excode); 130af57ed9fSAtsushi Murai } 131af57ed9fSAtsushi Murai 132af57ed9fSAtsushi Murai static void 133944f7098SBrian Somers CloseConnection(int signo) 134af57ed9fSAtsushi Murai { 135368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 136dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 137dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 138899011c4SBrian Somers bundle_Down(SignalBundle, CLOSE_STAYDOWN); 139dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1406d14e2a8SJordan K. Hubbard } 141af57ed9fSAtsushi Murai 142af57ed9fSAtsushi Murai static void 143944f7098SBrian Somers CloseSession(int signo) 144af57ed9fSAtsushi Murai { 145dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 146057f1760SBrian Somers Cleanup(); 147af57ed9fSAtsushi Murai } 148c3899f8dSAtsushi Murai 14975b8d283SBrian Somers static pid_t BGPid = 0; 15075b8d283SBrian Somers 15175b8d283SBrian Somers static void 15275b8d283SBrian Somers KillChild(int signo) 15375b8d283SBrian Somers { 154ac37ab22SBrian Somers signal(signo, SIG_IGN); 155dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 15675b8d283SBrian Somers kill(BGPid, SIGINT); 15775b8d283SBrian Somers } 15875b8d283SBrian Somers 159c3899f8dSAtsushi Murai static void 160057f1760SBrian Somers TerminalCont(int signo __unused) 161c3899f8dSAtsushi Murai { 162f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 163f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 164c3899f8dSAtsushi Murai } 165c3899f8dSAtsushi Murai 166c3899f8dSAtsushi Murai static void 167057f1760SBrian Somers TerminalStop(int signo __unused) 168c3899f8dSAtsushi Murai { 169f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 170f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 171f91ad6b0SBrian Somers raise(SIGSTOP); 1724ef16f24SBrian Somers } 1734ef16f24SBrian Somers 1748ea8442cSBrian Somers static void 175057f1760SBrian Somers BringDownServer(int signo __unused) 1768ea8442cSBrian Somers { 177b6217683SBrian Somers /* Drops all child prompts too ! */ 17874457d3dSBrian Somers if (server_Close(SignalBundle)) 17974457d3dSBrian Somers log_Printf(LogPHASE, "Closed server socket\n"); 18074457d3dSBrian Somers } 18174457d3dSBrian Somers 18274457d3dSBrian Somers static void 183057f1760SBrian Somers RestartServer(int signo __unused) 18474457d3dSBrian Somers { 18574457d3dSBrian Somers /* Drops all child prompts and re-opens the socket */ 18674457d3dSBrian Somers server_Reopen(SignalBundle); 1878ea8442cSBrian Somers } 1888ea8442cSBrian Somers 18975240ed1SBrian Somers static void 190b6e82f33SBrian Somers Usage(void) 191af57ed9fSAtsushi Murai { 192d3974088SDag-Erling Smørgrav fprintf(stderr, "usage: ppp [-auto | -foreground | -background | -direct |" 1939b996792SBrian Somers " -dedicated | -ddial | -interactive]" 194b6e82f33SBrian Somers #ifndef NOALIAS 19567b072f7SBrian Somers " [-nat]" 196b6e82f33SBrian Somers #endif 197c0593e34SBrian Somers " [-quiet] [-unit N] [system ...]\n"); 198af57ed9fSAtsushi Murai exit(EX_START); 199af57ed9fSAtsushi Murai } 200af57ed9fSAtsushi Murai 201c0593e34SBrian Somers struct switches { 202c0593e34SBrian Somers unsigned nat : 1; 203c0593e34SBrian Somers unsigned fg : 1; 204c0593e34SBrian Somers unsigned quiet : 1; 205c0593e34SBrian Somers int mode; 206c0593e34SBrian Somers int unit; 207c0593e34SBrian Somers }; 208c0593e34SBrian Somers 2097cf368ebSBrian Somers static int 210c0593e34SBrian Somers ProcessArgs(int argc, char **argv, struct switches *sw) 211af57ed9fSAtsushi Murai { 2127cf368ebSBrian Somers int optc, newmode, arg; 213af57ed9fSAtsushi Murai char *cp; 214af57ed9fSAtsushi Murai 2157cf368ebSBrian Somers optc = 0; 216c0593e34SBrian Somers memset(sw, '\0', sizeof *sw); 217c0593e34SBrian Somers sw->mode = PHYS_INTERACTIVE; 218c0593e34SBrian Somers sw->unit = -1; 219c0593e34SBrian Somers 2207cf368ebSBrian Somers for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 2217cf368ebSBrian Somers cp = argv[arg] + 1; 22281358fa3SBrian Somers newmode = Nam2mode(cp); 22381358fa3SBrian Somers switch (newmode) { 22481358fa3SBrian Somers case PHYS_NONE: 225c0593e34SBrian Somers if (strcmp(cp, "nat") == 0) { 22667b072f7SBrian Somers #ifdef NONAT 227c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 228615ad4f9SBrian Somers #else 229c0593e34SBrian Somers sw->nat = 1; 230615ad4f9SBrian Somers #endif 2311ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 232c0593e34SBrian Somers } else if (strcmp(cp, "alias") == 0) { 233c0593e34SBrian Somers #ifdef NONAT 234c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 235c0593e34SBrian Somers fprintf(stderr, "%s ignored: NAT is compiled out\n", argv[arg]); 236c0593e34SBrian Somers #else 237886530abSBrian Somers log_Printf(LogWARN, "%s is deprecated\n", argv[arg]); 238886530abSBrian Somers fprintf(stderr, "%s is deprecated\n", argv[arg]); 239c0593e34SBrian Somers sw->nat = 1; 240c0593e34SBrian Somers #endif 241c0593e34SBrian Somers optc--; /* this option isn't exclusive */ 242c0593e34SBrian Somers } else if (strncmp(cp, "unit", 4) == 0) { 2439d06928dSBrian Somers optc--; /* this option isn't exclusive */ 244c0593e34SBrian Somers if (cp[4] == '\0') { 2459d06928dSBrian Somers optc--; /* nor is the argument */ 246c0593e34SBrian Somers if (++arg == argc) { 247c0593e34SBrian Somers fprintf(stderr, "-unit: Expected unit number\n"); 248c0593e34SBrian Somers Usage(); 249c0593e34SBrian Somers } else 250c0593e34SBrian Somers sw->unit = atoi(argv[arg]); 251c0593e34SBrian Somers } else 252c0593e34SBrian Somers sw->unit = atoi(cp + 4); 25367b072f7SBrian Somers } else if (strcmp(cp, "quiet") == 0) { 254c0593e34SBrian Somers sw->quiet = 1; 25567b072f7SBrian Somers optc--; /* this option isn't exclusive */ 256944f7098SBrian Somers } else 257af57ed9fSAtsushi Murai Usage(); 25881358fa3SBrian Somers break; 25981358fa3SBrian Somers 26081358fa3SBrian Somers case PHYS_ALL: 26181358fa3SBrian Somers Usage(); 26281358fa3SBrian Somers break; 26381358fa3SBrian Somers 26481358fa3SBrian Somers default: 265c0593e34SBrian Somers sw->mode = newmode; 266f6a4e748SBrian Somers if (newmode == PHYS_FOREGROUND) 267f6a4e748SBrian Somers sw->fg = 1; 26881358fa3SBrian Somers } 269af57ed9fSAtsushi Murai } 270af57ed9fSAtsushi Murai 271af57ed9fSAtsushi Murai if (optc > 1) { 27285602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2731ae349f5Scvs2svn exit(EX_START); 2741ae349f5Scvs2svn } 2751ae349f5Scvs2svn 276c0593e34SBrian Somers if (sw->mode == PHYS_AUTO && arg == argc) { 2777cf368ebSBrian Somers fprintf(stderr, "A system must be specified in auto mode.\n"); 278af57ed9fSAtsushi Murai exit(EX_START); 279af57ed9fSAtsushi Murai } 28039f94eddSBrian Somers 2817cf368ebSBrian Somers return arg; /* Don't SetLabel yet ! */ 282af57ed9fSAtsushi Murai } 283af57ed9fSAtsushi Murai 2847cf368ebSBrian Somers static void 2857cf368ebSBrian Somers CheckLabel(const char *label, struct prompt *prompt, int mode) 2867cf368ebSBrian Somers { 2877cf368ebSBrian Somers const char *err; 2887cf368ebSBrian Somers 2897cf368ebSBrian Somers if ((err = system_IsValid(label, prompt, mode)) != NULL) { 2907cf368ebSBrian Somers fprintf(stderr, "%s: %s\n", label, err); 2917cf368ebSBrian Somers if (mode == PHYS_DIRECT) 2927cf368ebSBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 2937cf368ebSBrian Somers label, err); 2947cf368ebSBrian Somers log_Close(); 2957cf368ebSBrian Somers exit(1); 2967cf368ebSBrian Somers } 2977cf368ebSBrian Somers } 2987cf368ebSBrian Somers 2997cf368ebSBrian Somers 3004ef16f24SBrian Somers int 301944f7098SBrian Somers main(int argc, char **argv) 302af57ed9fSAtsushi Murai { 3037cf368ebSBrian Somers char *name; 304756783fcSBrian Somers const char *lastlabel; 305057f1760SBrian Somers int arg, holdfd[3], label; 306057f1760SBrian Somers unsigned f; 3077a6f8720SBrian Somers struct bundle *bundle; 308b6217683SBrian Somers struct prompt *prompt; 309c0593e34SBrian Somers struct switches sw; 310e3b4c400SBrian Somers 311971abb29SBrian Somers probe_Init(); 312971abb29SBrian Somers 313108e336aSBrian Somers /* 314108e336aSBrian Somers * We open 3 descriptors to ensure that STDIN_FILENO, STDOUT_FILENO and 315108e336aSBrian Somers * STDERR_FILENO are always open. These are closed before DoLoop(), 316108e336aSBrian Somers * but *after* we've avoided the possibility of erroneously closing 317108e336aSBrian Somers * an important descriptor with close(STD{IN,OUT,ERR}_FILENO). 318108e336aSBrian Somers */ 319108e336aSBrian Somers if ((holdfd[0] = open(_PATH_DEVNULL, O_RDWR)) == -1) { 320108e336aSBrian Somers fprintf(stderr, "Cannot open %s !\n", _PATH_DEVNULL); 321108e336aSBrian Somers return 2; 322108e336aSBrian Somers } 323108e336aSBrian Somers for (f = 1; f < sizeof holdfd / sizeof *holdfd; f++) 324dd1a52b9SBrian Somers holdfd[f] = dup(holdfd[0]); 325108e336aSBrian Somers 32675240ed1SBrian Somers name = strrchr(argv[0], '/'); 327dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 3282a279fedSBrian Somers 32967b072f7SBrian Somers #ifndef NONAT 3302a630835SBrian Somers PacketAliasInit(); 3312a630835SBrian Somers #endif 332c0593e34SBrian Somers label = ProcessArgs(argc, argv, &sw); 33385b542cfSBrian Somers 33485b542cfSBrian Somers /* 335a611383fSBrian Somers * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 336a611383fSBrian Somers * output occasionally.... I must find the real reason some time. To 337a611383fSBrian Somers * display the dodgy behaviour, comment out this bit, make yourself a large 33885b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 33985b542cfSBrian Somers * command will drop chunks of data !!! 34085b542cfSBrian Somers */ 341c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) { 34285b542cfSBrian Somers close(STDIN_FILENO); 34385b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 34485b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 34585b542cfSBrian Somers return 2; 34685b542cfSBrian Somers } 34785b542cfSBrian Somers } 34885b542cfSBrian Somers 349b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 350c0593e34SBrian Somers if (sw.mode == PHYS_DIRECT) 351b6217683SBrian Somers prompt = NULL; 352ed0e9269SBrian Somers else 353b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 35412ef29a8SBrian Somers 3555106c671SBrian Somers ID0init(); 3564562be74SBrian Somers if (ID0realuid() != 0) { 3574562be74SBrian Somers char conf[200], *ptr; 3584562be74SBrian Somers 3597a66a36dSBrian Somers snprintf(conf, sizeof conf, "%s/%s", PPP_CONFDIR, CONFFILE); 3604562be74SBrian Somers do { 3611080ea25SBrian Somers struct stat sb; 3621080ea25SBrian Somers 3631080ea25SBrian Somers if (stat(conf, &sb) == 0 && sb.st_mode & S_IWOTH) { 364a33b2ef7SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 365a33b2ef7SBrian Somers conf); 3664562be74SBrian Somers return -1; 3674562be74SBrian Somers } 3684562be74SBrian Somers ptr = conf + strlen(conf)-2; 3694562be74SBrian Somers while (ptr > conf && *ptr != '/') 3704562be74SBrian Somers *ptr-- = '\0'; 3714562be74SBrian Somers } while (ptr >= conf); 3724562be74SBrian Somers } 3734562be74SBrian Somers 3747cf368ebSBrian Somers if (label < argc) 3757cf368ebSBrian Somers for (arg = label; arg < argc; arg++) 376c0593e34SBrian Somers CheckLabel(argv[arg], prompt, sw.mode); 3777cf368ebSBrian Somers else 378c0593e34SBrian Somers CheckLabel("default", prompt, sw.mode); 37912ef29a8SBrian Somers 380c0593e34SBrian Somers if (!sw.quiet) 381c0593e34SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(sw.mode)); 382ed0e9269SBrian Somers 383cf0a3940SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, sw.mode, sw.unit)) == NULL) 3844ef16f24SBrian Somers return EX_START; 385756783fcSBrian Somers 386756783fcSBrian Somers /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 387756783fcSBrian Somers 3880f2f3eb3SBrian Somers if (prompt) { 3890f2f3eb3SBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 390c0593e34SBrian Somers if (!sw.quiet) 3918fa6ebe4SBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 3920f2f3eb3SBrian Somers } 39383d1af55SBrian Somers SignalBundle = bundle; 394c0593e34SBrian Somers bundle->NatEnabled = sw.nat; 395c0593e34SBrian Somers if (sw.nat) 3960508c09aSBrian Somers opt_enable(bundle, OPT_IFACEALIAS); 39712ef29a8SBrian Somers 39830291ffbSBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 399565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 4001ae349f5Scvs2svn 401dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 402dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 403dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 404dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 405dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 406e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 407565e35e5SBrian Somers 408c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) 409dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 410f91ad6b0SBrian Somers 41174457d3dSBrian Somers sig_signal(SIGUSR1, RestartServer); 412dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 413af57ed9fSAtsushi Murai 414cf0a3940SBrian Somers lastlabel = argv[argc - 1]; 4157cf368ebSBrian Somers for (arg = label; arg < argc; arg++) { 4167cf368ebSBrian Somers /* In case we use LABEL or ``set enddisc label'' */ 417756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 418cf0a3940SBrian Somers system_Select(bundle, argv[arg], CONFFILE, prompt, NULL); 4191ae349f5Scvs2svn } 4207cf368ebSBrian Somers 4217cf368ebSBrian Somers if (label < argc) 4227cf368ebSBrian Somers /* In case the last label did a ``load'' */ 423756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 4247cf368ebSBrian Somers 425c0593e34SBrian Somers if (sw.mode == PHYS_AUTO && 42630949fd4SBrian Somers ncprange_family(&bundle->ncp.ipcp.cfg.peer_range) == AF_UNSPEC) { 4277cf368ebSBrian Somers prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 4287cf368ebSBrian Somers "in auto mode.\n"); 4298390b576SBrian Somers AbortProgram(EX_START); 430af57ed9fSAtsushi Murai } 4316efd9292SBrian Somers 432c0593e34SBrian Somers if (sw.mode != PHYS_INTERACTIVE) { 433c0593e34SBrian Somers if (sw.mode != PHYS_DIRECT) { 434c0593e34SBrian Somers if (!sw.fg) { 4355cf4388bSBrian Somers int bgpipe[2]; 4366d14e2a8SJordan K. Hubbard pid_t bgpid; 437a9c6b5dfSAtsushi Murai 438c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND && pipe(bgpipe)) { 439dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 4408390b576SBrian Somers AbortProgram(EX_SOCK); 4411ae349f5Scvs2svn } 4421ae349f5Scvs2svn 4436d14e2a8SJordan K. Hubbard bgpid = fork(); 4446d14e2a8SJordan K. Hubbard if (bgpid == -1) { 445dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 4468390b576SBrian Somers AbortProgram(EX_SOCK); 4476d14e2a8SJordan K. Hubbard } 4485cf4388bSBrian Somers 4496d14e2a8SJordan K. Hubbard if (bgpid) { 4506d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 451b42135deSBrian Somers int ret; 452a9c6b5dfSAtsushi Murai 453c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND) { 4545cf4388bSBrian Somers close(bgpipe[1]); 4556d14e2a8SJordan K. Hubbard BGPid = bgpid; 45675b8d283SBrian Somers /* If we get a signal, kill the child */ 45775b8d283SBrian Somers signal(SIGHUP, KillChild); 45875b8d283SBrian Somers signal(SIGTERM, KillChild); 45975b8d283SBrian Somers signal(SIGINT, KillChild); 46075b8d283SBrian Somers signal(SIGQUIT, KillChild); 46175b8d283SBrian Somers 46275b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 463b42135deSBrian Somers while ((ret = read(bgpipe[0], &c, 1)) == 1) { 464b42135deSBrian Somers switch (c) { 465b42135deSBrian Somers case EX_NORMAL: 4660fea4ed0SBrian Somers if (!sw.quiet) { 467b42135deSBrian Somers prompt_Printf(prompt, "PPP enabled\n"); 468b42135deSBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled\n"); 4690fea4ed0SBrian Somers } 4709bf01bcbSBrian Somers break; 471b42135deSBrian Somers case EX_REDIAL: 472b42135deSBrian Somers if (!sw.quiet) 473b42135deSBrian Somers prompt_Printf(prompt, "Attempting redial\n"); 474b42135deSBrian Somers continue; 475b42135deSBrian Somers case EX_RECONNECT: 476b42135deSBrian Somers if (!sw.quiet) 477b42135deSBrian Somers prompt_Printf(prompt, "Attempting reconnect\n"); 478b42135deSBrian Somers continue; 479b42135deSBrian Somers default: 480b42135deSBrian Somers prompt_Printf(prompt, "Child failed (%s)\n", 481b42135deSBrian Somers ex_desc((int)c)); 482b42135deSBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s)\n", 483b42135deSBrian Somers ex_desc((int) c)); 484b42135deSBrian Somers } 485b42135deSBrian Somers break; 486b42135deSBrian Somers } 487b42135deSBrian Somers if (ret != 1) { 488b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 489dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4906efd9292SBrian Somers } 4915cf4388bSBrian Somers close(bgpipe[0]); 4926d14e2a8SJordan K. Hubbard } 4934ef16f24SBrian Somers return c; 494c0593e34SBrian Somers } else if (sw.mode == PHYS_BACKGROUND) { 4955cf4388bSBrian Somers close(bgpipe[0]); 4965cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 497aefd026aSBrian Somers } 498aefd026aSBrian Somers 49906b47306SBrian Somers bundle_ChangedPID(bundle); 500da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 50167b072f7SBrian Somers } 502da66dd13SBrian Somers 50367b072f7SBrian Somers /* -auto, -dedicated, -ddial, -foreground & -background */ 504b6217683SBrian Somers prompt_Destroy(prompt, 0); 5052a279fedSBrian Somers close(STDOUT_FILENO); 5062a279fedSBrian Somers close(STDERR_FILENO); 5072a279fedSBrian Somers close(STDIN_FILENO); 508c0593e34SBrian Somers if (!sw.fg) 509b6217683SBrian Somers setsid(); 510565e35e5SBrian Somers } else { 51167b072f7SBrian Somers /* -direct - STDIN_FILENO gets used by physical_Open */ 512565e35e5SBrian Somers prompt_TtyInit(NULL); 513565e35e5SBrian Somers close(STDOUT_FILENO); 514565e35e5SBrian Somers close(STDERR_FILENO); 515d656a4c5SBrian Somers } 516af57ed9fSAtsushi Murai } else { 51767b072f7SBrian Somers /* -interactive */ 5182a279fedSBrian Somers close(STDERR_FILENO); 519565e35e5SBrian Somers prompt_TtyInit(prompt); 520b6217683SBrian Somers prompt_TtyCommandMode(prompt); 521b6217683SBrian Somers prompt_Required(prompt); 522af57ed9fSAtsushi Murai } 52335495becSBrian Somers 524108e336aSBrian Somers /* We can get rid of these now */ 525108e336aSBrian Somers for (f = 0; f < sizeof holdfd / sizeof *holdfd; f++) 526108e336aSBrian Somers close(holdfd[f]); 527108e336aSBrian Somers 528c0593e34SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(sw.mode)); 5290f78c7a7SBrian Somers DoLoop(bundle); 5301afedc4bSBrian Somers AbortProgram(EX_NORMAL); 531af57ed9fSAtsushi Murai 5321afedc4bSBrian Somers return EX_NORMAL; 533af57ed9fSAtsushi Murai } 534af57ed9fSAtsushi Murai 535af57ed9fSAtsushi Murai static void 5360f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 537af57ed9fSAtsushi Murai { 5388a52f3ecSBrian Somers fd_set *rfds, *wfds, *efds; 5391af29a6eSBrian Somers int i, nfds, nothing_done; 540c3899f8dSAtsushi Murai 5418a52f3ecSBrian Somers if ((rfds = mkfdset()) == NULL) { 5428a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5438a52f3ecSBrian Somers return; 5448a52f3ecSBrian Somers } 5458a52f3ecSBrian Somers 5468a52f3ecSBrian Somers if ((wfds = mkfdset()) == NULL) { 5478a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5488a52f3ecSBrian Somers free(rfds); 5498a52f3ecSBrian Somers return; 5508a52f3ecSBrian Somers } 5518a52f3ecSBrian Somers 5528a52f3ecSBrian Somers if ((efds = mkfdset()) == NULL) { 5538a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5548a52f3ecSBrian Somers free(rfds); 5558a52f3ecSBrian Somers free(wfds); 5568a52f3ecSBrian Somers return; 5578a52f3ecSBrian Somers } 5588a52f3ecSBrian Somers 559da8b7034SBrian Somers for (; !bundle_IsDead(bundle); bundle_CleanDatalinks(bundle)) { 560780700e5SAndrey A. Chernov nfds = 0; 5618a52f3ecSBrian Somers zerofdset(rfds); 5628a52f3ecSBrian Somers zerofdset(wfds); 5638a52f3ecSBrian Somers zerofdset(efds); 56484b8a6ebSAtsushi Murai 5650f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 5668a52f3ecSBrian Somers descriptor_UpdateSet(&bundle->desc, rfds, wfds, efds, &nfds); 5670f2f3eb3SBrian Somers 5680f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 5698a52f3ecSBrian Somers descriptor_UpdateSet(&server.desc, rfds, NULL, NULL, &nfds); 57007030d97SBrian Somers 5710cd8e902SBrian Somers bundle_CleanDatalinks(bundle); 5723b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 573f4768038SBrian Somers /* Don't select - we'll be here forever */ 574f4768038SBrian Somers break; 5750706ff38SBrian Somers 576486105bcSBrian Somers /* 577486105bcSBrian Somers * It's possible that we've had a signal since we last checked. If 578486105bcSBrian Somers * we don't check again before calling select(), we may end up stuck 579486105bcSBrian Somers * after having missed the event.... sig_Handle() tries to be as 580486105bcSBrian Somers * quick as possible if nothing is likely to have happened. 581486105bcSBrian Somers * This is only really likely if we block in open(... O_NONBLOCK) 582486105bcSBrian Somers * which will happen with a misconfigured device. 583486105bcSBrian Somers */ 584486105bcSBrian Somers if (sig_Handle()) 585486105bcSBrian Somers continue; 586486105bcSBrian Somers 5878a52f3ecSBrian Somers i = select(nfds, rfds, wfds, efds, NULL); 588712ae387SBrian Somers 58954cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 590dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 59124989c68SBrian Somers if (log_IsKept(LogTIMER)) { 59224989c68SBrian Somers struct timeval t; 59324989c68SBrian Somers 59424989c68SBrian Somers for (i = 0; i <= nfds; i++) { 5958a52f3ecSBrian Somers if (FD_ISSET(i, rfds)) { 59624989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 5978a52f3ecSBrian Somers FD_CLR(i, rfds); 59824989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 5998a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 60024989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 601af57ed9fSAtsushi Murai break; 602af57ed9fSAtsushi Murai } 60324989c68SBrian Somers } 6048a52f3ecSBrian Somers if (FD_ISSET(i, wfds)) { 60524989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 6068a52f3ecSBrian Somers FD_CLR(i, wfds); 60724989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6088a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 60924989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 610af57ed9fSAtsushi Murai break; 611af57ed9fSAtsushi Murai } 612e0d3e233SAndrey A. Chernov } 6138a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 61424989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 6158a52f3ecSBrian Somers FD_CLR(i, efds); 61624989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6178a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 61824989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 61958f264e1SBrian Somers break; 62058f264e1SBrian Somers } 62124989c68SBrian Somers } 62224989c68SBrian Somers } 62324989c68SBrian Somers } 62458f264e1SBrian Somers break; 625de451c68SBrian Somers } 626de451c68SBrian Somers 627f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Select returns %d\n", i); 628f0cdd9c0SBrian Somers 62954cd8e13SBrian Somers sig_Handle(); 63054cd8e13SBrian Somers 63154cd8e13SBrian Somers if (i <= 0) 63254cd8e13SBrian Somers continue; 63354cd8e13SBrian Somers 6343006ec67SBrian Somers for (i = 0; i <= nfds; i++) 6358a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 6368e7bd08eSBrian Somers log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 6378e7bd08eSBrian Somers /* We deal gracefully with link descriptor exceptions */ 638991c2a7bSBrian Somers if (!bundle_Exception(bundle, i)) { 639991c2a7bSBrian Somers log_Printf(LogERROR, "Exception cannot be handled !\n"); 6401ae349f5Scvs2svn break; 6411ae349f5Scvs2svn } 642991c2a7bSBrian Somers } 643c60f92caSBrian Somers 644b7c5748eSBrian Somers if (i <= nfds) 645b7c5748eSBrian Somers break; 646b7c5748eSBrian Somers 6471af29a6eSBrian Somers nothing_done = 1; 6481af29a6eSBrian Somers 6498a52f3ecSBrian Somers if (descriptor_IsSet(&server.desc, rfds)) { 6508a52f3ecSBrian Somers descriptor_Read(&server.desc, bundle, rfds); 6511af29a6eSBrian Somers nothing_done = 0; 6521af29a6eSBrian Somers } 6531af29a6eSBrian Somers 6548a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, rfds)) { 6558a52f3ecSBrian Somers descriptor_Read(&bundle->desc, bundle, rfds); 6561af29a6eSBrian Somers nothing_done = 0; 6571af29a6eSBrian Somers } 65842d4d396SBrian Somers 6598a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, wfds)) 660fb11a9c2SBrian Somers if (descriptor_Write(&bundle->desc, bundle, wfds) <= 0 && nothing_done) { 6611af29a6eSBrian Somers /* 662fb11a9c2SBrian Somers * This is disastrous. The OS has told us that something is 6631af29a6eSBrian Somers * writable, and all our write()s have failed. Rather than 6641af29a6eSBrian Somers * going back immediately to do our UpdateSet()s and select(), 6651af29a6eSBrian Somers * we sleep for a bit to avoid gobbling up all cpu time. 6661af29a6eSBrian Somers */ 6671af29a6eSBrian Somers struct timeval t; 6682f786681SBrian Somers 6691af29a6eSBrian Somers t.tv_sec = 0; 6701af29a6eSBrian Somers t.tv_usec = 100000; 6711af29a6eSBrian Somers select(0, NULL, NULL, NULL, &t); 6721af29a6eSBrian Somers } 673da8b7034SBrian Somers } 674565e35e5SBrian Somers 675dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 676af57ed9fSAtsushi Murai } 677