165309e5cSBrian Somers /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 465309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 565309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 665309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 765309e5cSBrian Somers * All rights reserved. 8af57ed9fSAtsushi Murai * 965309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 1065309e5cSBrian Somers * modification, are permitted provided that the following conditions 1165309e5cSBrian Somers * are met: 1265309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1465309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1565309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1665309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 17af57ed9fSAtsushi Murai * 1865309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1965309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2065309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2165309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2265309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2365309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2465309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2565309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2665309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2765309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2865309e5cSBrian Somers * SUCH DAMAGE. 29af57ed9fSAtsushi Murai * 3097d92980SPeter Wemm * $FreeBSD$ 31af57ed9fSAtsushi Murai */ 322764b86aSBrian Somers 33972a1bcfSBrian Somers #include <sys/param.h> 3475240ed1SBrian Somers #include <netinet/in.h> 35a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 36a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 37565e35e5SBrian Somers #include <sys/un.h> 386b457978SBrian Somers #include <sys/socket.h> 396b457978SBrian Somers #include <net/route.h> 4075240ed1SBrian Somers 4175240ed1SBrian Somers #include <errno.h> 4275240ed1SBrian Somers #include <fcntl.h> 4375240ed1SBrian Somers #include <paths.h> 4475240ed1SBrian Somers #include <signal.h> 456eafd353SBrian Somers #include <stdarg.h> 4675240ed1SBrian Somers #include <stdio.h> 47c0593e34SBrian Somers #include <stdlib.h> 4875240ed1SBrian Somers #include <string.h> 49b08bf2deSBrian Somers #include <sys/time.h> 5075240ed1SBrian Somers #include <termios.h> 5175240ed1SBrian Somers #include <unistd.h> 521080ea25SBrian Somers #include <sys/stat.h> 5375240ed1SBrian Somers 5467b072f7SBrian Somers #ifndef NONAT 5510e629b9SBrian Somers #ifdef LOCALNAT 567884358fSBrian Somers #include "alias.h" 5710e629b9SBrian Somers #else 5810e629b9SBrian Somers #include <alias.h> 591595bacdSBrian Somers #endif 601595bacdSBrian Somers #endif 6110e629b9SBrian Somers 625d9e6103SBrian Somers #include "layer.h" 631af29a6eSBrian Somers #include "probe.h" 6475240ed1SBrian Somers #include "mbuf.h" 6575240ed1SBrian Somers #include "log.h" 6675240ed1SBrian Somers #include "defs.h" 675106c671SBrian Somers #include "id.h" 6875240ed1SBrian Somers #include "timer.h" 6975240ed1SBrian Somers #include "fsm.h" 70879ed6faSBrian Somers #include "lqr.h" 71af57ed9fSAtsushi Murai #include "hdlc.h" 72af57ed9fSAtsushi Murai #include "lcp.h" 730053cc58SBrian Somers #include "ccp.h" 7429e275ceSBrian Somers #include "iplist.h" 7529e275ceSBrian Somers #include "throughput.h" 76eaa4df37SBrian Somers #include "slcompress.h" 7730949fd4SBrian Somers #include "ncpaddr.h" 78af57ed9fSAtsushi Murai #include "ipcp.h" 7984b8a6ebSAtsushi Murai #include "filter.h" 802f786681SBrian Somers #include "descriptor.h" 813b0f8d2eSBrian Somers #include "link.h" 823b0f8d2eSBrian Somers #include "mp.h" 83972a1bcfSBrian Somers #ifndef NORADIUS 84972a1bcfSBrian Somers #include "radius.h" 85972a1bcfSBrian Somers #endif 8630949fd4SBrian Somers #include "ipv6cp.h" 8730949fd4SBrian Somers #include "ncp.h" 885828db6dSBrian Somers #include "bundle.h" 891ae349f5Scvs2svn #include "auth.h" 90ed6a16c1SPoul-Henning Kamp #include "systems.h" 91f5ff0f7cSBrian Somers #include "sig.h" 9275240ed1SBrian Somers #include "main.h" 9377ff88adSBrian Somers #include "server.h" 9485b542cfSBrian Somers #include "prompt.h" 95b6dec9f0SBrian Somers #include "chat.h" 96e2ebb036SBrian Somers #include "chap.h" 9792b09558SBrian Somers #include "cbcp.h" 983006ec67SBrian Somers #include "datalink.h" 998fa6ebe4SBrian Somers #include "iface.h" 10053c9f6c0SAtsushi Murai 10153c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 10253c9f6c0SAtsushi Murai #ifdef O_NDELAY 10353c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 10453c9f6c0SAtsushi Murai #endif 10553c9f6c0SAtsushi Murai #endif 106af57ed9fSAtsushi Murai 1070f78c7a7SBrian Somers static void DoLoop(struct bundle *); 10875240ed1SBrian Somers static void TerminalStop(int); 10975240ed1SBrian Somers 11083d1af55SBrian Somers static struct bundle *SignalBundle; 111b6217683SBrian Somers static struct prompt *SignalPrompt; 112a5625ae7SPaolo Pisati struct libalias *la; 113c3899f8dSAtsushi Murai 114c3899f8dSAtsushi Murai void 115*672eba24SJohn Baldwin Cleanup(void) 116af57ed9fSAtsushi Murai { 117a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 1189c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 1196e4959f0SBrian Somers } 120af57ed9fSAtsushi Murai 1211afedc4bSBrian Somers void 1221afedc4bSBrian Somers AbortProgram(int excode) 1231afedc4bSBrian Somers { 12423ddebe2SBrian Somers if (SignalBundle) 125dd7e2610SBrian Somers server_Close(SignalBundle); 126dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 12723ddebe2SBrian Somers if (SignalBundle) { 1289c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 12968a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 13023ddebe2SBrian Somers } 131dd7e2610SBrian Somers log_Close(); 132af57ed9fSAtsushi Murai exit(excode); 133af57ed9fSAtsushi Murai } 134af57ed9fSAtsushi Murai 135af57ed9fSAtsushi Murai static void 136944f7098SBrian Somers CloseConnection(int signo) 137af57ed9fSAtsushi Murai { 138368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 139dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 140dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 141899011c4SBrian Somers bundle_Down(SignalBundle, CLOSE_STAYDOWN); 142dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1436d14e2a8SJordan K. Hubbard } 144af57ed9fSAtsushi Murai 145af57ed9fSAtsushi Murai static void 146944f7098SBrian Somers CloseSession(int signo) 147af57ed9fSAtsushi Murai { 148dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 149057f1760SBrian Somers Cleanup(); 150af57ed9fSAtsushi Murai } 151c3899f8dSAtsushi Murai 15275b8d283SBrian Somers static pid_t BGPid = 0; 15375b8d283SBrian Somers 15475b8d283SBrian Somers static void 15575b8d283SBrian Somers KillChild(int signo) 15675b8d283SBrian Somers { 157ac37ab22SBrian Somers signal(signo, SIG_IGN); 158dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 15975b8d283SBrian Somers kill(BGPid, SIGINT); 16075b8d283SBrian Somers } 16175b8d283SBrian Somers 162c3899f8dSAtsushi Murai static void 163057f1760SBrian Somers TerminalCont(int signo __unused) 164c3899f8dSAtsushi Murai { 165f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 166f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 167c3899f8dSAtsushi Murai } 168c3899f8dSAtsushi Murai 169c3899f8dSAtsushi Murai static void 170057f1760SBrian Somers TerminalStop(int signo __unused) 171c3899f8dSAtsushi Murai { 172f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 173f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 174f91ad6b0SBrian Somers raise(SIGSTOP); 1754ef16f24SBrian Somers } 1764ef16f24SBrian Somers 1778ea8442cSBrian Somers static void 178057f1760SBrian Somers BringDownServer(int signo __unused) 1798ea8442cSBrian Somers { 180b6217683SBrian Somers /* Drops all child prompts too ! */ 18174457d3dSBrian Somers if (server_Close(SignalBundle)) 18274457d3dSBrian Somers log_Printf(LogPHASE, "Closed server socket\n"); 18374457d3dSBrian Somers } 18474457d3dSBrian Somers 18574457d3dSBrian Somers static void 186057f1760SBrian Somers RestartServer(int signo __unused) 18774457d3dSBrian Somers { 18874457d3dSBrian Somers /* Drops all child prompts and re-opens the socket */ 18974457d3dSBrian Somers server_Reopen(SignalBundle); 1908ea8442cSBrian Somers } 1918ea8442cSBrian Somers 19275240ed1SBrian Somers static void 193b6e82f33SBrian Somers Usage(void) 194af57ed9fSAtsushi Murai { 195d3974088SDag-Erling Smørgrav fprintf(stderr, "usage: ppp [-auto | -foreground | -background | -direct |" 1969b996792SBrian Somers " -dedicated | -ddial | -interactive]" 197564299efSRuslan Ermilov #ifndef NONAT 19867b072f7SBrian Somers " [-nat]" 199b6e82f33SBrian Somers #endif 200c0593e34SBrian Somers " [-quiet] [-unit N] [system ...]\n"); 201af57ed9fSAtsushi Murai exit(EX_START); 202af57ed9fSAtsushi Murai } 203af57ed9fSAtsushi Murai 204c0593e34SBrian Somers struct switches { 205c0593e34SBrian Somers unsigned nat : 1; 206c0593e34SBrian Somers unsigned fg : 1; 207c0593e34SBrian Somers unsigned quiet : 1; 208c0593e34SBrian Somers int mode; 209c0593e34SBrian Somers int unit; 210c0593e34SBrian Somers }; 211c0593e34SBrian Somers 2127cf368ebSBrian Somers static int 213c0593e34SBrian Somers ProcessArgs(int argc, char **argv, struct switches *sw) 214af57ed9fSAtsushi Murai { 2157cf368ebSBrian Somers int optc, newmode, arg; 216af57ed9fSAtsushi Murai char *cp; 217af57ed9fSAtsushi Murai 2187cf368ebSBrian Somers optc = 0; 219c0593e34SBrian Somers memset(sw, '\0', sizeof *sw); 220c0593e34SBrian Somers sw->mode = PHYS_INTERACTIVE; 221c0593e34SBrian Somers sw->unit = -1; 222c0593e34SBrian Somers 2237cf368ebSBrian Somers for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 2247cf368ebSBrian Somers cp = argv[arg] + 1; 22581358fa3SBrian Somers newmode = Nam2mode(cp); 22681358fa3SBrian Somers switch (newmode) { 22781358fa3SBrian Somers case PHYS_NONE: 228c0593e34SBrian Somers if (strcmp(cp, "nat") == 0) { 22967b072f7SBrian Somers #ifdef NONAT 230c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 231615ad4f9SBrian Somers #else 232c0593e34SBrian Somers sw->nat = 1; 233615ad4f9SBrian Somers #endif 2341ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 235c0593e34SBrian Somers } else if (strcmp(cp, "alias") == 0) { 236c0593e34SBrian Somers #ifdef NONAT 237c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 238c0593e34SBrian Somers fprintf(stderr, "%s ignored: NAT is compiled out\n", argv[arg]); 239c0593e34SBrian Somers #else 240886530abSBrian Somers log_Printf(LogWARN, "%s is deprecated\n", argv[arg]); 241886530abSBrian Somers fprintf(stderr, "%s is deprecated\n", argv[arg]); 242c0593e34SBrian Somers sw->nat = 1; 243c0593e34SBrian Somers #endif 244c0593e34SBrian Somers optc--; /* this option isn't exclusive */ 245c0593e34SBrian Somers } else if (strncmp(cp, "unit", 4) == 0) { 2469d06928dSBrian Somers optc--; /* this option isn't exclusive */ 247c0593e34SBrian Somers if (cp[4] == '\0') { 2489d06928dSBrian Somers optc--; /* nor is the argument */ 249c0593e34SBrian Somers if (++arg == argc) { 250c0593e34SBrian Somers fprintf(stderr, "-unit: Expected unit number\n"); 251c0593e34SBrian Somers Usage(); 252c0593e34SBrian Somers } else 253c0593e34SBrian Somers sw->unit = atoi(argv[arg]); 254c0593e34SBrian Somers } else 255c0593e34SBrian Somers sw->unit = atoi(cp + 4); 25667b072f7SBrian Somers } else if (strcmp(cp, "quiet") == 0) { 257c0593e34SBrian Somers sw->quiet = 1; 25867b072f7SBrian Somers optc--; /* this option isn't exclusive */ 259944f7098SBrian Somers } else 260af57ed9fSAtsushi Murai Usage(); 26181358fa3SBrian Somers break; 26281358fa3SBrian Somers 26381358fa3SBrian Somers case PHYS_ALL: 26481358fa3SBrian Somers Usage(); 26581358fa3SBrian Somers break; 26681358fa3SBrian Somers 26781358fa3SBrian Somers default: 268c0593e34SBrian Somers sw->mode = newmode; 269f6a4e748SBrian Somers if (newmode == PHYS_FOREGROUND) 270f6a4e748SBrian Somers sw->fg = 1; 27181358fa3SBrian Somers } 272af57ed9fSAtsushi Murai } 273af57ed9fSAtsushi Murai 274af57ed9fSAtsushi Murai if (optc > 1) { 27585602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2761ae349f5Scvs2svn exit(EX_START); 2771ae349f5Scvs2svn } 2781ae349f5Scvs2svn 279c0593e34SBrian Somers if (sw->mode == PHYS_AUTO && arg == argc) { 2807cf368ebSBrian Somers fprintf(stderr, "A system must be specified in auto mode.\n"); 281af57ed9fSAtsushi Murai exit(EX_START); 282af57ed9fSAtsushi Murai } 28339f94eddSBrian Somers 2847cf368ebSBrian Somers return arg; /* Don't SetLabel yet ! */ 285af57ed9fSAtsushi Murai } 286af57ed9fSAtsushi Murai 2877cf368ebSBrian Somers static void 2887cf368ebSBrian Somers CheckLabel(const char *label, struct prompt *prompt, int mode) 2897cf368ebSBrian Somers { 2907cf368ebSBrian Somers const char *err; 2917cf368ebSBrian Somers 2927cf368ebSBrian Somers if ((err = system_IsValid(label, prompt, mode)) != NULL) { 2937cf368ebSBrian Somers fprintf(stderr, "%s: %s\n", label, err); 2947cf368ebSBrian Somers if (mode == PHYS_DIRECT) 2957cf368ebSBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 2967cf368ebSBrian Somers label, err); 2977cf368ebSBrian Somers log_Close(); 2987cf368ebSBrian Somers exit(1); 2997cf368ebSBrian Somers } 3007cf368ebSBrian Somers } 3017cf368ebSBrian Somers 3027cf368ebSBrian Somers 3034ef16f24SBrian Somers int 304944f7098SBrian Somers main(int argc, char **argv) 305af57ed9fSAtsushi Murai { 3067cf368ebSBrian Somers char *name; 307756783fcSBrian Somers const char *lastlabel; 308057f1760SBrian Somers int arg, holdfd[3], label; 309057f1760SBrian Somers unsigned f; 3107a6f8720SBrian Somers struct bundle *bundle; 311b6217683SBrian Somers struct prompt *prompt; 312c0593e34SBrian Somers struct switches sw; 313e3b4c400SBrian Somers 314971abb29SBrian Somers probe_Init(); 315971abb29SBrian Somers 316108e336aSBrian Somers /* 317108e336aSBrian Somers * We open 3 descriptors to ensure that STDIN_FILENO, STDOUT_FILENO and 318108e336aSBrian Somers * STDERR_FILENO are always open. These are closed before DoLoop(), 319108e336aSBrian Somers * but *after* we've avoided the possibility of erroneously closing 320108e336aSBrian Somers * an important descriptor with close(STD{IN,OUT,ERR}_FILENO). 321108e336aSBrian Somers */ 322108e336aSBrian Somers if ((holdfd[0] = open(_PATH_DEVNULL, O_RDWR)) == -1) { 323108e336aSBrian Somers fprintf(stderr, "Cannot open %s !\n", _PATH_DEVNULL); 324108e336aSBrian Somers return 2; 325108e336aSBrian Somers } 326108e336aSBrian Somers for (f = 1; f < sizeof holdfd / sizeof *holdfd; f++) 327dd1a52b9SBrian Somers holdfd[f] = dup(holdfd[0]); 328108e336aSBrian Somers 32975240ed1SBrian Somers name = strrchr(argv[0], '/'); 330dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 3312a279fedSBrian Somers 33267b072f7SBrian Somers #ifndef NONAT 333a5625ae7SPaolo Pisati la = LibAliasInit(NULL); 3342a630835SBrian Somers #endif 335c0593e34SBrian Somers label = ProcessArgs(argc, argv, &sw); 33685b542cfSBrian Somers 33785b542cfSBrian Somers /* 338a611383fSBrian Somers * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 339a611383fSBrian Somers * output occasionally.... I must find the real reason some time. To 340a611383fSBrian Somers * display the dodgy behaviour, comment out this bit, make yourself a large 34185b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 34285b542cfSBrian Somers * command will drop chunks of data !!! 34385b542cfSBrian Somers */ 344c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) { 34585b542cfSBrian Somers close(STDIN_FILENO); 34685b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 34785b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 34885b542cfSBrian Somers return 2; 34985b542cfSBrian Somers } 35085b542cfSBrian Somers } 35185b542cfSBrian Somers 352b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 353c0593e34SBrian Somers if (sw.mode == PHYS_DIRECT) 354b6217683SBrian Somers prompt = NULL; 355ed0e9269SBrian Somers else 356b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 35712ef29a8SBrian Somers 3585106c671SBrian Somers ID0init(); 3594562be74SBrian Somers if (ID0realuid() != 0) { 3604562be74SBrian Somers char conf[200], *ptr; 3614562be74SBrian Somers 3627a66a36dSBrian Somers snprintf(conf, sizeof conf, "%s/%s", PPP_CONFDIR, CONFFILE); 3634562be74SBrian Somers do { 3641080ea25SBrian Somers struct stat sb; 3651080ea25SBrian Somers 3661080ea25SBrian Somers if (stat(conf, &sb) == 0 && sb.st_mode & S_IWOTH) { 367a33b2ef7SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 368a33b2ef7SBrian Somers conf); 3694562be74SBrian Somers return -1; 3704562be74SBrian Somers } 3714562be74SBrian Somers ptr = conf + strlen(conf)-2; 3724562be74SBrian Somers while (ptr > conf && *ptr != '/') 3734562be74SBrian Somers *ptr-- = '\0'; 3744562be74SBrian Somers } while (ptr >= conf); 3754562be74SBrian Somers } 3764562be74SBrian Somers 3777cf368ebSBrian Somers if (label < argc) 3787cf368ebSBrian Somers for (arg = label; arg < argc; arg++) 379c0593e34SBrian Somers CheckLabel(argv[arg], prompt, sw.mode); 3807cf368ebSBrian Somers else 381c0593e34SBrian Somers CheckLabel("default", prompt, sw.mode); 38212ef29a8SBrian Somers 383c0593e34SBrian Somers if (!sw.quiet) 384c0593e34SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(sw.mode)); 385ed0e9269SBrian Somers 386cf0a3940SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, sw.mode, sw.unit)) == NULL) 3874ef16f24SBrian Somers return EX_START; 388756783fcSBrian Somers 389756783fcSBrian Somers /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 390756783fcSBrian Somers 39183d1af55SBrian Somers SignalBundle = bundle; 392c0593e34SBrian Somers bundle->NatEnabled = sw.nat; 393c0593e34SBrian Somers if (sw.nat) 3940508c09aSBrian Somers opt_enable(bundle, OPT_IFACEALIAS); 39512ef29a8SBrian Somers 39630291ffbSBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 397565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3981ae349f5Scvs2svn 399dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 400dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 401dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 402dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 403dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 404e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 405565e35e5SBrian Somers 406c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) 407dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 408f91ad6b0SBrian Somers 40974457d3dSBrian Somers sig_signal(SIGUSR1, RestartServer); 410dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 411af57ed9fSAtsushi Murai 412cf0a3940SBrian Somers lastlabel = argv[argc - 1]; 4137cf368ebSBrian Somers for (arg = label; arg < argc; arg++) { 4147cf368ebSBrian Somers /* In case we use LABEL or ``set enddisc label'' */ 415756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 416cf0a3940SBrian Somers system_Select(bundle, argv[arg], CONFFILE, prompt, NULL); 4171ae349f5Scvs2svn } 4187cf368ebSBrian Somers 4197cf368ebSBrian Somers if (label < argc) 4207cf368ebSBrian Somers /* In case the last label did a ``load'' */ 421756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 4227cf368ebSBrian Somers 423c0593e34SBrian Somers if (sw.mode == PHYS_AUTO && 42430949fd4SBrian Somers ncprange_family(&bundle->ncp.ipcp.cfg.peer_range) == AF_UNSPEC) { 4257cf368ebSBrian Somers prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 4267cf368ebSBrian Somers "in auto mode.\n"); 4278390b576SBrian Somers AbortProgram(EX_START); 428af57ed9fSAtsushi Murai } 4296efd9292SBrian Somers 430f2f5156fSBrian Somers if (prompt) { 431f2f5156fSBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 432f2f5156fSBrian Somers if (!sw.quiet) 433f2f5156fSBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 434f2f5156fSBrian Somers } 435f2f5156fSBrian Somers 436c0593e34SBrian Somers if (sw.mode != PHYS_INTERACTIVE) { 437c0593e34SBrian Somers if (sw.mode != PHYS_DIRECT) { 438c0593e34SBrian Somers if (!sw.fg) { 4395cf4388bSBrian Somers int bgpipe[2]; 4406d14e2a8SJordan K. Hubbard pid_t bgpid; 441a9c6b5dfSAtsushi Murai 442c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND && pipe(bgpipe)) { 443dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 4448390b576SBrian Somers AbortProgram(EX_SOCK); 4451ae349f5Scvs2svn } 4461ae349f5Scvs2svn 4476d14e2a8SJordan K. Hubbard bgpid = fork(); 4486d14e2a8SJordan K. Hubbard if (bgpid == -1) { 449dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 4508390b576SBrian Somers AbortProgram(EX_SOCK); 4516d14e2a8SJordan K. Hubbard } 4525cf4388bSBrian Somers 4536d14e2a8SJordan K. Hubbard if (bgpid) { 4546d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 455b42135deSBrian Somers int ret; 456a9c6b5dfSAtsushi Murai 457c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND) { 4585cf4388bSBrian Somers close(bgpipe[1]); 4596d14e2a8SJordan K. Hubbard BGPid = bgpid; 46075b8d283SBrian Somers /* If we get a signal, kill the child */ 46175b8d283SBrian Somers signal(SIGHUP, KillChild); 46275b8d283SBrian Somers signal(SIGTERM, KillChild); 46375b8d283SBrian Somers signal(SIGINT, KillChild); 46475b8d283SBrian Somers signal(SIGQUIT, KillChild); 46575b8d283SBrian Somers 46675b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 467b42135deSBrian Somers while ((ret = read(bgpipe[0], &c, 1)) == 1) { 468b42135deSBrian Somers switch (c) { 469b42135deSBrian Somers case EX_NORMAL: 4700fea4ed0SBrian Somers if (!sw.quiet) { 471b42135deSBrian Somers prompt_Printf(prompt, "PPP enabled\n"); 472b42135deSBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled\n"); 4730fea4ed0SBrian Somers } 4749bf01bcbSBrian Somers break; 475b42135deSBrian Somers case EX_REDIAL: 476b42135deSBrian Somers if (!sw.quiet) 477b42135deSBrian Somers prompt_Printf(prompt, "Attempting redial\n"); 478b42135deSBrian Somers continue; 479b42135deSBrian Somers case EX_RECONNECT: 480b42135deSBrian Somers if (!sw.quiet) 481b42135deSBrian Somers prompt_Printf(prompt, "Attempting reconnect\n"); 482b42135deSBrian Somers continue; 483b42135deSBrian Somers default: 484b42135deSBrian Somers prompt_Printf(prompt, "Child failed (%s)\n", 485b42135deSBrian Somers ex_desc((int)c)); 486b42135deSBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s)\n", 487b42135deSBrian Somers ex_desc((int) c)); 488b42135deSBrian Somers } 489b42135deSBrian Somers break; 490b42135deSBrian Somers } 491b42135deSBrian Somers if (ret != 1) { 492b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 493dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4946efd9292SBrian Somers } 4955cf4388bSBrian Somers close(bgpipe[0]); 4966d14e2a8SJordan K. Hubbard } 4974ef16f24SBrian Somers return c; 498c0593e34SBrian Somers } else if (sw.mode == PHYS_BACKGROUND) { 4995cf4388bSBrian Somers close(bgpipe[0]); 5005cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 501aefd026aSBrian Somers } 502aefd026aSBrian Somers 50306b47306SBrian Somers bundle_ChangedPID(bundle); 504da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 50567b072f7SBrian Somers } 506da66dd13SBrian Somers 50767b072f7SBrian Somers /* -auto, -dedicated, -ddial, -foreground & -background */ 508b6217683SBrian Somers prompt_Destroy(prompt, 0); 5092a279fedSBrian Somers close(STDOUT_FILENO); 5102a279fedSBrian Somers close(STDERR_FILENO); 5112a279fedSBrian Somers close(STDIN_FILENO); 512c0593e34SBrian Somers if (!sw.fg) 513b6217683SBrian Somers setsid(); 514565e35e5SBrian Somers } else { 515887ff31fSBrian Somers /* 516887ff31fSBrian Somers * -direct - STDIN_FILENO gets used by physical_Open. STDOUT_FILENO 517887ff31fSBrian Somers * *may* get used in exec/pipe mode. 518887ff31fSBrian Somers */ 519565e35e5SBrian Somers prompt_TtyInit(NULL); 520565e35e5SBrian Somers close(STDERR_FILENO); 521d656a4c5SBrian Somers } 522af57ed9fSAtsushi Murai } else { 52367b072f7SBrian Somers /* -interactive */ 5242a279fedSBrian Somers close(STDERR_FILENO); 525565e35e5SBrian Somers prompt_TtyInit(prompt); 526b6217683SBrian Somers prompt_TtyCommandMode(prompt); 527b6217683SBrian Somers prompt_Required(prompt); 528af57ed9fSAtsushi Murai } 52935495becSBrian Somers 530108e336aSBrian Somers /* We can get rid of these now */ 531108e336aSBrian Somers for (f = 0; f < sizeof holdfd / sizeof *holdfd; f++) 532108e336aSBrian Somers close(holdfd[f]); 533108e336aSBrian Somers 534c0593e34SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(sw.mode)); 5350f78c7a7SBrian Somers DoLoop(bundle); 5361afedc4bSBrian Somers AbortProgram(EX_NORMAL); 537af57ed9fSAtsushi Murai 5381afedc4bSBrian Somers return EX_NORMAL; 539af57ed9fSAtsushi Murai } 540af57ed9fSAtsushi Murai 541af57ed9fSAtsushi Murai static void 5420f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 543af57ed9fSAtsushi Murai { 5448a52f3ecSBrian Somers fd_set *rfds, *wfds, *efds; 5451af29a6eSBrian Somers int i, nfds, nothing_done; 546c3899f8dSAtsushi Murai 5478a52f3ecSBrian Somers if ((rfds = mkfdset()) == NULL) { 5488a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5498a52f3ecSBrian Somers return; 5508a52f3ecSBrian Somers } 5518a52f3ecSBrian Somers 5528a52f3ecSBrian Somers if ((wfds = mkfdset()) == NULL) { 5538a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5548a52f3ecSBrian Somers free(rfds); 5558a52f3ecSBrian Somers return; 5568a52f3ecSBrian Somers } 5578a52f3ecSBrian Somers 5588a52f3ecSBrian Somers if ((efds = mkfdset()) == NULL) { 5598a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5608a52f3ecSBrian Somers free(rfds); 5618a52f3ecSBrian Somers free(wfds); 5628a52f3ecSBrian Somers return; 5638a52f3ecSBrian Somers } 5648a52f3ecSBrian Somers 565da8b7034SBrian Somers for (; !bundle_IsDead(bundle); bundle_CleanDatalinks(bundle)) { 566780700e5SAndrey A. Chernov nfds = 0; 5678a52f3ecSBrian Somers zerofdset(rfds); 5688a52f3ecSBrian Somers zerofdset(wfds); 5698a52f3ecSBrian Somers zerofdset(efds); 57084b8a6ebSAtsushi Murai 5710f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 5728a52f3ecSBrian Somers descriptor_UpdateSet(&bundle->desc, rfds, wfds, efds, &nfds); 5730f2f3eb3SBrian Somers 5740f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 5758a52f3ecSBrian Somers descriptor_UpdateSet(&server.desc, rfds, NULL, NULL, &nfds); 57607030d97SBrian Somers 5770cd8e902SBrian Somers bundle_CleanDatalinks(bundle); 5783b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 579f4768038SBrian Somers /* Don't select - we'll be here forever */ 580f4768038SBrian Somers break; 5810706ff38SBrian Somers 582486105bcSBrian Somers /* 583486105bcSBrian Somers * It's possible that we've had a signal since we last checked. If 584486105bcSBrian Somers * we don't check again before calling select(), we may end up stuck 585486105bcSBrian Somers * after having missed the event.... sig_Handle() tries to be as 586486105bcSBrian Somers * quick as possible if nothing is likely to have happened. 587486105bcSBrian Somers * This is only really likely if we block in open(... O_NONBLOCK) 588486105bcSBrian Somers * which will happen with a misconfigured device. 589486105bcSBrian Somers */ 590486105bcSBrian Somers if (sig_Handle()) 591486105bcSBrian Somers continue; 592486105bcSBrian Somers 5938a52f3ecSBrian Somers i = select(nfds, rfds, wfds, efds, NULL); 594712ae387SBrian Somers 59554cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 596dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 59724989c68SBrian Somers if (log_IsKept(LogTIMER)) { 59824989c68SBrian Somers struct timeval t; 59924989c68SBrian Somers 60024989c68SBrian Somers for (i = 0; i <= nfds; i++) { 6018a52f3ecSBrian Somers if (FD_ISSET(i, rfds)) { 60224989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 6038a52f3ecSBrian Somers FD_CLR(i, rfds); 60424989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6058a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 60624989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 607af57ed9fSAtsushi Murai break; 608af57ed9fSAtsushi Murai } 60924989c68SBrian Somers } 6108a52f3ecSBrian Somers if (FD_ISSET(i, wfds)) { 61124989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 6128a52f3ecSBrian Somers FD_CLR(i, wfds); 61324989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6148a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 61524989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 616af57ed9fSAtsushi Murai break; 617af57ed9fSAtsushi Murai } 618e0d3e233SAndrey A. Chernov } 6198a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 62024989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 6218a52f3ecSBrian Somers FD_CLR(i, efds); 62224989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 6238a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 62424989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 62558f264e1SBrian Somers break; 62658f264e1SBrian Somers } 62724989c68SBrian Somers } 62824989c68SBrian Somers } 62924989c68SBrian Somers } 63058f264e1SBrian Somers break; 631de451c68SBrian Somers } 632de451c68SBrian Somers 633f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Select returns %d\n", i); 634f0cdd9c0SBrian Somers 63554cd8e13SBrian Somers sig_Handle(); 63654cd8e13SBrian Somers 63754cd8e13SBrian Somers if (i <= 0) 63854cd8e13SBrian Somers continue; 63954cd8e13SBrian Somers 6403006ec67SBrian Somers for (i = 0; i <= nfds; i++) 6418a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 6428e7bd08eSBrian Somers log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 6438e7bd08eSBrian Somers /* We deal gracefully with link descriptor exceptions */ 644991c2a7bSBrian Somers if (!bundle_Exception(bundle, i)) { 645991c2a7bSBrian Somers log_Printf(LogERROR, "Exception cannot be handled !\n"); 6461ae349f5Scvs2svn break; 6471ae349f5Scvs2svn } 648991c2a7bSBrian Somers } 649c60f92caSBrian Somers 650b7c5748eSBrian Somers if (i <= nfds) 651b7c5748eSBrian Somers break; 652b7c5748eSBrian Somers 6531af29a6eSBrian Somers nothing_done = 1; 6541af29a6eSBrian Somers 6558a52f3ecSBrian Somers if (descriptor_IsSet(&server.desc, rfds)) { 6568a52f3ecSBrian Somers descriptor_Read(&server.desc, bundle, rfds); 6571af29a6eSBrian Somers nothing_done = 0; 6581af29a6eSBrian Somers } 6591af29a6eSBrian Somers 6608a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, rfds)) { 6618a52f3ecSBrian Somers descriptor_Read(&bundle->desc, bundle, rfds); 6621af29a6eSBrian Somers nothing_done = 0; 6631af29a6eSBrian Somers } 66442d4d396SBrian Somers 6658a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, wfds)) 666fb11a9c2SBrian Somers if (descriptor_Write(&bundle->desc, bundle, wfds) <= 0 && nothing_done) { 6671af29a6eSBrian Somers /* 668fb11a9c2SBrian Somers * This is disastrous. The OS has told us that something is 6691af29a6eSBrian Somers * writable, and all our write()s have failed. Rather than 6701af29a6eSBrian Somers * going back immediately to do our UpdateSet()s and select(), 6711af29a6eSBrian Somers * we sleep for a bit to avoid gobbling up all cpu time. 6721af29a6eSBrian Somers */ 6731af29a6eSBrian Somers struct timeval t; 6742f786681SBrian Somers 6751af29a6eSBrian Somers t.tv_sec = 0; 6761af29a6eSBrian Somers t.tv_usec = 100000; 6771af29a6eSBrian Somers select(0, NULL, NULL, NULL, &t); 6781af29a6eSBrian Somers } 679da8b7034SBrian Somers } 680565e35e5SBrian Somers 681dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 682af57ed9fSAtsushi Murai } 683