11ae349f5Scvs2svn /* 21ae349f5Scvs2svn * User Process PPP 31ae349f5Scvs2svn * 41ae349f5Scvs2svn * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51ae349f5Scvs2svn * 61ae349f5Scvs2svn * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 71ae349f5Scvs2svn * 81ae349f5Scvs2svn * Redistribution and use in source and binary forms are permitted 91ae349f5Scvs2svn * provided that the above copyright notice and this paragraph are 101ae349f5Scvs2svn * duplicated in all such forms and that any documentation, 111ae349f5Scvs2svn * advertising materials, and other materials related to such 121ae349f5Scvs2svn * distribution and use acknowledge that the software was developed 131ae349f5Scvs2svn * by the Internet Initiative Japan, Inc. The name of the 141ae349f5Scvs2svn * IIJ may not be used to endorse or promote products derived 151ae349f5Scvs2svn * from this software without specific prior written permission. 161ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171ae349f5Scvs2svn * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181ae349f5Scvs2svn * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191ae349f5Scvs2svn * 20b7c5748eSBrian Somers * $Id: main.c,v 1.121.2.56 1998/05/06 18:50:09 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn */ 242764b86aSBrian Somers 251ae349f5Scvs2svn #include <sys/param.h> 26e43ebac1SBrian Somers #include <sys/socket.h> 271ae349f5Scvs2svn #include <netinet/in.h> 281ae349f5Scvs2svn #include <netinet/in_systm.h> 291ae349f5Scvs2svn #include <netinet/ip.h> 30565e35e5SBrian Somers #include <sys/un.h> 31e43ebac1SBrian Somers #include <net/if_tun.h> 321ae349f5Scvs2svn 331ae349f5Scvs2svn #include <errno.h> 341ae349f5Scvs2svn #include <fcntl.h> 351ae349f5Scvs2svn #include <paths.h> 361ae349f5Scvs2svn #include <signal.h> 371ae349f5Scvs2svn #include <stdio.h> 381ae349f5Scvs2svn #include <string.h> 391ae349f5Scvs2svn #include <termios.h> 401ae349f5Scvs2svn #include <unistd.h> 411ae349f5Scvs2svn 421ae349f5Scvs2svn #include "mbuf.h" 431ae349f5Scvs2svn #include "log.h" 441ae349f5Scvs2svn #include "defs.h" 451ae349f5Scvs2svn #include "id.h" 461ae349f5Scvs2svn #include "timer.h" 471ae349f5Scvs2svn #include "fsm.h" 48879ed6faSBrian Somers #include "lqr.h" 491ae349f5Scvs2svn #include "hdlc.h" 501ae349f5Scvs2svn #include "lcp.h" 511ae349f5Scvs2svn #include "ccp.h" 5229e275ceSBrian Somers #include "iplist.h" 5329e275ceSBrian Somers #include "throughput.h" 54eaa4df37SBrian Somers #include "slcompress.h" 551ae349f5Scvs2svn #include "ipcp.h" 565ca5389aSBrian Somers #include "filter.h" 572f786681SBrian Somers #include "descriptor.h" 583b0f8d2eSBrian Somers #include "link.h" 593b0f8d2eSBrian Somers #include "mp.h" 605828db6dSBrian Somers #include "bundle.h" 611ae349f5Scvs2svn #include "loadalias.h" 621ae349f5Scvs2svn #include "auth.h" 631ae349f5Scvs2svn #include "systems.h" 641ae349f5Scvs2svn #include "ip.h" 651ae349f5Scvs2svn #include "sig.h" 661ae349f5Scvs2svn #include "main.h" 671ae349f5Scvs2svn #include "tun.h" 6877ff88adSBrian Somers #include "server.h" 6985b542cfSBrian Somers #include "prompt.h" 70b6dec9f0SBrian Somers #include "chat.h" 71e2ebb036SBrian Somers #include "chap.h" 723006ec67SBrian Somers #include "datalink.h" 731ae349f5Scvs2svn 741ae349f5Scvs2svn #ifndef O_NONBLOCK 751ae349f5Scvs2svn #ifdef O_NDELAY 761ae349f5Scvs2svn #define O_NONBLOCK O_NDELAY 771ae349f5Scvs2svn #endif 781ae349f5Scvs2svn #endif 791ae349f5Scvs2svn 801ae349f5Scvs2svn static char pid_filename[MAXPATHLEN]; 811ae349f5Scvs2svn 82b6217683SBrian Somers static void DoLoop(struct bundle *, struct prompt *); 831ae349f5Scvs2svn static void TerminalStop(int); 841ae349f5Scvs2svn static const char *ex_desc(int); 851ae349f5Scvs2svn 8683d1af55SBrian Somers static struct bundle *SignalBundle; 87b6217683SBrian Somers static struct prompt *SignalPrompt; 887a6f8720SBrian Somers 891ae349f5Scvs2svn void 901ae349f5Scvs2svn Cleanup(int excode) 911ae349f5Scvs2svn { 92a0cbd833SBrian Somers SignalBundle->CleaningUp = 1; 933006ec67SBrian Somers if (bundle_Phase(SignalBundle) != PHASE_DEAD) 943b0f8d2eSBrian Somers bundle_Close(SignalBundle, NULL, 1); 951afedc4bSBrian Somers } 96455aabc3SBrian Somers 971afedc4bSBrian Somers void 981afedc4bSBrian Somers AbortProgram(int excode) 991afedc4bSBrian Somers { 100dd7e2610SBrian Somers server_Close(SignalBundle); 1011ae349f5Scvs2svn ID0unlink(pid_filename); 102dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 103d345321bSBrian Somers bundle_Close(SignalBundle, NULL, 1); 10468a0f0ccSBrian Somers bundle_Destroy(SignalBundle); 105dd7e2610SBrian Somers log_Close(); 1061ae349f5Scvs2svn exit(excode); 1071ae349f5Scvs2svn } 1081ae349f5Scvs2svn 1091ae349f5Scvs2svn static void 1101ae349f5Scvs2svn CloseConnection(int signo) 1111ae349f5Scvs2svn { 1121ae349f5Scvs2svn /* NOTE, these are manual, we've done a setsid() */ 113dd7e2610SBrian Somers sig_signal(SIGINT, SIG_IGN); 114dd7e2610SBrian Somers log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo); 1151bc9b5baSBrian Somers bundle_Down(SignalBundle); 116dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 1171ae349f5Scvs2svn } 1181ae349f5Scvs2svn 1191ae349f5Scvs2svn static void 1201ae349f5Scvs2svn CloseSession(int signo) 1211ae349f5Scvs2svn { 122dd7e2610SBrian Somers log_Printf(LogPHASE, "Signal %d, terminate.\n", signo); 1231ae349f5Scvs2svn Cleanup(EX_TERM); 1241ae349f5Scvs2svn } 1251ae349f5Scvs2svn 12675b8d283SBrian Somers static pid_t BGPid = 0; 12775b8d283SBrian Somers 12875b8d283SBrian Somers static void 12975b8d283SBrian Somers KillChild(int signo) 13075b8d283SBrian Somers { 131dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Signal %d\n", signo); 13275b8d283SBrian Somers kill(BGPid, SIGINT); 13375b8d283SBrian Somers } 13475b8d283SBrian Somers 1351ae349f5Scvs2svn static void 1361ae349f5Scvs2svn TerminalCont(int signo) 1371ae349f5Scvs2svn { 138f91ad6b0SBrian Somers signal(SIGCONT, SIG_DFL); 139f91ad6b0SBrian Somers prompt_Continue(SignalPrompt); 1401ae349f5Scvs2svn } 1411ae349f5Scvs2svn 1421ae349f5Scvs2svn static void 1431ae349f5Scvs2svn TerminalStop(int signo) 1441ae349f5Scvs2svn { 145f91ad6b0SBrian Somers prompt_Suspend(SignalPrompt); 146f91ad6b0SBrian Somers signal(SIGCONT, TerminalCont); 147f91ad6b0SBrian Somers raise(SIGSTOP); 1481ae349f5Scvs2svn } 1491ae349f5Scvs2svn 150b6217683SBrian Somers #if 0 /* What's our passwd :-O */ 1511ae349f5Scvs2svn static void 1521ae349f5Scvs2svn SetUpServer(int signo) 1531ae349f5Scvs2svn { 1541ae349f5Scvs2svn int res; 1551ae349f5Scvs2svn 1561ae349f5Scvs2svn VarHaveLocalAuthKey = 0; 1571ae349f5Scvs2svn LocalAuthInit(); 158455aabc3SBrian Somers if ((res = ServerTcpOpen(SERVER_PORT + SignalBundle->unit)) != 0) 159dd7e2610SBrian Somers log_Printf(LogERROR, "SIGUSR1: Failed %d to open port %d\n", 160455aabc3SBrian Somers res, SERVER_PORT + SignalBundle->unit); 1611ae349f5Scvs2svn } 162b6217683SBrian Somers #endif 1631ae349f5Scvs2svn 1641ae349f5Scvs2svn static void 1651ae349f5Scvs2svn BringDownServer(int signo) 1661ae349f5Scvs2svn { 167b6217683SBrian Somers /* Drops all child prompts too ! */ 168dd7e2610SBrian Somers server_Close(SignalBundle); 1691ae349f5Scvs2svn } 1701ae349f5Scvs2svn 1711ae349f5Scvs2svn static const char * 1721ae349f5Scvs2svn ex_desc(int ex) 1731ae349f5Scvs2svn { 1741ae349f5Scvs2svn static char num[12]; 1751ae349f5Scvs2svn static const char *desc[] = { 1761ae349f5Scvs2svn "normal", "start", "sock", "modem", "dial", "dead", "done", 1771ae349f5Scvs2svn "reboot", "errdead", "hangup", "term", "nodial", "nologin" 1781ae349f5Scvs2svn }; 1791ae349f5Scvs2svn 1801ae349f5Scvs2svn if (ex >= 0 && ex < sizeof desc / sizeof *desc) 1811ae349f5Scvs2svn return desc[ex]; 1821ae349f5Scvs2svn snprintf(num, sizeof num, "%d", ex); 1831ae349f5Scvs2svn return num; 1841ae349f5Scvs2svn } 1851ae349f5Scvs2svn 1861ae349f5Scvs2svn static void 1871ae349f5Scvs2svn Usage(void) 1881ae349f5Scvs2svn { 1891ae349f5Scvs2svn fprintf(stderr, 1901ae349f5Scvs2svn "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]" 1911ae349f5Scvs2svn #ifndef NOALIAS 1921ae349f5Scvs2svn " [ -alias ]" 1931ae349f5Scvs2svn #endif 1941ae349f5Scvs2svn " [system]\n"); 1951ae349f5Scvs2svn exit(EX_START); 1961ae349f5Scvs2svn } 1971ae349f5Scvs2svn 1981ae349f5Scvs2svn static char * 199565e35e5SBrian Somers ProcessArgs(int argc, char **argv, int *mode) 2001ae349f5Scvs2svn { 201565e35e5SBrian Somers int optc, labelrequired; 2021ae349f5Scvs2svn char *cp; 2031ae349f5Scvs2svn 204565e35e5SBrian Somers optc = labelrequired = 0; 205565e35e5SBrian Somers *mode = PHYS_MANUAL; 2061ae349f5Scvs2svn while (argc > 0 && **argv == '-') { 2071ae349f5Scvs2svn cp = *argv + 1; 2081ae349f5Scvs2svn if (strcmp(cp, "auto") == 0) { 209565e35e5SBrian Somers *mode = PHYS_DEMAND; 210565e35e5SBrian Somers labelrequired = 1; 2111ae349f5Scvs2svn } else if (strcmp(cp, "background") == 0) { 212565e35e5SBrian Somers *mode = PHYS_1OFF; 213565e35e5SBrian Somers labelrequired = 1; 214565e35e5SBrian Somers } else if (strcmp(cp, "direct") == 0) 2156f384573SBrian Somers *mode = PHYS_DIRECT; 216565e35e5SBrian Somers else if (strcmp(cp, "dedicated") == 0) 217565e35e5SBrian Somers *mode = PHYS_DEDICATED; 218565e35e5SBrian Somers else if (strcmp(cp, "ddial") == 0) { 219565e35e5SBrian Somers *mode = PHYS_PERM; 220565e35e5SBrian Somers labelrequired = 1; 2211ae349f5Scvs2svn } else if (strcmp(cp, "alias") == 0) { 222565e35e5SBrian Somers #ifndef NOALIAS 223dd7e2610SBrian Somers if (alias_Load() != 0) 224565e35e5SBrian Somers #endif 225dd7e2610SBrian Somers log_Printf(LogWARN, "Cannot load alias library\n"); 2261ae349f5Scvs2svn optc--; /* this option isn't exclusive */ 2271ae349f5Scvs2svn } else 2281ae349f5Scvs2svn Usage(); 2291ae349f5Scvs2svn optc++; 2301ae349f5Scvs2svn argv++; 2311ae349f5Scvs2svn argc--; 2321ae349f5Scvs2svn } 2331ae349f5Scvs2svn if (argc > 1) { 23485602e52SBrian Somers fprintf(stderr, "You may specify only one system label.\n"); 2351ae349f5Scvs2svn exit(EX_START); 2361ae349f5Scvs2svn } 2371ae349f5Scvs2svn 2381ae349f5Scvs2svn if (optc > 1) { 23985602e52SBrian Somers fprintf(stderr, "You may specify only one mode.\n"); 2401ae349f5Scvs2svn exit(EX_START); 2411ae349f5Scvs2svn } 2421ae349f5Scvs2svn 243565e35e5SBrian Somers if (labelrequired && argc != 1) { 244565e35e5SBrian Somers fprintf(stderr, "Destination system must be specified in" 245565e35e5SBrian Somers " auto, background or ddial mode.\n"); 246565e35e5SBrian Somers exit(EX_START); 247565e35e5SBrian Somers } 248565e35e5SBrian Somers 2491ae349f5Scvs2svn return argc == 1 ? *argv : NULL; /* Don't SetLabel yet ! */ 2501ae349f5Scvs2svn } 2511ae349f5Scvs2svn 2521ae349f5Scvs2svn int 2531ae349f5Scvs2svn main(int argc, char **argv) 2541ae349f5Scvs2svn { 2551ae349f5Scvs2svn FILE *lockfile; 2561ae349f5Scvs2svn char *name, *label; 257565e35e5SBrian Somers int nfds, mode; 2587a6f8720SBrian Somers struct bundle *bundle; 259b6217683SBrian Somers struct prompt *prompt; 2601ae349f5Scvs2svn 2611ae349f5Scvs2svn nfds = getdtablesize(); 2621ae349f5Scvs2svn if (nfds >= FD_SETSIZE) 2631ae349f5Scvs2svn /* 2641ae349f5Scvs2svn * If we've got loads of file descriptors, make sure they're all 2651ae349f5Scvs2svn * closed. If they aren't, we may end up with a seg fault when our 2661ae349f5Scvs2svn * `fd_set's get too big when select()ing ! 2671ae349f5Scvs2svn */ 2681ae349f5Scvs2svn while (--nfds > 2) 2691ae349f5Scvs2svn close(nfds); 2701ae349f5Scvs2svn 2711ae349f5Scvs2svn name = strrchr(argv[0], '/'); 272dd7e2610SBrian Somers log_Open(name ? name + 1 : argv[0]); 2731ae349f5Scvs2svn 2741ae349f5Scvs2svn argc--; 2751ae349f5Scvs2svn argv++; 276565e35e5SBrian Somers label = ProcessArgs(argc, argv, &mode); 27785b542cfSBrian Somers 27885b542cfSBrian Somers #ifdef __FreeBSD__ 27985b542cfSBrian Somers /* 28085b542cfSBrian Somers * A FreeBSD hack to dodge a bug in the tty driver that drops output 28185b542cfSBrian Somers * occasionally.... I must find the real reason some time. To display 28285b542cfSBrian Somers * the dodgy behaviour, comment out this bit, make yourself a large 28385b542cfSBrian Somers * routing table and then run ppp in interactive mode. The `show route' 28485b542cfSBrian Somers * command will drop chunks of data !!! 28585b542cfSBrian Somers */ 286565e35e5SBrian Somers if (mode == PHYS_MANUAL) { 28785b542cfSBrian Somers close(STDIN_FILENO); 28885b542cfSBrian Somers if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) { 28985b542cfSBrian Somers fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY); 29085b542cfSBrian Somers return 2; 29185b542cfSBrian Somers } 29285b542cfSBrian Somers } 29385b542cfSBrian Somers #endif 29485b542cfSBrian Somers 295b6217683SBrian Somers /* Allow output for the moment (except in direct mode) */ 2966f384573SBrian Somers if (mode == PHYS_DIRECT) 297b6217683SBrian Somers prompt = NULL; 29885602e52SBrian Somers else { 29985602e52SBrian Somers const char *m; 30085602e52SBrian Somers 301b6217683SBrian Somers SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD); 302565e35e5SBrian Somers if (mode == PHYS_PERM) 30385602e52SBrian Somers m = "direct dial"; 304565e35e5SBrian Somers else if (mode & PHYS_1OFF) 30585602e52SBrian Somers m = "background"; 306565e35e5SBrian Somers else if (mode & PHYS_DEMAND) 30785602e52SBrian Somers m = "auto"; 308565e35e5SBrian Somers else if (mode & PHYS_DEDICATED) 30985602e52SBrian Somers m = "dedicated"; 310565e35e5SBrian Somers else if (mode & PHYS_MANUAL) 31185602e52SBrian Somers m = "interactive"; 31285602e52SBrian Somers else 31385602e52SBrian Somers m = NULL; 31485602e52SBrian Somers 31585602e52SBrian Somers if (m) 31685602e52SBrian Somers prompt_Printf(prompt, "Working in %s mode\n", m); 31785602e52SBrian Somers } 3181ae349f5Scvs2svn 3191ae349f5Scvs2svn ID0init(); 3201ae349f5Scvs2svn if (ID0realuid() != 0) { 3211ae349f5Scvs2svn char conf[200], *ptr; 3221ae349f5Scvs2svn 3231ae349f5Scvs2svn snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 3241ae349f5Scvs2svn do { 3251ae349f5Scvs2svn if (!access(conf, W_OK)) { 326dd7e2610SBrian Somers log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", conf); 3271ae349f5Scvs2svn return -1; 3281ae349f5Scvs2svn } 3291ae349f5Scvs2svn ptr = conf + strlen(conf)-2; 3301ae349f5Scvs2svn while (ptr > conf && *ptr != '/') 3311ae349f5Scvs2svn *ptr-- = '\0'; 3321ae349f5Scvs2svn } while (ptr >= conf); 3331ae349f5Scvs2svn } 3341ae349f5Scvs2svn 335dd7e2610SBrian Somers if (!system_IsValid(label, prompt, mode)) { 3361ae349f5Scvs2svn fprintf(stderr, "You may not use ppp in this mode with this label\n"); 3376f384573SBrian Somers if (mode == PHYS_DIRECT) { 3381ae349f5Scvs2svn const char *l; 3391ae349f5Scvs2svn l = label ? label : "default"; 340dd7e2610SBrian Somers log_Printf(LogWARN, "Label %s rejected -direct connection\n", l); 3411ae349f5Scvs2svn } 342dd7e2610SBrian Somers log_Close(); 3431ae349f5Scvs2svn return 1; 3441ae349f5Scvs2svn } 3451ae349f5Scvs2svn 346565e35e5SBrian Somers if ((bundle = bundle_Create(TUN_PREFIX, prompt, mode)) == NULL) { 347dd7e2610SBrian Somers log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno)); 3481ae349f5Scvs2svn return EX_START; 3491ae349f5Scvs2svn } 35083d1af55SBrian Somers SignalBundle = bundle; 3517a6f8720SBrian Somers 352dd7e2610SBrian Somers if (system_Select(bundle, "default", CONFFILE, prompt) < 0) 353565e35e5SBrian Somers prompt_Printf(prompt, "Warning: No default entry found in config file.\n"); 3541ae349f5Scvs2svn 355dd7e2610SBrian Somers sig_signal(SIGHUP, CloseSession); 356dd7e2610SBrian Somers sig_signal(SIGTERM, CloseSession); 357dd7e2610SBrian Somers sig_signal(SIGINT, CloseConnection); 358dd7e2610SBrian Somers sig_signal(SIGQUIT, CloseSession); 359dd7e2610SBrian Somers sig_signal(SIGALRM, SIG_IGN); 3601ae349f5Scvs2svn signal(SIGPIPE, SIG_IGN); 361565e35e5SBrian Somers 362565e35e5SBrian Somers if (mode == PHYS_MANUAL) 363dd7e2610SBrian Somers sig_signal(SIGTSTP, TerminalStop); 364f91ad6b0SBrian Somers 365b6217683SBrian Somers #if 0 /* What's our passwd :-O */ 366dd7e2610SBrian Somers sig_signal(SIGUSR1, SetUpServer); 3671ae349f5Scvs2svn #endif 368dd7e2610SBrian Somers sig_signal(SIGUSR2, BringDownServer); 3691ae349f5Scvs2svn 3701ae349f5Scvs2svn if (label) { 37149052c95SBrian Somers /* 372dd7e2610SBrian Somers * Set label both before and after system_Select ! 373dd7e2610SBrian Somers * This way, "set enddisc label" works during system_Select, and we 37449052c95SBrian Somers * also end up with the correct label if we have embedded load 37549052c95SBrian Somers * commands. 37649052c95SBrian Somers */ 37749052c95SBrian Somers bundle_SetLabel(bundle, label); 378dd7e2610SBrian Somers if (system_Select(bundle, label, CONFFILE, prompt) < 0) { 379b6217683SBrian Somers prompt_Printf(prompt, "Destination system (%s) not found.\n", label); 3808390b576SBrian Somers AbortProgram(EX_START); 3811ae349f5Scvs2svn } 38249052c95SBrian Somers bundle_SetLabel(bundle, label); 383565e35e5SBrian Somers if (mode == PHYS_DEMAND && 3845828db6dSBrian Somers bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) { 385565e35e5SBrian Somers prompt_Printf(prompt, "You must \"set ifaddr\" with a peer address " 386565e35e5SBrian Somers "in label %s for auto mode.\n", label); 3878390b576SBrian Somers AbortProgram(EX_START); 3881ae349f5Scvs2svn } 3891ae349f5Scvs2svn } 3901ae349f5Scvs2svn 391565e35e5SBrian Somers if (mode != PHYS_MANUAL) { 3926f384573SBrian Somers if (mode != PHYS_DIRECT) { 3935cf4388bSBrian Somers int bgpipe[2]; 3945cf4388bSBrian Somers pid_t bgpid; 3955cf4388bSBrian Somers 396565e35e5SBrian Somers if (mode == PHYS_1OFF && pipe(bgpipe)) { 397dd7e2610SBrian Somers log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); 3988390b576SBrian Somers AbortProgram(EX_SOCK); 3991ae349f5Scvs2svn } 4001ae349f5Scvs2svn 4011ae349f5Scvs2svn bgpid = fork(); 4021ae349f5Scvs2svn if (bgpid == -1) { 403dd7e2610SBrian Somers log_Printf(LogERROR, "fork: %s\n", strerror(errno)); 4048390b576SBrian Somers AbortProgram(EX_SOCK); 4051ae349f5Scvs2svn } 4065cf4388bSBrian Somers 4071ae349f5Scvs2svn if (bgpid) { 4081ae349f5Scvs2svn char c = EX_NORMAL; 4091ae349f5Scvs2svn 410565e35e5SBrian Somers if (mode == PHYS_1OFF) { 4115cf4388bSBrian Somers close(bgpipe[1]); 41275b8d283SBrian Somers BGPid = bgpid; 41375b8d283SBrian Somers /* If we get a signal, kill the child */ 41475b8d283SBrian Somers signal(SIGHUP, KillChild); 41575b8d283SBrian Somers signal(SIGTERM, KillChild); 41675b8d283SBrian Somers signal(SIGINT, KillChild); 41775b8d283SBrian Somers signal(SIGQUIT, KillChild); 41875b8d283SBrian Somers 41975b8d283SBrian Somers /* Wait for our child to close its pipe before we exit */ 4205cf4388bSBrian Somers if (read(bgpipe[0], &c, 1) != 1) { 421b6217683SBrian Somers prompt_Printf(prompt, "Child exit, no status.\n"); 422dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child exit, no status.\n"); 4231ae349f5Scvs2svn } else if (c == EX_NORMAL) { 424b6217683SBrian Somers prompt_Printf(prompt, "PPP enabled.\n"); 425dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: PPP enabled.\n"); 4261ae349f5Scvs2svn } else { 427b6217683SBrian Somers prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c)); 428dd7e2610SBrian Somers log_Printf(LogPHASE, "Parent: Child failed (%s).\n", 4291ae349f5Scvs2svn ex_desc((int) c)); 4301ae349f5Scvs2svn } 4315cf4388bSBrian Somers close(bgpipe[0]); 4321ae349f5Scvs2svn } 4331ae349f5Scvs2svn return c; 434565e35e5SBrian Somers } else if (mode == PHYS_1OFF) { 4355cf4388bSBrian Somers close(bgpipe[0]); 4365cf4388bSBrian Somers bundle->notify.fd = bgpipe[1]; 4375cf4388bSBrian Somers } 4381ae349f5Scvs2svn 439565e35e5SBrian Somers /* -auto, -dedicated, -ddial & -background */ 440b6217683SBrian Somers prompt_Destroy(prompt, 0); 441b6217683SBrian Somers close(STDOUT_FILENO); 442b6217683SBrian Somers close(STDERR_FILENO); 4431ae349f5Scvs2svn close(STDIN_FILENO); 444b6217683SBrian Somers setsid(); 445565e35e5SBrian Somers } else { 446565e35e5SBrian Somers /* -direct: STDIN_FILENO gets used by modem_Open */ 447565e35e5SBrian Somers prompt_TtyInit(NULL); 448565e35e5SBrian Somers close(STDOUT_FILENO); 449565e35e5SBrian Somers close(STDERR_FILENO); 4501ae349f5Scvs2svn } 4511ae349f5Scvs2svn } else { 452565e35e5SBrian Somers /* Interactive mode */ 4531ae349f5Scvs2svn close(STDERR_FILENO); 454565e35e5SBrian Somers prompt_TtyInit(prompt); 455b6217683SBrian Somers prompt_TtyCommandMode(prompt); 456b6217683SBrian Somers prompt_Required(prompt); 4571ae349f5Scvs2svn } 4581ae349f5Scvs2svn 4591ae349f5Scvs2svn snprintf(pid_filename, sizeof pid_filename, "%stun%d.pid", 460455aabc3SBrian Somers _PATH_VARRUN, bundle->unit); 4611ae349f5Scvs2svn lockfile = ID0fopen(pid_filename, "w"); 4621ae349f5Scvs2svn if (lockfile != NULL) { 4631ae349f5Scvs2svn fprintf(lockfile, "%d\n", (int) getpid()); 4641ae349f5Scvs2svn fclose(lockfile); 4651ae349f5Scvs2svn } 4661ae349f5Scvs2svn #ifndef RELEASE_CRUNCH 4671ae349f5Scvs2svn else 468dd7e2610SBrian Somers log_Printf(LogALERT, "Warning: Can't create %s: %s\n", 4691ae349f5Scvs2svn pid_filename, strerror(errno)); 4701ae349f5Scvs2svn #endif 4711ae349f5Scvs2svn 472dd7e2610SBrian Somers log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); 473b6217683SBrian Somers DoLoop(bundle, prompt); 4741afedc4bSBrian Somers AbortProgram(EX_NORMAL); 4751afedc4bSBrian Somers 4761afedc4bSBrian Somers return EX_NORMAL; 4771ae349f5Scvs2svn } 4781ae349f5Scvs2svn 4791ae349f5Scvs2svn static void 480b6217683SBrian Somers DoLoop(struct bundle *bundle, struct prompt *prompt) 4811ae349f5Scvs2svn { 4821ae349f5Scvs2svn fd_set rfds, wfds, efds; 483078c562eSBrian Somers int i, nfds; 4841ae349f5Scvs2svn 485565e35e5SBrian Somers do { 4861ae349f5Scvs2svn nfds = 0; 4871ae349f5Scvs2svn FD_ZERO(&rfds); 4881ae349f5Scvs2svn FD_ZERO(&wfds); 4891ae349f5Scvs2svn FD_ZERO(&efds); 4901ae349f5Scvs2svn 491dd7e2610SBrian Somers sig_Handle(); 492b6dec9f0SBrian Somers 4931bc9b5baSBrian Somers /* This may nuke a datalink */ 4941fa665f5SBrian Somers descriptor_UpdateSet(&bundle->ncp.mp.server.desc, &rfds, &wfds, 4951fa665f5SBrian Somers &efds, &nfds); 4966f384573SBrian Somers descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds); 4976f384573SBrian Somers descriptor_UpdateSet(&server.desc, &rfds, &wfds, &efds, &nfds); 4981ae349f5Scvs2svn 4993b0f8d2eSBrian Somers if (bundle_IsDead(bundle)) 500f4768038SBrian Somers /* Don't select - we'll be here forever */ 501f4768038SBrian Somers break; 502f4768038SBrian Somers 5033006ec67SBrian Somers i = select(nfds, &rfds, &wfds, &efds, NULL); 5041ae349f5Scvs2svn 5053006ec67SBrian Somers if (i == 0) 5061ae349f5Scvs2svn continue; 507078c562eSBrian Somers else if (i < 0) { 508078c562eSBrian Somers if (errno == EINTR) 5091ae349f5Scvs2svn continue; 510dd7e2610SBrian Somers log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 5111ae349f5Scvs2svn break; 5121ae349f5Scvs2svn } 51377ff88adSBrian Somers 5143006ec67SBrian Somers for (i = 0; i <= nfds; i++) 5153006ec67SBrian Somers if (FD_ISSET(i, &efds)) { 516dd7e2610SBrian Somers log_Printf(LogALERT, "Exception detected on descriptor %d\n", i); 5171ae349f5Scvs2svn break; 5181ae349f5Scvs2svn } 51977ff88adSBrian Somers 520b7c5748eSBrian Somers if (i <= nfds) 521b7c5748eSBrian Somers break; 522b7c5748eSBrian Somers 5231fa665f5SBrian Somers if (descriptor_IsSet(&bundle->ncp.mp.server.desc, &rfds)) 5241fa665f5SBrian Somers descriptor_Read(&bundle->ncp.mp.server.desc, bundle, &rfds); 5251fa665f5SBrian Somers 52677ff88adSBrian Somers if (descriptor_IsSet(&server.desc, &rfds)) 527b77776a7SBrian Somers descriptor_Read(&server.desc, bundle, &rfds); 52842d4d396SBrian Somers 5292f786681SBrian Somers if (descriptor_IsSet(&bundle->desc, &wfds)) 5302f786681SBrian Somers descriptor_Write(&bundle->desc, bundle, &wfds); 5312f786681SBrian Somers 5321bc9b5baSBrian Somers /* This may add a datalink */ 5332f786681SBrian Somers if (descriptor_IsSet(&bundle->desc, &rfds)) 5342f786681SBrian Somers descriptor_Read(&bundle->desc, bundle, &rfds); 535565e35e5SBrian Somers } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle)); 536565e35e5SBrian Somers 537dd7e2610SBrian Somers log_Printf(LogDEBUG, "DoLoop done.\n"); 5381ae349f5Scvs2svn } 539