1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * User Process PPP 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 2097d92980SPeter Wemm * $FreeBSD$ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai */ 242764b86aSBrian Somers 25972a1bcfSBrian Somers #include <sys/param.h> 2675240ed1SBrian Somers #include <netinet/in.h> 27a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 28a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 29565e35e5SBrian Somers #include <sys/un.h> 306b457978SBrian Somers #include <sys/socket.h> 316b457978SBrian Somers #include <net/route.h> 3275240ed1SBrian Somers 3375240ed1SBrian Somers #include <errno.h> 3475240ed1SBrian Somers #include <fcntl.h> 3575240ed1SBrian Somers #include <paths.h> 3675240ed1SBrian Somers #include <signal.h> 3775240ed1SBrian Somers #include <stdio.h> 38c0593e34SBrian Somers #include <stdlib.h> 3975240ed1SBrian Somers #include <string.h> 4075240ed1SBrian Somers #include <sys/time.h> 4175240ed1SBrian Somers #include <termios.h> 4275240ed1SBrian Somers #include <unistd.h> 431080ea25SBrian Somers #include <sys/stat.h> 4475240ed1SBrian Somers 4567b072f7SBrian Somers #ifndef NONAT 4610e629b9SBrian Somers #ifdef LOCALNAT 477884358fSBrian Somers #include "alias.h" 4810e629b9SBrian Somers #else 4910e629b9SBrian Somers #include <alias.h> 501595bacdSBrian Somers #endif 511595bacdSBrian Somers #endif 5210e629b9SBrian Somers 535d9e6103SBrian Somers #include "layer.h" 541af29a6eSBrian Somers #include "probe.h" 5575240ed1SBrian Somers #include "mbuf.h" 5675240ed1SBrian Somers #include "log.h" 5775240ed1SBrian Somers #include "defs.h" 585106c671SBrian Somers #include "id.h" 5975240ed1SBrian Somers #include "timer.h" 6075240ed1SBrian Somers #include "fsm.h" 61879ed6faSBrian Somers #include "lqr.h" 62af57ed9fSAtsushi Murai #include "hdlc.h" 63af57ed9fSAtsushi Murai #include "lcp.h" 640053cc58SBrian Somers #include "ccp.h" 6529e275ceSBrian Somers #include "iplist.h" 6629e275ceSBrian Somers #include "throughput.h" 67eaa4df37SBrian Somers #include "slcompress.h" 68af57ed9fSAtsushi Murai #include "ipcp.h" 6984b8a6ebSAtsushi Murai #include "filter.h" 702f786681SBrian Somers #include "descriptor.h" 713b0f8d2eSBrian Somers #include "link.h" 723b0f8d2eSBrian Somers #include "mp.h" 73972a1bcfSBrian Somers #ifndef NORADIUS 74972a1bcfSBrian Somers #include "radius.h" 75972a1bcfSBrian Somers #endif 765828db6dSBrian Somers #include "bundle.h" 771ae349f5Scvs2svn #include "auth.h" 78ed6a16c1SPoul-Henning Kamp #include "systems.h" 79f5ff0f7cSBrian Somers #include "sig.h" 8075240ed1SBrian Somers #include "main.h" 8177ff88adSBrian Somers #include "server.h" 8285b542cfSBrian Somers #include "prompt.h" 83b6dec9f0SBrian Somers #include "chat.h" 84e2ebb036SBrian Somers #include "chap.h" 8592b09558SBrian Somers #include "cbcp.h" 863006ec67SBrian Somers #include "datalink.h" 878fa6ebe4SBrian Somers #include "iface.h" 8853c9f6c0SAtsushi Murai 8953c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 9053c9f6c0SAtsushi Murai #ifdef O_NDELAY 9153c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 9253c9f6c0SAtsushi Murai #endif 9353c9f6c0SAtsushi Murai #endif 94af57ed9fSAtsushi Murai 950f78c7a7SBrian Somers static void DoLoop(struct bundle *); 9675240ed1SBrian Somers static void TerminalStop(int); 9775240ed1SBrian Somers 9883d1af55SBrian Somers static struct bundle *SignalBundle; 99b6217683SBrian Somers static struct prompt *SignalPrompt; 100c3899f8dSAtsushi Murai 101c3899f8dSAtsushi Murai void 102944f7098SBrian Somers Cleanup(int excode) 103af57ed9fSAtsushi Murai { 104a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 1059c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 1066e4959f0SBrian Somers } 107af57ed9fSAtsushi Murai 1081afedc4bSBrian Somers void 1091afedc4bSBrian Somers AbortProgram(int excode) 1101afedc4bSBrian Somers { 111dd7e2610SBrian Somers server_Close(SignalBundle); 112dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 1139c81b87dSBrian Somers bundle_Close(SignalBundle, NULL, CLOSE_STAYDOWN); 11468a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 115dd7e2610SBrian Somers log_Close(); 116af57ed9fSAtsushi Murai exit(excode); 117af57ed9fSAtsushi Murai } 118af57ed9fSAtsushi Murai 119af57ed9fSAtsushi Murai static void 120944f7098SBrian Somers CloseConnection(int signo) 121af57ed9fSAtsushi Murai { 122368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 123dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 124dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 125899011c4SBrian Somers bundle_Down(SignalBundle, CLOSE_STAYDOWN); 126dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1276d14e2a8SJordan K. Hubbard } 128af57ed9fSAtsushi Murai 129af57ed9fSAtsushi Murai static void 130944f7098SBrian Somers CloseSession(int signo) 131af57ed9fSAtsushi Murai { 132dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 133af57ed9fSAtsushi Murai Cleanup(EX_TERM); 134af57ed9fSAtsushi Murai } 135c3899f8dSAtsushi Murai 13675b8d283SBrian Somers static pid_t BGPid = 0; 13775b8d283SBrian Somers 13875b8d283SBrian Somers static void 13975b8d283SBrian Somers KillChild(int signo) 14075b8d283SBrian Somers { 141ac37ab22SBrian Somers signal(signo, SIG_IGN); 142dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 14375b8d283SBrian Somers kill(BGPid, SIGINT); 14475b8d283SBrian Somers } 14575b8d283SBrian Somers 146c3899f8dSAtsushi Murai static void 147b6e82f33SBrian Somers TerminalCont(int signo) 148c3899f8dSAtsushi Murai { 149f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 150f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 151c3899f8dSAtsushi Murai } 152c3899f8dSAtsushi Murai 153c3899f8dSAtsushi Murai static void 154944f7098SBrian Somers TerminalStop(int signo) 155c3899f8dSAtsushi Murai { 156f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 157f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 158f91ad6b0SBrian Somers raise(SIGSTOP); 1594ef16f24SBrian Somers } 1604ef16f24SBrian Somers 1618ea8442cSBrian Somers static void 1628ea8442cSBrian Somers BringDownServer(int signo) 1638ea8442cSBrian Somers { 164b6217683SBrian Somers /* Drops all child prompts too ! */ 16574457d3dSBrian Somers if (server_Close(SignalBundle)) 16674457d3dSBrian Somers log_Printf(LogPHASE, "Closed server socket\n"); 16774457d3dSBrian Somers } 16874457d3dSBrian Somers 16974457d3dSBrian Somers static void 17074457d3dSBrian Somers RestartServer(int signo) 17174457d3dSBrian Somers { 17274457d3dSBrian Somers /* Drops all child prompts and re-opens the socket */ 17374457d3dSBrian Somers server_Reopen(SignalBundle); 1748ea8442cSBrian Somers } 1758ea8442cSBrian Somers 17675240ed1SBrian Somers static void 177b6e82f33SBrian Somers Usage(void) 178af57ed9fSAtsushi Murai { 1799b996792SBrian Somers fprintf(stderr, "Usage: ppp [-auto | -foreground | -background | -direct |" 1809b996792SBrian Somers " -dedicated | -ddial | -interactive]" 181b6e82f33SBrian Somers #ifndef NOALIAS 18267b072f7SBrian Somers " [-nat]" 183b6e82f33SBrian Somers #endif 184c0593e34SBrian Somers " [-quiet] [-unit N] [system ...]\n"); 185af57ed9fSAtsushi Murai exit(EX_START); 186af57ed9fSAtsushi Murai } 187af57ed9fSAtsushi Murai 188c0593e34SBrian Somers struct switches { 189c0593e34SBrian Somers unsigned nat : 1; 190c0593e34SBrian Somers unsigned fg : 1; 191c0593e34SBrian Somers unsigned quiet : 1; 192c0593e34SBrian Somers int mode; 193c0593e34SBrian Somers int unit; 194c0593e34SBrian Somers }; 195c0593e34SBrian Somers 1967cf368ebSBrian Somers static int 197c0593e34SBrian Somers ProcessArgs(int argc, char **argv, struct switches *sw) 198af57ed9fSAtsushi Murai { 1997cf368ebSBrian Somers int optc, newmode, arg; 200af57ed9fSAtsushi Murai char *cp; 201af57ed9fSAtsushi Murai 2027cf368ebSBrian Somers optc = 0; 203c0593e34SBrian Somers memset(sw, '\0', sizeof *sw); 204c0593e34SBrian Somers sw->mode = PHYS_INTERACTIVE; 205c0593e34SBrian Somers sw->unit = -1; 206c0593e34SBrian Somers 2077cf368ebSBrian Somers for (arg = 1; arg < argc && *argv[arg] == '-'; arg++, optc++) { 2087cf368ebSBrian Somers cp = argv[arg] + 1; 20981358fa3SBrian Somers newmode = Nam2mode(cp); 21081358fa3SBrian Somers switch (newmode) { 21181358fa3SBrian Somers case PHYS_NONE: 212c0593e34SBrian Somers if (strcmp(cp, "nat") == 0) { 21367b072f7SBrian Somers #ifdef NONAT 214c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 215615ad4f9SBrian Somers #else 216c0593e34SBrian Somers sw->nat = 1; 217615ad4f9SBrian Somers #endif 2181ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 219c0593e34SBrian Somers } else if (strcmp(cp, "alias") == 0) { 220c0593e34SBrian Somers #ifdef NONAT 221c0593e34SBrian Somers log_Printf(LogWARN, "%s ignored: NAT is compiled out\n", argv[arg]); 222c0593e34SBrian Somers fprintf(stderr, "%s ignored: NAT is compiled out\n", argv[arg]); 223c0593e34SBrian Somers #else 224886530abSBrian Somers log_Printf(LogWARN, "%s is deprecated\n", argv[arg]); 225886530abSBrian Somers fprintf(stderr, "%s is deprecated\n", argv[arg]); 226c0593e34SBrian Somers sw->nat = 1; 227c0593e34SBrian Somers #endif 228c0593e34SBrian Somers optc--; /* this option isn't exclusive */ 229c0593e34SBrian Somers } else if (strncmp(cp, "unit", 4) == 0) { 2309d06928dSBrian Somers optc--; /* this option isn't exclusive */ 231c0593e34SBrian Somers if (cp[4] == '\0') { 2329d06928dSBrian Somers optc--; /* nor is the argument */ 233c0593e34SBrian Somers if (++arg == argc) { 234c0593e34SBrian Somers fprintf(stderr, "-unit: Expected unit number\n"); 235c0593e34SBrian Somers Usage(); 236c0593e34SBrian Somers } else 237c0593e34SBrian Somers sw->unit = atoi(argv[arg]); 238c0593e34SBrian Somers } else 239c0593e34SBrian Somers sw->unit = atoi(cp + 4); 24067b072f7SBrian Somers } else if (strcmp(cp, "quiet") == 0) { 241c0593e34SBrian Somers sw->quiet = 1; 24267b072f7SBrian Somers optc--; /* this option isn't exclusive */ 243944f7098SBrian Somers } else 244af57ed9fSAtsushi Murai Usage(); 24581358fa3SBrian Somers break; 24681358fa3SBrian Somers 24781358fa3SBrian Somers case PHYS_ALL: 24881358fa3SBrian Somers Usage(); 24981358fa3SBrian Somers break; 25081358fa3SBrian Somers 25181358fa3SBrian Somers default: 252c0593e34SBrian Somers sw->mode = newmode; 253f6a4e748SBrian Somers if (newmode == PHYS_FOREGROUND) 254f6a4e748SBrian Somers sw->fg = 1; 25581358fa3SBrian Somers } 256af57ed9fSAtsushi Murai } 257af57ed9fSAtsushi Murai 258af57ed9fSAtsushi Murai if (optc > 1) { 25985602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2601ae349f5Scvs2svn exit(EX_START); 2611ae349f5Scvs2svn } 2621ae349f5Scvs2svn 263c0593e34SBrian Somers if (sw->mode == PHYS_AUTO && arg == argc) { 2647cf368ebSBrian Somers fprintf(stderr, "A system must be specified in auto mode.\n"); 265af57ed9fSAtsushi Murai exit(EX_START); 266af57ed9fSAtsushi Murai } 26739f94eddSBrian Somers 2687cf368ebSBrian Somers return arg; /* Don't SetLabel yet ! */ 269af57ed9fSAtsushi Murai } 270af57ed9fSAtsushi Murai 2717cf368ebSBrian Somers static void 2727cf368ebSBrian Somers CheckLabel(const char *label, struct prompt *prompt, int mode) 2737cf368ebSBrian Somers { 2747cf368ebSBrian Somers const char *err; 2757cf368ebSBrian Somers 2767cf368ebSBrian Somers if ((err = system_IsValid(label, prompt, mode)) != NULL) { 2777cf368ebSBrian Somers fprintf(stderr, "%s: %s\n", label, err); 2787cf368ebSBrian Somers if (mode == PHYS_DIRECT) 2797cf368ebSBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection: %s\n", 2807cf368ebSBrian Somers label, err); 2817cf368ebSBrian Somers log_Close(); 2827cf368ebSBrian Somers exit(1); 2837cf368ebSBrian Somers } 2847cf368ebSBrian Somers } 2857cf368ebSBrian Somers 2867cf368ebSBrian Somers 2874ef16f24SBrian Somers int 288944f7098SBrian Somers main(int argc, char **argv) 289af57ed9fSAtsushi Murai { 2907cf368ebSBrian Somers char *name; 291756783fcSBrian Somers const char *lastlabel; 2928a52f3ecSBrian Somers int label, arg; 2937a6f8720SBrian Somers struct bundle *bundle; 294b6217683SBrian Somers struct prompt *prompt; 295c0593e34SBrian Somers struct switches sw; 296e3b4c400SBrian Somers 29775240ed1SBrian Somers name = strrchr(argv[0], '/'); 298dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 2992a279fedSBrian Somers 30067b072f7SBrian Somers #ifndef NONAT 3012a630835SBrian Somers PacketAliasInit(); 3022a630835SBrian Somers #endif 303c0593e34SBrian Somers label = ProcessArgs(argc, argv, &sw); 30485b542cfSBrian Somers 30585b542cfSBrian Somers /* 306a611383fSBrian Somers * A FreeBSD & OpenBSD hack to dodge a bug in the tty driver that drops 307a611383fSBrian Somers * output occasionally.... I must find the real reason some time. To 308a611383fSBrian Somers * display the dodgy behaviour, comment out this bit, make yourself a large 30985b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 31085b542cfSBrian Somers * command will drop chunks of data !!! 31185b542cfSBrian Somers */ 312c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) { 31385b542cfSBrian Somers close(STDIN_FILENO); 31485b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 31585b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 31685b542cfSBrian Somers return 2; 31785b542cfSBrian Somers } 31885b542cfSBrian Somers } 31985b542cfSBrian Somers 320b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 321c0593e34SBrian Somers if (sw.mode == PHYS_DIRECT) 322b6217683SBrian Somers prompt = NULL; 323ed0e9269SBrian Somers else 324b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 32512ef29a8SBrian Somers 3265106c671SBrian Somers ID0init(); 3274562be74SBrian Somers if (ID0realuid() != 0) { 3284562be74SBrian Somers char conf[200], *ptr; 3294562be74SBrian Somers 3307a66a36dSBrian Somers snprintf(conf, sizeof conf, "%s/%s", PPP_CONFDIR, CONFFILE); 3314562be74SBrian Somers do { 3321080ea25SBrian Somers struct stat sb; 3331080ea25SBrian Somers 3341080ea25SBrian Somers if (stat(conf, &sb) == 0 && sb.st_mode & S_IWOTH) { 335a33b2ef7SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", 336a33b2ef7SBrian Somers conf); 3374562be74SBrian Somers return -1; 3384562be74SBrian Somers } 3394562be74SBrian Somers ptr = conf + strlen(conf)-2; 3404562be74SBrian Somers while (ptr > conf && *ptr != '/') 3414562be74SBrian Somers *ptr-- = '\0'; 3424562be74SBrian Somers } while (ptr >= conf); 3434562be74SBrian Somers } 3444562be74SBrian Somers 3457cf368ebSBrian Somers if (label < argc) 3467cf368ebSBrian Somers for (arg = label; arg < argc; arg++) 347c0593e34SBrian Somers CheckLabel(argv[arg], prompt, sw.mode); 3487cf368ebSBrian Somers else 349c0593e34SBrian Somers CheckLabel("default", prompt, sw.mode); 35012ef29a8SBrian Somers 351c0593e34SBrian Somers if (!sw.quiet) 352c0593e34SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(sw.mode)); 353ed0e9269SBrian Somers 354cf0a3940SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, sw.mode, sw.unit)) == NULL) 3554ef16f24SBrian Somers return EX_START; 356756783fcSBrian Somers 357756783fcSBrian Somers /* NOTE: We may now have changed argv[1] via a ``set proctitle'' */ 358756783fcSBrian Somers 3590f2f3eb3SBrian Somers if (prompt) { 3600f2f3eb3SBrian Somers prompt->bundle = bundle; /* couldn't do it earlier */ 361c0593e34SBrian Somers if (!sw.quiet) 3628fa6ebe4SBrian Somers prompt_Printf(prompt, "Using interface: %s\n", bundle->iface->name); 3630f2f3eb3SBrian Somers } 36483d1af55SBrian Somers SignalBundle = bundle; 365c0593e34SBrian Somers bundle->NatEnabled = sw.nat; 366c0593e34SBrian Somers if (sw.nat) 3678fa6ebe4SBrian Somers bundle->cfg.opt |= OPT_IFACEALIAS; 36812ef29a8SBrian Somers 36930291ffbSBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt, NULL) < 0) 370565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3711ae349f5Scvs2svn 372dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 373dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 374dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 375dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 376dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 377e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 378565e35e5SBrian Somers 379c0593e34SBrian Somers if (sw.mode == PHYS_INTERACTIVE) 380dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 381f91ad6b0SBrian Somers 38274457d3dSBrian Somers sig_signal(SIGUSR1, RestartServer); 383dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 384af57ed9fSAtsushi Murai 385cf0a3940SBrian Somers lastlabel = argv[argc - 1]; 3867cf368ebSBrian Somers for (arg = label; arg < argc; arg++) { 3877cf368ebSBrian Somers /* In case we use LABEL or ``set enddisc label'' */ 388756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 389cf0a3940SBrian Somers system_Select(bundle, argv[arg], CONFFILE, prompt, NULL); 3901ae349f5Scvs2svn } 3917cf368ebSBrian Somers 3927cf368ebSBrian Somers if (label < argc) 3937cf368ebSBrian Somers /* In case the last label did a ``load'' */ 394756783fcSBrian Somers bundle_SetLabel(bundle, lastlabel); 3957cf368ebSBrian Somers 396c0593e34SBrian Somers if (sw.mode == PHYS_AUTO && 3975828db6dSBrian Somers bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 3987cf368ebSBrian Somers prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address " 3997cf368ebSBrian Somers "in auto mode.\n"); 4008390b576SBrian Somers AbortProgram(EX_START); 401af57ed9fSAtsushi Murai } 4026efd9292SBrian Somers 403c0593e34SBrian Somers if (sw.mode != PHYS_INTERACTIVE) { 404c0593e34SBrian Somers if (sw.mode != PHYS_DIRECT) { 405c0593e34SBrian Somers if (!sw.fg) { 4065cf4388bSBrian Somers int bgpipe[2]; 4076d14e2a8SJordan K. Hubbard pid_t bgpid; 408a9c6b5dfSAtsushi Murai 409c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND && pipe(bgpipe)) { 410dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 4118390b576SBrian Somers AbortProgram(EX_SOCK); 4121ae349f5Scvs2svn } 4131ae349f5Scvs2svn 4146d14e2a8SJordan K. Hubbard bgpid = fork(); 4156d14e2a8SJordan K. Hubbard if (bgpid == -1) { 416dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 4178390b576SBrian Somers AbortProgram(EX_SOCK); 4186d14e2a8SJordan K. Hubbard } 4195cf4388bSBrian Somers 4206d14e2a8SJordan K. Hubbard if (bgpid) { 4216d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 422b42135deSBrian Somers int ret; 423a9c6b5dfSAtsushi Murai 424c0593e34SBrian Somers if (sw.mode == PHYS_BACKGROUND) { 4255cf4388bSBrian Somers close(bgpipe[1]); 4266d14e2a8SJordan K. Hubbard BGPid = bgpid; 42775b8d283SBrian Somers /* If we get a signal, kill the child */ 42875b8d283SBrian Somers signal(SIGHUP, KillChild); 42975b8d283SBrian Somers signal(SIGTERM, KillChild); 43075b8d283SBrian Somers signal(SIGINT, KillChild); 43175b8d283SBrian Somers signal(SIGQUIT, KillChild); 43275b8d283SBrian Somers 43375b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 434b42135deSBrian Somers while ((ret = read(bgpipe[0], &c, 1)) == 1) { 435b42135deSBrian Somers switch (c) { 436b42135deSBrian Somers case EX_NORMAL: 437b42135deSBrian Somers prompt_Printf(prompt, "PPP enabled\n"); 438b42135deSBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled\n"); 4399bf01bcbSBrian Somers break; 440b42135deSBrian Somers case EX_REDIAL: 441b42135deSBrian Somers if (!sw.quiet) 442b42135deSBrian Somers prompt_Printf(prompt, "Attempting redial\n"); 443b42135deSBrian Somers continue; 444b42135deSBrian Somers case EX_RECONNECT: 445b42135deSBrian Somers if (!sw.quiet) 446b42135deSBrian Somers prompt_Printf(prompt, "Attempting reconnect\n"); 447b42135deSBrian Somers continue; 448b42135deSBrian Somers default: 449b42135deSBrian Somers prompt_Printf(prompt, "Child failed (%s)\n", 450b42135deSBrian Somers ex_desc((int)c)); 451b42135deSBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s)\n", 452b42135deSBrian Somers ex_desc((int) c)); 453b42135deSBrian Somers } 454b42135deSBrian Somers break; 455b42135deSBrian Somers } 456b42135deSBrian Somers if (ret != 1) { 457b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 458dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4596efd9292SBrian Somers } 4605cf4388bSBrian Somers close(bgpipe[0]); 4616d14e2a8SJordan K. Hubbard } 4624ef16f24SBrian Somers return c; 463c0593e34SBrian Somers } else if (sw.mode == PHYS_BACKGROUND) { 4645cf4388bSBrian Somers close(bgpipe[0]); 4655cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 466aefd026aSBrian Somers } 467aefd026aSBrian Somers 46806b47306SBrian Somers bundle_ChangedPID(bundle); 469da66dd13SBrian Somers bundle_LockTun(bundle); /* we have a new pid */ 47067b072f7SBrian Somers } 471da66dd13SBrian Somers 47267b072f7SBrian Somers /* -auto, -dedicated, -ddial, -foreground & -background */ 473b6217683SBrian Somers prompt_Destroy(prompt, 0); 4742a279fedSBrian Somers close(STDOUT_FILENO); 4752a279fedSBrian Somers close(STDERR_FILENO); 4762a279fedSBrian Somers close(STDIN_FILENO); 477c0593e34SBrian Somers if (!sw.fg) 478b6217683SBrian Somers setsid(); 479565e35e5SBrian Somers } else { 48067b072f7SBrian Somers /* -direct - STDIN_FILENO gets used by physical_Open */ 481565e35e5SBrian Somers prompt_TtyInit(NULL); 482565e35e5SBrian Somers close(STDOUT_FILENO); 483565e35e5SBrian Somers close(STDERR_FILENO); 484d656a4c5SBrian Somers } 485af57ed9fSAtsushi Murai } else { 48667b072f7SBrian Somers /* -interactive */ 4872a279fedSBrian Somers close(STDERR_FILENO); 488565e35e5SBrian Somers prompt_TtyInit(prompt); 489b6217683SBrian Somers prompt_TtyCommandMode(prompt); 490b6217683SBrian Somers prompt_Required(prompt); 491af57ed9fSAtsushi Murai } 49235495becSBrian Somers 493c0593e34SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(sw.mode)); 4940f78c7a7SBrian Somers DoLoop(bundle); 4951afedc4bSBrian Somers AbortProgram(EX_NORMAL); 496af57ed9fSAtsushi Murai 4971afedc4bSBrian Somers return EX_NORMAL; 498af57ed9fSAtsushi Murai } 499af57ed9fSAtsushi Murai 500af57ed9fSAtsushi Murai static void 5010f78c7a7SBrian Somers DoLoop(struct bundle *bundle) 502af57ed9fSAtsushi Murai { 5038a52f3ecSBrian Somers fd_set *rfds, *wfds, *efds; 5041af29a6eSBrian Somers int i, nfds, nothing_done; 5051af29a6eSBrian Somers struct probe probe; 5061af29a6eSBrian Somers 5071af29a6eSBrian Somers probe_Init(&probe); 508c3899f8dSAtsushi Murai 5098a52f3ecSBrian Somers if ((rfds = mkfdset()) == NULL) { 5108a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5118a52f3ecSBrian Somers return; 5128a52f3ecSBrian Somers } 5138a52f3ecSBrian Somers 5148a52f3ecSBrian Somers if ((wfds = mkfdset()) == NULL) { 5158a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5168a52f3ecSBrian Somers free(rfds); 5178a52f3ecSBrian Somers return; 5188a52f3ecSBrian Somers } 5198a52f3ecSBrian Somers 5208a52f3ecSBrian Somers if ((efds = mkfdset()) == NULL) { 5218a52f3ecSBrian Somers log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); 5228a52f3ecSBrian Somers free(rfds); 5238a52f3ecSBrian Somers free(wfds); 5248a52f3ecSBrian Somers return; 5258a52f3ecSBrian Somers } 5268a52f3ecSBrian Somers 527da8b7034SBrian Somers for (; !bundle_IsDead(bundle); bundle_CleanDatalinks(bundle)) { 528780700e5SAndrey A. Chernov nfds = 0; 5298a52f3ecSBrian Somers zerofdset(rfds); 5308a52f3ecSBrian Somers zerofdset(wfds); 5318a52f3ecSBrian Somers zerofdset(efds); 53284b8a6ebSAtsushi Murai 5330f2f3eb3SBrian Somers /* All our datalinks, the tun device and the MP socket */ 5348a52f3ecSBrian Somers descriptor_UpdateSet(&bundle->desc, rfds, wfds, efds, &nfds); 5350f2f3eb3SBrian Somers 5360f2f3eb3SBrian Somers /* All our prompts and the diagnostic socket */ 5378a52f3ecSBrian Somers descriptor_UpdateSet(&server.desc, rfds, NULL, NULL, &nfds); 53807030d97SBrian Somers 5390cd8e902SBrian Somers bundle_CleanDatalinks(bundle); 5403b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 541f4768038SBrian Somers /* Don't select - we'll be here forever */ 542f4768038SBrian Somers break; 5430706ff38SBrian Somers 544486105bcSBrian Somers /* 545486105bcSBrian Somers * It's possible that we've had a signal since we last checked. If 546486105bcSBrian Somers * we don't check again before calling select(), we may end up stuck 547486105bcSBrian Somers * after having missed the event.... sig_Handle() tries to be as 548486105bcSBrian Somers * quick as possible if nothing is likely to have happened. 549486105bcSBrian Somers * This is only really likely if we block in open(... O_NONBLOCK) 550486105bcSBrian Somers * which will happen with a misconfigured device. 551486105bcSBrian Somers */ 552486105bcSBrian Somers if (sig_Handle()) 553486105bcSBrian Somers continue; 554486105bcSBrian Somers 5558a52f3ecSBrian Somers i = select(nfds, rfds, wfds, efds, NULL); 556712ae387SBrian Somers 55754cd8e13SBrian Somers if (i < 0 && errno != EINTR) { 558dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 55924989c68SBrian Somers if (log_IsKept(LogTIMER)) { 56024989c68SBrian Somers struct timeval t; 56124989c68SBrian Somers 56224989c68SBrian Somers for (i = 0; i <= nfds; i++) { 5638a52f3ecSBrian Somers if (FD_ISSET(i, rfds)) { 56424989c68SBrian Somers log_Printf(LogTIMER, "Read set contains %d\n", i); 5658a52f3ecSBrian Somers FD_CLR(i, rfds); 56624989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 5678a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 56824989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 569af57ed9fSAtsushi Murai break; 570af57ed9fSAtsushi Murai } 57124989c68SBrian Somers } 5728a52f3ecSBrian Somers if (FD_ISSET(i, wfds)) { 57324989c68SBrian Somers log_Printf(LogTIMER, "Write set contains %d\n", i); 5748a52f3ecSBrian Somers FD_CLR(i, wfds); 57524989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 5768a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 57724989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 578af57ed9fSAtsushi Murai break; 579af57ed9fSAtsushi Murai } 580e0d3e233SAndrey A. Chernov } 5818a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 58224989c68SBrian Somers log_Printf(LogTIMER, "Error set contains %d\n", i); 5838a52f3ecSBrian Somers FD_CLR(i, efds); 58424989c68SBrian Somers t.tv_sec = t.tv_usec = 0; 5858a52f3ecSBrian Somers if (select(nfds, rfds, wfds, efds, &t) != -1) { 58624989c68SBrian Somers log_Printf(LogTIMER, "The culprit !\n"); 58758f264e1SBrian Somers break; 58858f264e1SBrian Somers } 58924989c68SBrian Somers } 59024989c68SBrian Somers } 59124989c68SBrian Somers } 59258f264e1SBrian Somers break; 593de451c68SBrian Somers } 594de451c68SBrian Somers 595f0cdd9c0SBrian Somers log_Printf(LogTIMER, "Select returns %d\n", i); 596f0cdd9c0SBrian Somers 59754cd8e13SBrian Somers sig_Handle(); 59854cd8e13SBrian Somers 59954cd8e13SBrian Somers if (i <= 0) 60054cd8e13SBrian Somers continue; 60154cd8e13SBrian Somers 6023006ec67SBrian Somers for (i = 0; i <= nfds; i++) 6038a52f3ecSBrian Somers if (FD_ISSET(i, efds)) { 6048e7bd08eSBrian Somers log_Printf(LogPHASE, "Exception detected on descriptor %d\n", i); 6058e7bd08eSBrian Somers /* We deal gracefully with link descriptor exceptions */ 606991c2a7bSBrian Somers if (!bundle_Exception(bundle, i)) { 607991c2a7bSBrian Somers log_Printf(LogERROR, "Exception cannot be handled !\n"); 6081ae349f5Scvs2svn break; 6091ae349f5Scvs2svn } 610991c2a7bSBrian Somers } 611c60f92caSBrian Somers 612b7c5748eSBrian Somers if (i <= nfds) 613b7c5748eSBrian Somers break; 614b7c5748eSBrian Somers 6151af29a6eSBrian Somers nothing_done = 1; 6161af29a6eSBrian Somers 6178a52f3ecSBrian Somers if (descriptor_IsSet(&server.desc, rfds)) { 6188a52f3ecSBrian Somers descriptor_Read(&server.desc, bundle, rfds); 6191af29a6eSBrian Somers nothing_done = 0; 6201af29a6eSBrian Somers } 6211af29a6eSBrian Somers 6228a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, rfds)) { 6238a52f3ecSBrian Somers descriptor_Read(&bundle->desc, bundle, rfds); 6241af29a6eSBrian Somers nothing_done = 0; 6251af29a6eSBrian Somers } 62642d4d396SBrian Somers 6278a52f3ecSBrian Somers if (descriptor_IsSet(&bundle->desc, wfds)) 6288a52f3ecSBrian Somers if (!descriptor_Write(&bundle->desc, bundle, wfds) && nothing_done) { 6291af29a6eSBrian Somers /* 6301af29a6eSBrian Somers * This is disasterous. The OS has told us that something is 6311af29a6eSBrian Somers * writable, and all our write()s have failed. Rather than 6321af29a6eSBrian Somers * going back immediately to do our UpdateSet()s and select(), 6331af29a6eSBrian Somers * we sleep for a bit to avoid gobbling up all cpu time. 6341af29a6eSBrian Somers */ 6351af29a6eSBrian Somers struct timeval t; 6362f786681SBrian Somers 6371af29a6eSBrian Somers t.tv_sec = 0; 6381af29a6eSBrian Somers t.tv_usec = 100000; 6391af29a6eSBrian Somers select(0, NULL, NULL, NULL, &t); 6401af29a6eSBrian Somers } 641da8b7034SBrian Somers } 642565e35e5SBrian Somers 643dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 644af57ed9fSAtsushi Murai } 645