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> 4375240ed1SBrian Somers #include <stdio.h> 44c0593e34SBrian Somers #include <stdlib.h> 4575240ed1SBrian Somers #include <string.h> 4675240ed1SBrian Somers #include <sys/time.h> 4775240ed1SBrian Somers #include <termios.h> 4875240ed1SBrian Somers #include <unistd.h> 491080ea25SBrian Somers #include <sys/stat.h> 5075240ed1SBrian Somers 5167b072f7SBrian Somers #ifndef NONAT 5210e629b9SBrian Somers #ifdef LOCALNAT 537884358fSBrian Somers #include "alias.h" 5410e629b9SBrian Somers #else 5510e629b9SBrian Somers #include <alias.h> 561595bacdSBrian Somers #endif 571595bacdSBrian Somers #endif 5810e629b9SBrian Somers 595d9e6103SBrian Somers #include "layer.h" 601af29a6eSBrian Somers #include "probe.h" 6175240ed1SBrian Somers #include "mbuf.h" 6275240ed1SBrian Somers #include "log.h" 6375240ed1SBrian Somers #include "defs.h" 645106c671SBrian Somers #include "id.h" 6575240ed1SBrian Somers #include "timer.h" 6675240ed1SBrian Somers #include "fsm.h" 67879ed6faSBrian Somers #include "lqr.h" 68af57ed9fSAtsushi Murai #include "hdlc.h" 69af57ed9fSAtsushi Murai #include "lcp.h" 700053cc58SBrian Somers #include "ccp.h" 7129e275ceSBrian Somers #include "iplist.h" 7229e275ceSBrian Somers #include "throughput.h" 73eaa4df37SBrian Somers #include "slcompress.h" 7430949fd4SBrian Somers #include "ncpaddr.h" 7530949fd4SBrian Somers #include "ip.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 112944f7098SBrian Somers Cleanup(int excode) 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 { 121dd7e2610SBrian Somers server_Close(SignalBundle); 122dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 1239c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 12468a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 125dd7e2610SBrian Somers log_Close(); 126af57ed9fSAtsushi Murai exit(excode); 127af57ed9fSAtsushi Murai } 128af57ed9fSAtsushi Murai 129af57ed9fSAtsushi Murai static void 130944f7098SBrian Somers CloseConnection(int signo) 131af57ed9fSAtsushi Murai { 132368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 133dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 134dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 135899011c4SBrian Somers bundle_Down(SignalBundle, CLOSE_STAYDOWN); 136dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1376d14e2a8SJordan K. Hubbard } 138af57ed9fSAtsushi Murai 139af57ed9fSAtsushi Murai static void 140944f7098SBrian Somers CloseSession(int signo) 141af57ed9fSAtsushi Murai { 142dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 143af57ed9fSAtsushi Murai Cleanup(EX_TERM); 144af57ed9fSAtsushi Murai } 145c3899f8dSAtsushi Murai 14675b8d283SBrian Somers static pid_t BGPid = 0; 14775b8d283SBrian Somers 14875b8d283SBrian Somers static void 14975b8d283SBrian Somers KillChild(int signo) 15075b8d283SBrian Somers { 151ac37ab22SBrian Somers signal(signo, SIG_IGN); 152dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 15375b8d283SBrian Somers kill(BGPid, SIGINT); 15475b8d283SBrian Somers } 15575b8d283SBrian Somers 156c3899f8dSAtsushi Murai static void 157b6e82f33SBrian Somers TerminalCont(int signo) 158c3899f8dSAtsushi Murai { 159f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 160f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 161c3899f8dSAtsushi Murai } 162c3899f8dSAtsushi Murai 163c3899f8dSAtsushi Murai static void 164944f7098SBrian Somers TerminalStop(int signo) 165c3899f8dSAtsushi Murai { 166f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 167f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 168f91ad6b0SBrian Somers raise(SIGSTOP); 1694ef16f24SBrian Somers } 1704ef16f24SBrian Somers 1718ea8442cSBrian Somers static void 1728ea8442cSBrian Somers BringDownServer(int signo) 1738ea8442cSBrian Somers { 174b6217683SBrian Somers /* Drops all child prompts too ! */ 17574457d3dSBrian Somers if (server_Close(SignalBundle)) 17674457d3dSBrian Somers log_Printf(LogPHASE, "Closed server socket\n"); 17774457d3dSBrian Somers } 17874457d3dSBrian Somers 17974457d3dSBrian Somers static void 18074457d3dSBrian Somers RestartServer(int signo) 18174457d3dSBrian Somers { 18274457d3dSBrian Somers /* Drops all child prompts and re-opens the socket */ 18374457d3dSBrian Somers server_Reopen(SignalBundle); 1848ea8442cSBrian Somers } 1858ea8442cSBrian Somers 18675240ed1SBrian Somers static void 187b6e82f33SBrian Somers Usage(void) 188af57ed9fSAtsushi Murai { 1899b996792SBrian Somers fprintf(stderr, "Usage: ppp [-auto | -foreground | -background | -direct |" 1909b996792SBrian Somers " -dedicated | -ddial | -interactive]" 191b6e82f33SBrian Somers #ifndef NOALIAS 19267b072f7SBrian Somers " [-nat]" 193b6e82f33SBrian Somers #endif 194c0593e34SBrian Somers " [-quiet] [-unit N] [system ...]\n"); 195af57ed9fSAtsushi Murai exit(EX_START); 196af57ed9fSAtsushi Murai } 197af57ed9fSAtsushi Murai 198c0593e34SBrian Somers struct switches { 199c0593e34SBrian Somers unsigned nat : 1; 200c0593e34SBrian Somers unsigned fg : 1; 201c0593e34SBrian Somers unsigned quiet : 1; 202c0593e34SBrian Somers int mode; 203c0593e34SBrian Somers int unit; 204c0593e34SBrian Somers }; 205c0593e34SBrian Somers 2067cf368ebSBrian Somers static int 207c0593e34SBrian Somers ProcessArgs(int argc, char **argv, struct switches *sw) 208af57ed9fSAtsushi Murai { 2097cf368ebSBrian Somers int optc, newmode, arg; 210af57ed9fSAtsushi Murai char *cp; 211af57ed9fSAtsushi Murai 2127cf368ebSBrian Somers optc = 0; 213c0593e34SBrian Somers memset(sw, '\0', sizeof *sw); 214c0593e34SBrian Somers sw->mode = PHYS_INTERACTIVE; 215c0593e34SBrian Somers sw->unit = -1; 216c0593e34SBrian Somers 2177cf368ebSBrian Somers for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 2187cf368ebSBrian Somers cp = argv[arg] + 1; 21981358fa3SBrian Somers newmode = Nam2mode(cp); 22081358fa3SBrian Somers switch (newmode) { 22181358fa3SBrian Somers case PHYS_NONE: 222c0593e34SBrian Somers if (strcmp(cp, "nat") == 0) { 22367b072f7SBrian Somers #ifdef NONAT 224c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 225615ad4f9SBrian Somers #else 226c0593e34SBrian Somers sw->nat = 1; 227615ad4f9SBrian Somers #endif 2281ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 229c0593e34SBrian Somers } else if (strcmp(cp, "alias") == 0) { 230c0593e34SBrian Somers #ifdef NONAT 231c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 232c0593e34SBrian Somers fprintf(stderr, "%s ignored: NAT is compiled out\n", argv[arg]); 233c0593e34SBrian Somers #else 234886530abSBrian Somers log_Printf(LogWARN, "%s is deprecated\n", argv[arg]); 235886530abSBrian Somers fprintf(stderr, "%s is deprecated\n", argv[arg]); 236c0593e34SBrian Somers sw->nat = 1; 237c0593e34SBrian Somers #endif 238c0593e34SBrian Somers optc--; /* this option isn't exclusive */ 239c0593e34SBrian Somers } else if (strncmp(cp, "unit", 4) == 0) { 2409d06928dSBrian Somers optc--; /* this option isn't exclusive */ 241c0593e34SBrian Somers if (cp[4] == '\0') { 2429d06928dSBrian Somers optc--; /* nor is the argument */ 243c0593e34SBrian Somers if (++arg == argc) { 244c0593e34SBrian Somers fprintf(stderr, "-unit: Expected unit number\n"); 245c0593e34SBrian Somers Usage(); 246c0593e34SBrian Somers } else 247c0593e34SBrian Somers sw->unit = atoi(argv[arg]); 248c0593e34SBrian Somers } else 249c0593e34SBrian Somers sw->unit = atoi(cp + 4); 25067b072f7SBrian Somers } else if (strcmp(cp, "quiet") == 0) { 251c0593e34SBrian Somers sw->quiet = 1; 25267b072f7SBrian Somers optc--; /* this option isn't exclusive */ 253944f7098SBrian Somers } else 254af57ed9fSAtsushi Murai Usage(); 25581358fa3SBrian Somers break; 25681358fa3SBrian Somers 25781358fa3SBrian Somers case PHYS_ALL: 25881358fa3SBrian Somers Usage(); 25981358fa3SBrian Somers break; 26081358fa3SBrian Somers 26181358fa3SBrian Somers default: 262c0593e34SBrian Somers sw->mode = newmode; 263f6a4e748SBrian Somers if (newmode == PHYS_FOREGROUND) 264f6a4e748SBrian Somers sw->fg = 1; 26581358fa3SBrian Somers } 266af57ed9fSAtsushi Murai } 267af57ed9fSAtsushi Murai 268af57ed9fSAtsushi Murai if (optc > 1) { 26985602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2701ae349f5Scvs2svn exit(EX_START); 2711ae349f5Scvs2svn } 2721ae349f5Scvs2svn 273c0593e34SBrian Somers if (sw->mode == PHYS_AUTO && arg == argc) { 2747cf368ebSBrian Somers fprintf(stderr, "A system must be specified in auto mode.\n"); 275af57ed9fSAtsushi Murai exit(EX_START); 276af57ed9fSAtsushi Murai } 27739f94eddSBrian Somers 2787cf368ebSBrian Somers return arg; /* Don't SetLabel yet ! */ 279af57ed9fSAtsushi Murai } 280af57ed9fSAtsushi Murai 2817cf368ebSBrian Somers static void 2827cf368ebSBrian Somers CheckLabel(const char *label, struct prompt *prompt, int mode) 2837cf368ebSBrian Somers { 2847cf368ebSBrian Somers const char *err; 2857cf368ebSBrian Somers 2867cf368ebSBrian Somers if ((err = system_IsValid(label, prompt, mode)) != NULL) { 2877cf368ebSBrian Somers fprintf(stderr, "%s: %s\n", label, err); 2887cf368ebSBrian Somers if (mode == PHYS_DIRECT) 2897cf368ebSBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 2907cf368ebSBrian Somers label, err); 2917cf368ebSBrian Somers log_Close(); 2927cf368ebSBrian Somers exit(1); 2937cf368ebSBrian Somers } 2947cf368ebSBrian Somers } 2957cf368ebSBrian Somers 2967cf368ebSBrian Somers 2974ef16f24SBrian Somers int 298944f7098SBrian Somers main(int argc, char **argv) 299af57ed9fSAtsushi Murai { 3007cf368ebSBrian Somers char *name; 301756783fcSBrian Somers const char *lastlabel; 302108e336aSBrian Somers int arg, f, holdfd[3], label; 3037a6f8720SBrian Somers struct bundle *bundle; 304b6217683SBrian Somers struct prompt *prompt; 305c0593e34SBrian Somers struct switches sw; 306e3b4c400SBrian Somers 307971abb29SBrian Somers probe_Init(); 308971abb29SBrian Somers 309108e336aSBrian Somers /* 310108e336aSBrian Somers * We open 3 descriptors to ensure that STDIN_FILENO, STDOUT_FILENO and 311108e336aSBrian Somers * STDERR_FILENO are always open. These are closed before DoLoop(), 312108e336aSBrian Somers * but *after* we've avoided the possibility of erroneously closing 313108e336aSBrian Somers * an important descriptor with close(STD{IN,OUT,ERR}_FILENO). 314108e336aSBrian Somers */ 315108e336aSBrian Somers if ((holdfd[0] = open(_PATH_DEVNULL, O_RDWR)) == -1) { 316108e336aSBrian Somers fprintf(stderr, "Cannot open %s !\n", _PATH_DEVNULL); 317108e336aSBrian Somers return 2; 318108e336aSBrian Somers } 319108e336aSBrian Somers for (f = 1; f < sizeof holdfd / sizeof *holdfd; f++) 320dd1a52b9SBrian Somers holdfd[f] = dup(holdfd[0]); 321108e336aSBrian Somers 32275240ed1SBrian Somers name = strrchr(argv[0], '/'); 323dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 3242a279fedSBrian Somers 32567b072f7SBrian Somers #ifndef NONAT 3262a630835SBrian Somers PacketAliasInit(); 3272a630835SBrian Somers #endif 328c0593e34SBrian Somers label = ProcessArgs(argc, argv, &sw); 32985b542cfSBrian Somers 33085b542cfSBrian Somers /* 331a611383fSBrian Somers * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 332a611383fSBrian Somers * output occasionally.... I must find the real reason some time. To 333a611383fSBrian Somers * display the dodgy behaviour, comment out this bit, make yourself a large 33485b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 33585b542cfSBrian Somers * command will drop chunks of data !!! 33685b542cfSBrian Somers */ 337c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) { 33885b542cfSBrian Somers close(STDIN_FILENO); 33985b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 34085b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 34185b542cfSBrian Somers return 2; 34285b542cfSBrian Somers } 34385b542cfSBrian Somers } 34485b542cfSBrian Somers 345b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 346c0593e34SBrian Somers if (sw.mode == PHYS_DIRECT) 347b6217683SBrian Somers prompt = NULL; 348ed0e9269SBrian Somers else 349b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 35012ef29a8SBrian Somers 3515106c671SBrian Somers ID0init(); 3524562be74SBrian Somers if (ID0realuid() != 0) { 3534562be74SBrian Somers char conf[200], *ptr; 3544562be74SBrian Somers 3557a66a36dSBrian Somers snprintf(conf, sizeof conf, "%s/%s", PPP_CONFDIR, CONFFILE); 3564562be74SBrian Somers do { 3571080ea25SBrian Somers struct stat sb; 3581080ea25SBrian Somers 3591080ea25SBrian Somers if (stat(conf, &sb) == 0 && sb.st_mode & S_IWOTH) { 360a33b2ef7SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 361a33b2ef7SBrian Somers conf); 3624562be74SBrian Somers return -1; 3634562be74SBrian Somers } 3644562be74SBrian Somers ptr = conf + strlen(conf)-2; 3654562be74SBrian Somers while (ptr > conf && *ptr != '/') 3664562be74SBrian Somers *ptr-- = '\0'; 3674562be74SBrian Somers } while (ptr >= conf); 3684562be74SBrian Somers } 3694562be74SBrian Somers 3707cf368ebSBrian Somers if (label < argc) 3717cf368ebSBrian Somers for (arg = label; arg < argc; arg++) 372c0593e34SBrian Somers CheckLabel(argv[arg], prompt, sw.mode); 3737cf368ebSBrian Somers else 374c0593e34SBrian Somers CheckLabel("default", prompt, sw.mode); 37512ef29a8SBrian Somers 376c0593e34SBrian Somers if (!sw.quiet) 377c0593e34SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(sw.mode)); 378ed0e9269SBrian Somers 379cf0a3940SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, sw.mode, sw.unit)) == NULL) 3804ef16f24SBrian Somers return EX_START; 381756783fcSBrian Somers 382756783fcSBrian Somers /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 383756783fcSBrian Somers 3840f2f3eb3SBrian Somers if (prompt) { 3850f2f3eb3SBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 386c0593e34SBrian Somers if (!sw.quiet) 3878fa6ebe4SBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 3880f2f3eb3SBrian Somers } 38983d1af55SBrian Somers SignalBundle = bundle; 390c0593e34SBrian Somers bundle->NatEnabled = sw.nat; 391c0593e34SBrian Somers if (sw.nat) 3928fa6ebe4SBrian Somers bundle->cfg.opt |= OPT_IFACEALIAS; 39312ef29a8SBrian Somers 39430291ffbSBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 395565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3961ae349f5Scvs2svn 397dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 398dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 399dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 400dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 401dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 402e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 403565e35e5SBrian Somers 404c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) 405dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 406f91ad6b0SBrian Somers 40774457d3dSBrian Somers sig_signal(SIGUSR1, RestartServer); 408dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 409af57ed9fSAtsushi Murai 410cf0a3940SBrian Somers lastlabel = argv[argc - 1]; 4117cf368ebSBrian Somers for (arg = label; arg < argc; arg++) { 4127cf368ebSBrian Somers /* In case we use LABEL or ``set enddisc label'' */ 413756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 414cf0a3940SBrian Somers system_Select(bundle, argv[arg], CONFFILE, prompt, NULL); 4151ae349f5Scvs2svn } 4167cf368ebSBrian Somers 4177cf368ebSBrian Somers if (label < argc) 4187cf368ebSBrian Somers /* In case the last label did a ``load'' */ 419756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 4207cf368ebSBrian Somers 421c0593e34SBrian Somers if (sw.mode == PHYS_AUTO && 42230949fd4SBrian Somers ncprange_family(&bundle->ncp.ipcp.cfg.peer_range) == AF_UNSPEC) { 4237cf368ebSBrian Somers prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 4247cf368ebSBrian Somers "in auto mode.\n"); 4258390b576SBrian Somers AbortProgram(EX_START); 426af57ed9fSAtsushi Murai } 4276efd9292SBrian Somers 428c0593e34SBrian Somers if (sw.mode != PHYS_INTERACTIVE) { 429c0593e34SBrian Somers if (sw.mode != PHYS_DIRECT) { 430c0593e34SBrian Somers if (!sw.fg) { 4315cf4388bSBrian Somers int bgpipe[2]; 4326d14e2a8SJordan K. Hubbard pid_t bgpid; 433a9c6b5dfSAtsushi Murai 434c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND && pipe(bgpipe)) { 435dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 4368390b576SBrian Somers AbortProgram(EX_SOCK); 4371ae349f5Scvs2svn } 4381ae349f5Scvs2svn 4396d14e2a8SJordan K. Hubbard bgpid = fork(); 4406d14e2a8SJordan K. Hubbard if (bgpid == -1) { 441dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 4428390b576SBrian Somers AbortProgram(EX_SOCK); 4436d14e2a8SJordan K. Hubbard } 4445cf4388bSBrian Somers 4456d14e2a8SJordan K. Hubbard if (bgpid) { 4466d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 447b42135deSBrian Somers int ret; 448a9c6b5dfSAtsushi Murai 449c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND) { 4505cf4388bSBrian Somers close(bgpipe[1]); 4516d14e2a8SJordan K. Hubbard BGPid = bgpid; 45275b8d283SBrian Somers /* If we get a signal, kill the child */ 45375b8d283SBrian Somers signal(SIGHUP, KillChild); 45475b8d283SBrian Somers signal(SIGTERM, KillChild); 45575b8d283SBrian Somers signal(SIGINT, KillChild); 45675b8d283SBrian Somers signal(SIGQUIT, KillChild); 45775b8d283SBrian Somers 45875b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 459b42135deSBrian Somers while ((ret = read(bgpipe[0], &c, 1)) == 1) { 460b42135deSBrian Somers switch (c) { 461b42135deSBrian Somers case EX_NORMAL: 4620fea4ed0SBrian Somers if (!sw.quiet) { 463b42135deSBrian Somers prompt_Printf(prompt, "PPP enabled\n"); 464b42135deSBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled\n"); 4650fea4ed0SBrian Somers } 4669bf01bcbSBrian Somers break; 467b42135deSBrian Somers case EX_REDIAL: 468b42135deSBrian Somers if (!sw.quiet) 469b42135deSBrian Somers prompt_Printf(prompt, "Attempting redial\n"); 470b42135deSBrian Somers continue; 471b42135deSBrian Somers case EX_RECONNECT: 472b42135deSBrian Somers if (!sw.quiet) 473b42135deSBrian Somers prompt_Printf(prompt, "Attempting reconnect\n"); 474b42135deSBrian Somers continue; 475b42135deSBrian Somers default: 476b42135deSBrian Somers prompt_Printf(prompt, "Child failed (%s)\n", 477b42135deSBrian Somers ex_desc((int)c)); 478b42135deSBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s)\n", 479b42135deSBrian Somers ex_desc((int) c)); 480b42135deSBrian Somers } 481b42135deSBrian Somers break; 482b42135deSBrian Somers } 483b42135deSBrian Somers if (ret != 1) { 484b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 485dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4866efd9292SBrian Somers } 4875cf4388bSBrian Somers close(bgpipe[0]); 4886d14e2a8SJordan K. Hubbard } 4894ef16f24SBrian Somers return c; 490c0593e34SBrian Somers } else if (sw.mode == PHYS_BACKGROUND) { 4915cf4388bSBrian Somers close(bgpipe[0]); 4925cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 493aefd026aSBrian Somers } 494aefd026aSBrian Somers 49506b47306SBrian Somers bundle_ChangedPID(bundle); 496da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 49767b072f7SBrian Somers } 498da66dd13SBrian Somers 49967b072f7SBrian Somers /* -auto, -dedicated, -ddial, -foreground & -background */ 500b6217683SBrian Somers prompt_Destroy(prompt, 0); 5012a279fedSBrian Somers close(STDOUT_FILENO); 5022a279fedSBrian Somers close(STDERR_FILENO); 5032a279fedSBrian Somers close(STDIN_FILENO); 504c0593e34SBrian Somers if (!sw.fg) 505b6217683SBrian Somers setsid(); 506565e35e5SBrian Somers } else { 50767b072f7SBrian Somers /* -direct - STDIN_FILENO gets used by physical_Open */ 508565e35e5SBrian Somers prompt_TtyInit(NULL); 509565e35e5SBrian Somers close(STDOUT_FILENO); 510565e35e5SBrian Somers close(STDERR_FILENO); 511d656a4c5SBrian Somers } 512af57ed9fSAtsushi Murai } else { 51367b072f7SBrian Somers /* -interactive */ 5142a279fedSBrian Somers close(STDERR_FILENO); 515565e35e5SBrian Somers prompt_TtyInit(prompt); 516b6217683SBrian Somers prompt_TtyCommandMode(prompt); 517b6217683SBrian Somers prompt_Required(prompt); 518af57ed9fSAtsushi Murai } 51935495becSBrian Somers 520108e336aSBrian Somers /* We can get rid of these now */ 521108e336aSBrian Somers for (f = 0; f < sizeof holdfd / sizeof *holdfd; f++) 522108e336aSBrian Somers close(holdfd[f]); 523108e336aSBrian Somers 524c0593e34SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(sw.mode)); 5250f78c7a7SBrian Somers DoLoop(bundle); 5261afedc4bSBrian Somers AbortProgram(EX_NORMAL); 527af57ed9fSAtsushi Murai 5281afedc4bSBrian Somers return EX_NORMAL; 529af57ed9fSAtsushi Murai } 530af57ed9fSAtsushi Murai 531af57ed9fSAtsushi Murai static void 5320f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 533af57ed9fSAtsushi Murai { 5348a52f3ecSBrian Somers fd_set *rfds, *wfds, *efds; 5351af29a6eSBrian Somers int i, nfds, nothing_done; 536c3899f8dSAtsushi Murai 5378a52f3ecSBrian Somers if ((rfds = mkfdset()) == NULL) { 5388a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5398a52f3ecSBrian Somers return; 5408a52f3ecSBrian Somers } 5418a52f3ecSBrian Somers 5428a52f3ecSBrian Somers if ((wfds = mkfdset()) == NULL) { 5438a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5448a52f3ecSBrian Somers free(rfds); 5458a52f3ecSBrian Somers return; 5468a52f3ecSBrian Somers } 5478a52f3ecSBrian Somers 5488a52f3ecSBrian Somers if ((efds = mkfdset()) == NULL) { 5498a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5508a52f3ecSBrian Somers free(rfds); 5518a52f3ecSBrian Somers free(wfds); 5528a52f3ecSBrian Somers return; 5538a52f3ecSBrian Somers } 5548a52f3ecSBrian Somers 555da8b7034SBrian Somers for (; !bundle_IsDead(bundle); bundle_CleanDatalinks(bundle)) { 556780700e5SAndrey A. Chernov nfds = 0; 5578a52f3ecSBrian Somers zerofdset(rfds); 5588a52f3ecSBrian Somers zerofdset(wfds); 5598a52f3ecSBrian Somers zerofdset(efds); 56084b8a6ebSAtsushi Murai 5610f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 5628a52f3ecSBrian Somers descriptor_UpdateSet(&bundle->desc, rfds, wfds, efds, &nfds); 5630f2f3eb3SBrian Somers 5640f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 5658a52f3ecSBrian Somers descriptor_UpdateSet(&server.desc, rfds, NULL, NULL, &nfds); 56607030d97SBrian Somers 5670cd8e902SBrian Somers bundle_CleanDatalinks(bundle); 5683b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 569f4768038SBrian Somers /* Don't select - we'll be here forever */ 570f4768038SBrian Somers break; 5710706ff38SBrian Somers 572486105bcSBrian Somers /* 573486105bcSBrian Somers * It's possible that we've had a signal since we last checked. If 574486105bcSBrian Somers * we don't check again before calling select(), we may end up stuck 575486105bcSBrian Somers * after having missed the event.... sig_Handle() tries to be as 576486105bcSBrian Somers * quick as possible if nothing is likely to have happened. 577486105bcSBrian Somers * This is only really likely if we block in open(... O_NONBLOCK) 578486105bcSBrian Somers * which will happen with a misconfigured device. 579486105bcSBrian Somers */ 580486105bcSBrian Somers if (sig_Handle()) 581486105bcSBrian Somers continue; 582486105bcSBrian Somers 5838a52f3ecSBrian Somers i = select(nfds, rfds, wfds, efds, NULL); 584712ae387SBrian Somers 58554cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 586dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 58724989c68SBrian Somers if (log_IsKept(LogTIMER)) { 58824989c68SBrian Somers struct timeval t; 58924989c68SBrian Somers 59024989c68SBrian Somers for (i = 0; i <= nfds; i++) { 5918a52f3ecSBrian Somers if (FD_ISSET(i, rfds)) { 59224989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 5938a52f3ecSBrian Somers FD_CLR(i, rfds); 59424989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 5958a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 59624989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 597af57ed9fSAtsushi Murai break; 598af57ed9fSAtsushi Murai } 59924989c68SBrian Somers } 6008a52f3ecSBrian Somers if (FD_ISSET(i, wfds)) { 60124989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 6028a52f3ecSBrian Somers FD_CLR(i, wfds); 60324989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6048a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 60524989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 606af57ed9fSAtsushi Murai break; 607af57ed9fSAtsushi Murai } 608e0d3e233SAndrey A. Chernov } 6098a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 61024989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 6118a52f3ecSBrian Somers FD_CLR(i, efds); 61224989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6138a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 61424989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 61558f264e1SBrian Somers break; 61658f264e1SBrian Somers } 61724989c68SBrian Somers } 61824989c68SBrian Somers } 61924989c68SBrian Somers } 62058f264e1SBrian Somers break; 621de451c68SBrian Somers } 622de451c68SBrian Somers 623f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Select returns %d\n", i); 624f0cdd9c0SBrian Somers 62554cd8e13SBrian Somers sig_Handle(); 62654cd8e13SBrian Somers 62754cd8e13SBrian Somers if (i <= 0) 62854cd8e13SBrian Somers continue; 62954cd8e13SBrian Somers 6303006ec67SBrian Somers for (i = 0; i <= nfds; i++) 6318a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 6328e7bd08eSBrian Somers log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 6338e7bd08eSBrian Somers /* We deal gracefully with link descriptor exceptions */ 634991c2a7bSBrian Somers if (!bundle_Exception(bundle, i)) { 635991c2a7bSBrian Somers log_Printf(LogERROR, "Exception cannot be handled !\n"); 6361ae349f5Scvs2svn break; 6371ae349f5Scvs2svn } 638991c2a7bSBrian Somers } 639c60f92caSBrian Somers 640b7c5748eSBrian Somers if (i <= nfds) 641b7c5748eSBrian Somers break; 642b7c5748eSBrian Somers 6431af29a6eSBrian Somers nothing_done = 1; 6441af29a6eSBrian Somers 6458a52f3ecSBrian Somers if (descriptor_IsSet(&server.desc, rfds)) { 6468a52f3ecSBrian Somers descriptor_Read(&server.desc, bundle, rfds); 6471af29a6eSBrian Somers nothing_done = 0; 6481af29a6eSBrian Somers } 6491af29a6eSBrian Somers 6508a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, rfds)) { 6518a52f3ecSBrian Somers descriptor_Read(&bundle->desc, bundle, rfds); 6521af29a6eSBrian Somers nothing_done = 0; 6531af29a6eSBrian Somers } 65442d4d396SBrian Somers 6558a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, wfds)) 6568a52f3ecSBrian Somers if (!descriptor_Write(&bundle->desc, bundle, wfds) && nothing_done) { 6571af29a6eSBrian Somers /* 6581af29a6eSBrian Somers * This is disasterous. The OS has told us that something is 6591af29a6eSBrian Somers * writable, and all our write()s have failed. Rather than 6601af29a6eSBrian Somers * going back immediately to do our UpdateSet()s and select(), 6611af29a6eSBrian Somers * we sleep for a bit to avoid gobbling up all cpu time. 6621af29a6eSBrian Somers */ 6631af29a6eSBrian Somers struct timeval t; 6642f786681SBrian Somers 6651af29a6eSBrian Somers t.tv_sec = 0; 6661af29a6eSBrian Somers t.tv_usec = 100000; 6671af29a6eSBrian Somers select(0, NULL, NULL, NULL, &t); 6681af29a6eSBrian Somers } 669da8b7034SBrian Somers } 670565e35e5SBrian Somers 671dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 672af57ed9fSAtsushi Murai } 673