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 * 204562be74SBrian Somers * $Id: main.c,v 1.97 1997/11/13 14:44:06 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai * o Add commands for traffic summary, version display, etc. 24af57ed9fSAtsushi Murai * o Add signal handler for misc controls. 25af57ed9fSAtsushi Murai */ 2675240ed1SBrian Somers #include <sys/param.h> 27af57ed9fSAtsushi Murai #include <sys/socket.h> 2875240ed1SBrian Somers #include <netinet/in.h> 29a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 30a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 3175240ed1SBrian Somers #include <arpa/inet.h> 3275240ed1SBrian Somers #include <netdb.h> 3375240ed1SBrian Somers 3475240ed1SBrian Somers #include <errno.h> 3575240ed1SBrian Somers #include <fcntl.h> 3675240ed1SBrian Somers #include <paths.h> 3775240ed1SBrian Somers #include <signal.h> 3875240ed1SBrian Somers #include <stdio.h> 3975240ed1SBrian Somers #include <stdlib.h> 4075240ed1SBrian Somers #include <string.h> 4175240ed1SBrian Somers #include <sys/time.h> 4275240ed1SBrian Somers #include <sys/wait.h> 43683cef3cSBrian Somers #include <sysexits.h> 4475240ed1SBrian Somers #include <termios.h> 4575240ed1SBrian Somers #include <unistd.h> 4675240ed1SBrian Somers 4775240ed1SBrian Somers #include "mbuf.h" 4875240ed1SBrian Somers #include "log.h" 4975240ed1SBrian Somers #include "defs.h" 505106c671SBrian Somers #include "id.h" 5175240ed1SBrian Somers #include "timer.h" 5275240ed1SBrian Somers #include "fsm.h" 53af57ed9fSAtsushi Murai #include "modem.h" 54af57ed9fSAtsushi Murai #include "os.h" 55af57ed9fSAtsushi Murai #include "hdlc.h" 56ed6a16c1SPoul-Henning Kamp #include "ccp.h" 57af57ed9fSAtsushi Murai #include "lcp.h" 58af57ed9fSAtsushi Murai #include "ipcp.h" 596ed9fb2fSBrian Somers #include "loadalias.h" 6075240ed1SBrian Somers #include "command.h" 61af57ed9fSAtsushi Murai #include "vars.h" 6253c9f6c0SAtsushi Murai #include "auth.h" 6384b8a6ebSAtsushi Murai #include "filter.h" 64ed6a16c1SPoul-Henning Kamp #include "systems.h" 65ed6a16c1SPoul-Henning Kamp #include "ip.h" 66f5ff0f7cSBrian Somers #include "sig.h" 674ef16f24SBrian Somers #include "server.h" 68de451c68SBrian Somers #include "lcpproto.h" 6975240ed1SBrian Somers #include "main.h" 7075240ed1SBrian Somers #include "vjcomp.h" 7175240ed1SBrian Somers #include "async.h" 724562be74SBrian Somers #include "pathnames.h" 7353c9f6c0SAtsushi Murai 7453c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 7553c9f6c0SAtsushi Murai #ifdef O_NDELAY 7653c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 7753c9f6c0SAtsushi Murai #endif 7853c9f6c0SAtsushi Murai #endif 79af57ed9fSAtsushi Murai 8075240ed1SBrian Somers int TermMode = 0; 8175240ed1SBrian Somers int tunno = 0; 82af57ed9fSAtsushi Murai 83af57ed9fSAtsushi Murai static struct termios oldtio; /* Original tty mode */ 84af57ed9fSAtsushi Murai static struct termios comtio; /* Command level tty mode */ 856d14e2a8SJordan K. Hubbard static pid_t BGPid = 0; 8641c6c543SBrian Somers static char pid_filename[MAXPATHLEN]; 8776c5241dSBrian Somers static int dial_up; 88af57ed9fSAtsushi Murai 8975240ed1SBrian Somers static void DoLoop(void); 9075240ed1SBrian Somers static void TerminalStop(int); 9175240ed1SBrian Somers static char *ex_desc(int); 9275240ed1SBrian Somers 93af57ed9fSAtsushi Murai static void 94368aee2bSBrian Somers TtyInit(int DontWantInt) 95af57ed9fSAtsushi Murai { 96af57ed9fSAtsushi Murai struct termios newtio; 97af57ed9fSAtsushi Murai int stat; 98af57ed9fSAtsushi Murai 99af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 100274e766cSBrian Somers if (stat > 0) { 101af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 102274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 103274e766cSBrian Somers } 104af57ed9fSAtsushi Murai newtio = oldtio; 105af57ed9fSAtsushi Murai newtio.c_lflag &= ~(ECHO | ISIG | ICANON); 106af57ed9fSAtsushi Murai newtio.c_iflag = 0; 107af57ed9fSAtsushi Murai newtio.c_oflag &= ~OPOST; 108af57ed9fSAtsushi Murai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 109368aee2bSBrian Somers if (DontWantInt) 110af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 111af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 112af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 113af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 11453c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 115af57ed9fSAtsushi Murai comtio = newtio; 116af57ed9fSAtsushi Murai } 117af57ed9fSAtsushi Murai 118af57ed9fSAtsushi Murai /* 119af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 120af57ed9fSAtsushi Murai */ 121c3899f8dSAtsushi Murai void 122944f7098SBrian Somers TtyCommandMode(int prompt) 123af57ed9fSAtsushi Murai { 124af57ed9fSAtsushi Murai struct termios newtio; 125af57ed9fSAtsushi Murai int stat; 126af57ed9fSAtsushi Murai 127af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 128af57ed9fSAtsushi Murai return; 12953c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 130c3899f8dSAtsushi Murai newtio.c_lflag |= (ECHO | ISIG | ICANON); 131af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 132af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 13353c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 134af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 135274e766cSBrian Somers if (stat > 0) { 136af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 137274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 138274e766cSBrian Somers } 139af57ed9fSAtsushi Murai TermMode = 0; 140944f7098SBrian Somers if (prompt) 141944f7098SBrian Somers Prompt(); 142af57ed9fSAtsushi Murai } 143af57ed9fSAtsushi Murai 144af57ed9fSAtsushi Murai /* 145af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 146af57ed9fSAtsushi Murai */ 147af57ed9fSAtsushi Murai void 148af57ed9fSAtsushi Murai TtyTermMode() 149af57ed9fSAtsushi Murai { 150af57ed9fSAtsushi Murai int stat; 151af57ed9fSAtsushi Murai 15253c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 153af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 154274e766cSBrian Somers if (stat > 0) { 155af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 156274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 157274e766cSBrian Somers } 158af57ed9fSAtsushi Murai TermMode = 1; 159af57ed9fSAtsushi Murai } 160af57ed9fSAtsushi Murai 161af57ed9fSAtsushi Murai void 162c3899f8dSAtsushi Murai TtyOldMode() 163c3899f8dSAtsushi Murai { 164c3899f8dSAtsushi Murai int stat; 165c3899f8dSAtsushi Murai 166c3899f8dSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 167274e766cSBrian Somers if (stat > 0) { 168c3899f8dSAtsushi Murai stat &= ~O_NONBLOCK; 169274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 170274e766cSBrian Somers } 171c3899f8dSAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 172c3899f8dSAtsushi Murai } 173c3899f8dSAtsushi Murai 174c3899f8dSAtsushi Murai void 175944f7098SBrian Somers Cleanup(int excode) 176af57ed9fSAtsushi Murai { 1778ea8442cSBrian Somers ServerClose(); 1780fe7ca31SBrian Somers OsInterfaceDown(1); 1790fe7ca31SBrian Somers HangupModem(1); 1809a571ec7SBrian Somers nointr_sleep(1); 1816e4959f0SBrian Somers DeleteIfRoutes(1); 1825106c671SBrian Somers ID0unlink(pid_filename); 1836e4959f0SBrian Somers if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 1846e4959f0SBrian Somers char c = EX_ERRDEAD; 185944f7098SBrian Somers 1866e4959f0SBrian Somers if (write(BGFiledes[1], &c, 1) == 1) 187927145beSBrian Somers LogPrintf(LogPHASE, "Parent notified of failure.\n"); 1886e4959f0SBrian Somers else 189927145beSBrian Somers LogPrintf(LogPHASE, "Failed to notify parent of failure.\n"); 1906e4959f0SBrian Somers close(BGFiledes[1]); 1916e4959f0SBrian Somers } 192927145beSBrian Somers LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 193c3899f8dSAtsushi Murai TtyOldMode(); 1945106c671SBrian Somers LogClose(); 195af57ed9fSAtsushi Murai 196af57ed9fSAtsushi Murai exit(excode); 197af57ed9fSAtsushi Murai } 198af57ed9fSAtsushi Murai 199af57ed9fSAtsushi Murai static void 200944f7098SBrian Somers CloseConnection(int signo) 201af57ed9fSAtsushi Murai { 202368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 20312ef29a8SBrian Somers pending_signal(SIGINT, SIG_IGN); 204873725ccSBrian Somers LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo); 205944f7098SBrian Somers reconnectState = RECON_FALSE; 206944f7098SBrian Somers reconnectCount = 0; 207368aee2bSBrian Somers DownConnection(); 20875240ed1SBrian Somers dial_up = 0; 20912ef29a8SBrian Somers pending_signal(SIGINT, CloseConnection); 2106d14e2a8SJordan K. Hubbard } 211af57ed9fSAtsushi Murai 212af57ed9fSAtsushi Murai static void 213944f7098SBrian Somers CloseSession(int signo) 214af57ed9fSAtsushi Murai { 2156d14e2a8SJordan K. Hubbard if (BGPid) { 2166d14e2a8SJordan K. Hubbard kill(BGPid, SIGINT); 2176d14e2a8SJordan K. Hubbard exit(EX_TERM); 2186d14e2a8SJordan K. Hubbard } 219927145beSBrian Somers LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo); 22025aa96acSBrian Somers reconnect(RECON_FALSE); 221af57ed9fSAtsushi Murai LcpClose(); 222af57ed9fSAtsushi Murai Cleanup(EX_TERM); 223af57ed9fSAtsushi Murai } 224c3899f8dSAtsushi Murai 225c3899f8dSAtsushi Murai static void 226c3899f8dSAtsushi Murai TerminalCont() 227c3899f8dSAtsushi Murai { 228f5ff0f7cSBrian Somers pending_signal(SIGCONT, SIG_DFL); 229f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 230c3899f8dSAtsushi Murai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 231c3899f8dSAtsushi Murai } 232c3899f8dSAtsushi Murai 233c3899f8dSAtsushi Murai static void 234944f7098SBrian Somers TerminalStop(int signo) 235c3899f8dSAtsushi Murai { 236f5ff0f7cSBrian Somers pending_signal(SIGCONT, TerminalCont); 237c3899f8dSAtsushi Murai TtyOldMode(); 238f5ff0f7cSBrian Somers pending_signal(SIGTSTP, SIG_DFL); 239c3899f8dSAtsushi Murai kill(getpid(), signo); 240c3899f8dSAtsushi Murai } 241c3899f8dSAtsushi Murai 2424ef16f24SBrian Somers static void 243944f7098SBrian Somers SetUpServer(int signo) 2444ef16f24SBrian Somers { 2454ef16f24SBrian Somers int res; 246944f7098SBrian Somers 2478ea8442cSBrian Somers VarHaveLocalAuthKey = 0; 2488ea8442cSBrian Somers LocalAuthInit(); 2494ef16f24SBrian Somers if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0) 250683cef3cSBrian Somers LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n", 251683cef3cSBrian Somers res, SERVER_PORT + tunno); 2524ef16f24SBrian Somers } 2534ef16f24SBrian Somers 2548ea8442cSBrian Somers static void 2558ea8442cSBrian Somers BringDownServer(int signo) 2568ea8442cSBrian Somers { 2578ea8442cSBrian Somers VarHaveLocalAuthKey = 0; 2588ea8442cSBrian Somers LocalAuthInit(); 2598ea8442cSBrian Somers ServerClose(); 2608ea8442cSBrian Somers } 2618ea8442cSBrian Somers 2626efd9292SBrian Somers static char * 2636efd9292SBrian Somers ex_desc(int ex) 2646efd9292SBrian Somers { 2656efd9292SBrian Somers static char num[12]; 2666efd9292SBrian Somers static char *desc[] = {"normal", "start", "sock", 2676efd9292SBrian Somers "modem", "dial", "dead", "done", "reboot", "errdead", 2686efd9292SBrian Somers "hangup", "term", "nodial", "nologin"}; 2696efd9292SBrian Somers 2706efd9292SBrian Somers if (ex >= 0 && ex < sizeof(desc) / sizeof(*desc)) 2716efd9292SBrian Somers return desc[ex]; 2726efd9292SBrian Somers snprintf(num, sizeof num, "%d", ex); 2736efd9292SBrian Somers return num; 2746efd9292SBrian Somers } 275c3899f8dSAtsushi Murai 27675240ed1SBrian Somers static void 277af57ed9fSAtsushi Murai Usage() 278af57ed9fSAtsushi Murai { 279680026d6SNate Williams fprintf(stderr, 2806d14e2a8SJordan K. Hubbard "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 281af57ed9fSAtsushi Murai exit(EX_START); 282af57ed9fSAtsushi Murai } 283af57ed9fSAtsushi Murai 28475240ed1SBrian Somers static void 285af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 286af57ed9fSAtsushi Murai { 287af57ed9fSAtsushi Murai int optc; 288af57ed9fSAtsushi Murai char *cp; 289af57ed9fSAtsushi Murai 290af57ed9fSAtsushi Murai optc = 0; 29112ef29a8SBrian Somers mode = MODE_INTER; 292af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 293af57ed9fSAtsushi Murai cp = *argv + 1; 29412ef29a8SBrian Somers if (strcmp(cp, "auto") == 0) { 295af57ed9fSAtsushi Murai mode |= MODE_AUTO; 29612ef29a8SBrian Somers mode &= ~MODE_INTER; 29712ef29a8SBrian Somers } else if (strcmp(cp, "background") == 0) { 29812ef29a8SBrian Somers mode |= MODE_BACKGROUND; 29912ef29a8SBrian Somers mode &= ~MODE_INTER; 30012ef29a8SBrian Somers } else if (strcmp(cp, "direct") == 0) { 301af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 30212ef29a8SBrian Somers mode &= ~MODE_INTER; 30312ef29a8SBrian Somers } else if (strcmp(cp, "dedicated") == 0) { 304af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 30512ef29a8SBrian Somers mode &= ~MODE_INTER; 30612ef29a8SBrian Somers } else if (strcmp(cp, "ddial") == 0) { 30712ef29a8SBrian Somers mode |= MODE_DDIAL; 30812ef29a8SBrian Somers mode &= ~MODE_INTER; 30912ef29a8SBrian Somers } else if (strcmp(cp, "alias") == 0) { 3106ed9fb2fSBrian Somers if (loadAliasHandlers(&VarAliasHandlers) == 0) 311a9f484e5SJordan K. Hubbard mode |= MODE_ALIAS; 3126ed9fb2fSBrian Somers else 313927145beSBrian Somers LogPrintf(LogWARN, "Cannot load alias library\n"); 314a9f484e5SJordan K. Hubbard optc--; /* this option isn't exclusive */ 315944f7098SBrian Somers } else 316af57ed9fSAtsushi Murai Usage(); 317af57ed9fSAtsushi Murai optc++; 318944f7098SBrian Somers argv++; 319944f7098SBrian Somers argc--; 320af57ed9fSAtsushi Murai } 321af57ed9fSAtsushi Murai if (argc > 1) { 322af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 323af57ed9fSAtsushi Murai exit(EX_START); 324af57ed9fSAtsushi Murai } 325944f7098SBrian Somers if (argc == 1) 32612ef29a8SBrian Somers SetLabel(*argv); 327af57ed9fSAtsushi Murai 328af57ed9fSAtsushi Murai if (optc > 1) { 329af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 330af57ed9fSAtsushi Murai exit(EX_START); 331af57ed9fSAtsushi Murai } 332af57ed9fSAtsushi Murai } 333af57ed9fSAtsushi Murai 334af57ed9fSAtsushi Murai static void 335af57ed9fSAtsushi Murai Greetings() 336af57ed9fSAtsushi Murai { 337927145beSBrian Somers if (VarTerm) { 338927145beSBrian Somers fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n"); 339927145beSBrian Somers fflush(VarTerm); 340927145beSBrian Somers } 341af57ed9fSAtsushi Murai } 342af57ed9fSAtsushi Murai 3434ef16f24SBrian Somers int 344944f7098SBrian Somers main(int argc, char **argv) 345af57ed9fSAtsushi Murai { 346aefd026aSBrian Somers FILE *lockfile; 347927145beSBrian Somers char *name; 348af57ed9fSAtsushi Murai 3490706ff38SBrian Somers VarTerm = 0; 35075240ed1SBrian Somers name = strrchr(argv[0], '/'); 351927145beSBrian Somers LogOpen(name ? name + 1 : argv[0]); 352927145beSBrian Somers 353944f7098SBrian Somers argc--; 354944f7098SBrian Somers argv++; 355af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 35612ef29a8SBrian Somers if (!(mode & MODE_DIRECT)) 3570706ff38SBrian Somers VarTerm = stdout; 35812ef29a8SBrian Somers 3595106c671SBrian Somers ID0init(); 3604562be74SBrian Somers if (ID0realuid() != 0) { 3614562be74SBrian Somers char conf[200], *ptr; 3624562be74SBrian Somers 3634562be74SBrian Somers snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE); 3644562be74SBrian Somers do { 3654562be74SBrian Somers if (!access(conf, W_OK)) { 3664562be74SBrian Somers LogPrintf(LogALERT, "ppp: Access violation: Please protect %s\n", conf); 3674562be74SBrian Somers return -1; 3684562be74SBrian Somers } 3694562be74SBrian Somers ptr = conf + strlen(conf)-2; 3704562be74SBrian Somers while (ptr > conf && *ptr != '/') 3714562be74SBrian Somers *ptr-- = '\0'; 3724562be74SBrian Somers } while (ptr >= conf); 3734562be74SBrian Somers } 3744562be74SBrian Somers 37512ef29a8SBrian Somers if (!ValidSystem(GetLabel())) { 37612ef29a8SBrian Somers fprintf(stderr, "You may not use ppp in this mode with this label\n"); 377815624cfSBrian Somers if (mode & MODE_DIRECT) { 378815624cfSBrian Somers const char *l; 379815624cfSBrian Somers if ((l = GetLabel()) == NULL) 380815624cfSBrian Somers l = "default"; 381815624cfSBrian Somers VarTerm = 0; 382815624cfSBrian Somers LogPrintf(LogWARN, "Label %s rejected -direct connection\n", l); 383815624cfSBrian Somers } 384815624cfSBrian Somers LogClose(); 38512ef29a8SBrian Somers return 1; 38612ef29a8SBrian Somers } 38712ef29a8SBrian Somers 388af57ed9fSAtsushi Murai Greetings(); 389af57ed9fSAtsushi Murai IpcpDefAddress(); 390683cef3cSBrian Somers LocalAuthInit(); 391af57ed9fSAtsushi Murai 392927145beSBrian Somers if (SelectSystem("default", CONFFILE) < 0 && VarTerm) 393927145beSBrian Somers fprintf(VarTerm, "Warning: No default entry is given in config file.\n"); 394af57ed9fSAtsushi Murai 395af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 3964ef16f24SBrian Somers LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno)); 3974ef16f24SBrian Somers return EX_START; 398af57ed9fSAtsushi Murai } 399af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 400927145beSBrian Somers fprintf(VarTerm, "Interactive mode\n"); 401cc39a98fSBrian Somers netfd = STDOUT_FILENO; 40212ef29a8SBrian Somers } else if ((mode & MODE_OUTGOING_DAEMON) && !(mode & MODE_DEDICATED)) 40312ef29a8SBrian Somers if (GetLabel() == NULL) { 404927145beSBrian Somers if (VarTerm) 405927145beSBrian Somers fprintf(VarTerm, "Destination system must be specified in" 4066efd9292SBrian Somers " auto, background or ddial mode.\n"); 4074ef16f24SBrian Somers return EX_START; 4086d14e2a8SJordan K. Hubbard } 40912ef29a8SBrian Somers 41053c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 411af57ed9fSAtsushi Murai 412873725ccSBrian Somers pending_signal(SIGHUP, CloseSession); 413f5ff0f7cSBrian Somers pending_signal(SIGTERM, CloseSession); 414873725ccSBrian Somers pending_signal(SIGINT, CloseConnection); 415f5ff0f7cSBrian Somers pending_signal(SIGQUIT, CloseSession); 41653c9f6c0SAtsushi Murai #ifdef SIGPIPE 417e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 41853c9f6c0SAtsushi Murai #endif 41953c9f6c0SAtsushi Murai #ifdef SIGALRM 420f5ff0f7cSBrian Somers pending_signal(SIGALRM, SIG_IGN); 42153c9f6c0SAtsushi Murai #endif 4224ef16f24SBrian Somers if (mode & MODE_INTER) { 423c3899f8dSAtsushi Murai #ifdef SIGTSTP 424f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 425c3899f8dSAtsushi Murai #endif 426c3899f8dSAtsushi Murai #ifdef SIGTTIN 427f5ff0f7cSBrian Somers pending_signal(SIGTTIN, TerminalStop); 428c3899f8dSAtsushi Murai #endif 429c3899f8dSAtsushi Murai #ifdef SIGTTOU 430f5ff0f7cSBrian Somers pending_signal(SIGTTOU, SIG_IGN); 431c3899f8dSAtsushi Murai #endif 432c3899f8dSAtsushi Murai } 43312ef29a8SBrian Somers if (!(mode & MODE_INTER)) { 4344ef16f24SBrian Somers #ifdef SIGUSR1 4354ef16f24SBrian Somers pending_signal(SIGUSR1, SetUpServer); 4364ef16f24SBrian Somers #endif 4378ea8442cSBrian Somers #ifdef SIGUSR2 4388ea8442cSBrian Somers pending_signal(SIGUSR2, BringDownServer); 4398ea8442cSBrian Somers #endif 44012ef29a8SBrian Somers } 441af57ed9fSAtsushi Murai 44212ef29a8SBrian Somers if (GetLabel()) { 44312ef29a8SBrian Somers if (SelectSystem(GetLabel(), CONFFILE) < 0) { 444e4450123SBrian Somers LogPrintf(LogWARN, "Destination system %s not found in conf file.\n", 445e4450123SBrian Somers GetLabel()); 446af57ed9fSAtsushi Murai Cleanup(EX_START); 447af57ed9fSAtsushi Murai } 44812ef29a8SBrian Somers if (mode & MODE_OUTGOING_DAEMON && 44912ef29a8SBrian Somers DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 450e4450123SBrian Somers LogPrintf(LogWARN, "You must \"set ifaddr\" in label %s for" 451e4450123SBrian Somers " auto, background or ddial mode.\n", GetLabel()); 452af57ed9fSAtsushi Murai Cleanup(EX_START); 453af57ed9fSAtsushi Murai } 454af57ed9fSAtsushi Murai } 4556efd9292SBrian Somers 45612ef29a8SBrian Somers if (mode & MODE_DAEMON) { 4576d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4586d14e2a8SJordan K. Hubbard if (pipe(BGFiledes)) { 459afc7fa2cSBrian Somers LogPrintf(LogERROR, "pipe: %s\n", strerror(errno)); 4606d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4616d14e2a8SJordan K. Hubbard } 4626d14e2a8SJordan K. Hubbard } 463af57ed9fSAtsushi Murai 464af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 4656d14e2a8SJordan K. Hubbard pid_t bgpid; 466a9c6b5dfSAtsushi Murai 4676d14e2a8SJordan K. Hubbard bgpid = fork(); 4686d14e2a8SJordan K. Hubbard if (bgpid == -1) { 469afc7fa2cSBrian Somers LogPrintf(LogERROR, "fork: %s\n", strerror(errno)); 4706d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4716d14e2a8SJordan K. Hubbard } 4726d14e2a8SJordan K. Hubbard if (bgpid) { 4736d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 474a9c6b5dfSAtsushi Murai 4756d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4766d14e2a8SJordan K. Hubbard /* Wait for our child to close its pipe before we exit. */ 4776d14e2a8SJordan K. Hubbard BGPid = bgpid; 4786e4959f0SBrian Somers close(BGFiledes[1]); 4796efd9292SBrian Somers if (read(BGFiledes[0], &c, 1) != 1) { 480927145beSBrian Somers fprintf(VarTerm, "Child exit, no status.\n"); 481927145beSBrian Somers LogPrintf(LogPHASE, "Parent: Child exit, no status.\n"); 4826efd9292SBrian Somers } else if (c == EX_NORMAL) { 483927145beSBrian Somers fprintf(VarTerm, "PPP enabled.\n"); 484927145beSBrian Somers LogPrintf(LogPHASE, "Parent: PPP enabled.\n"); 4856efd9292SBrian Somers } else { 486927145beSBrian Somers fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c)); 487927145beSBrian Somers LogPrintf(LogPHASE, "Parent: Child failed (%s).\n", 48880e37c72SBrian Somers ex_desc((int) c)); 4896efd9292SBrian Somers } 4906e4959f0SBrian Somers close(BGFiledes[0]); 4916d14e2a8SJordan K. Hubbard } 4924ef16f24SBrian Somers return c; 4936e4959f0SBrian Somers } else if (mode & MODE_BACKGROUND) 4946e4959f0SBrian Somers close(BGFiledes[0]); 495aefd026aSBrian Somers } 496aefd026aSBrian Somers 497d656a4c5SBrian Somers VarTerm = 0; /* We know it's currently stdout */ 498fd2bc5ebSBrian Somers close(1); 499d656a4c5SBrian Somers close(2); 5000706ff38SBrian Somers 501d656a4c5SBrian Somers if (mode & MODE_DIRECT) 502368aee2bSBrian Somers TtyInit(1); 50312ef29a8SBrian Somers else if (mode & MODE_DAEMON) { 504d656a4c5SBrian Somers setsid(); 505fd2bc5ebSBrian Somers close(0); 506d656a4c5SBrian Somers } 507af57ed9fSAtsushi Murai } else { 508368aee2bSBrian Somers TtyInit(0); 509c3899f8dSAtsushi Murai TtyCommandMode(1); 510af57ed9fSAtsushi Murai } 51135495becSBrian Somers 51235495becSBrian Somers snprintf(pid_filename, sizeof(pid_filename), "%stun%d.pid", 51335495becSBrian Somers _PATH_VARRUN, tunno); 5145106c671SBrian Somers lockfile = ID0fopen(pid_filename, "w"); 5155106c671SBrian Somers if (lockfile != NULL) { 51635495becSBrian Somers fprintf(lockfile, "%d\n", (int) getpid()); 51735495becSBrian Somers fclose(lockfile); 51835495becSBrian Somers } else 51935495becSBrian Somers LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 52035495becSBrian Somers pid_filename, strerror(errno)); 52135495becSBrian Somers 522927145beSBrian Somers LogPrintf(LogPHASE, "PPP Started.\n"); 523af57ed9fSAtsushi Murai 524af57ed9fSAtsushi Murai 525af57ed9fSAtsushi Murai do 526af57ed9fSAtsushi Murai DoLoop(); 527af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 528af57ed9fSAtsushi Murai 529af57ed9fSAtsushi Murai Cleanup(EX_DONE); 5304ef16f24SBrian Somers return 0; 531af57ed9fSAtsushi Murai } 532af57ed9fSAtsushi Murai 533af57ed9fSAtsushi Murai /* 5346d14e2a8SJordan K. Hubbard * Turn into packet mode, where we speak PPP. 535af57ed9fSAtsushi Murai */ 536af57ed9fSAtsushi Murai void 537af57ed9fSAtsushi Murai PacketMode() 538af57ed9fSAtsushi Murai { 5399780ef31SBrian Somers if (RawModem() < 0) { 540927145beSBrian Somers LogPrintf(LogWARN, "PacketMode: Not connected.\n"); 541af57ed9fSAtsushi Murai return; 542af57ed9fSAtsushi Murai } 543af57ed9fSAtsushi Murai AsyncInit(); 54403604f35SBrian Somers VjInit(15); 545af57ed9fSAtsushi Murai LcpInit(); 546af57ed9fSAtsushi Murai IpcpInit(); 547af57ed9fSAtsushi Murai CcpInit(); 548af57ed9fSAtsushi Murai LcpUp(); 549af57ed9fSAtsushi Murai 550af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 55112ef29a8SBrian Somers if (mode & MODE_INTER) 552c3899f8dSAtsushi Murai TtyCommandMode(1); 553927145beSBrian Somers if (VarTerm) { 554927145beSBrian Somers fprintf(VarTerm, "Packet mode.\n"); 555b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 556af57ed9fSAtsushi Murai } 557af57ed9fSAtsushi Murai } 558af57ed9fSAtsushi Murai 559af57ed9fSAtsushi Murai static void 560af57ed9fSAtsushi Murai ShowHelp() 561af57ed9fSAtsushi Murai { 562030d3ce6SBrian Somers fprintf(stderr, "The following commands are available:\r\n"); 563030d3ce6SBrian Somers fprintf(stderr, " ~p\tEnter Packet mode\r\n"); 564030d3ce6SBrian Somers fprintf(stderr, " ~-\tDecrease log level\r\n"); 565030d3ce6SBrian Somers fprintf(stderr, " ~+\tIncrease log level\r\n"); 566030d3ce6SBrian Somers fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n"); 567030d3ce6SBrian Somers fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n"); 568030d3ce6SBrian Somers fprintf(stderr, " ~.\tTerminate program\r\n"); 569030d3ce6SBrian Somers fprintf(stderr, " ~?\tThis help\r\n"); 570af57ed9fSAtsushi Murai } 571af57ed9fSAtsushi Murai 572af57ed9fSAtsushi Murai static void 573af57ed9fSAtsushi Murai ReadTty() 574af57ed9fSAtsushi Murai { 575af57ed9fSAtsushi Murai int n; 576af57ed9fSAtsushi Murai char ch; 577af57ed9fSAtsushi Murai static int ttystate; 578927145beSBrian Somers FILE *oVarTerm; 57986e02934SBrian Somers char linebuff[LINE_LEN]; 580af57ed9fSAtsushi Murai 581927145beSBrian Somers LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n", 582927145beSBrian Somers TermMode, netfd, mode); 583af57ed9fSAtsushi Murai if (!TermMode) { 584af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff) - 1); 58553c9f6c0SAtsushi Murai if (n > 0) { 586927145beSBrian Somers aft_cmd = 1; 587a1e8f937SBrian Somers if (linebuff[n-1] == '\n') 588a1e8f937SBrian Somers linebuff[--n] = '\0'; 589d9181b05SBrian Somers if (n) 590d9181b05SBrian Somers DecodeCommand(linebuff, n, IsInteractive(0) ? NULL : "Client"); 591a1e8f937SBrian Somers Prompt(); 59253c9f6c0SAtsushi Murai } else { 593927145beSBrian Somers LogPrintf(LogPHASE, "client connection closed.\n"); 594927145beSBrian Somers oVarTerm = VarTerm; 595927145beSBrian Somers VarTerm = 0; 596927145beSBrian Somers if (oVarTerm && oVarTerm != stdout) 597927145beSBrian Somers fclose(oVarTerm); 598927145beSBrian Somers close(netfd); 599927145beSBrian Somers netfd = -1; 600af57ed9fSAtsushi Murai } 601af57ed9fSAtsushi Murai return; 602af57ed9fSAtsushi Murai } 603af57ed9fSAtsushi Murai 604af57ed9fSAtsushi Murai /* 605af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 606af57ed9fSAtsushi Murai */ 607927145beSBrian Somers n = read(fileno(VarTerm), &ch, 1); 608afc7fa2cSBrian Somers LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n); 609af57ed9fSAtsushi Murai 610af57ed9fSAtsushi Murai if (n > 0) { 611af57ed9fSAtsushi Murai switch (ttystate) { 612af57ed9fSAtsushi Murai case 0: 613af57ed9fSAtsushi Murai if (ch == '~') 614af57ed9fSAtsushi Murai ttystate++; 615af57ed9fSAtsushi Murai else 616af57ed9fSAtsushi Murai write(modem, &ch, n); 617af57ed9fSAtsushi Murai break; 618af57ed9fSAtsushi Murai case 1: 619af57ed9fSAtsushi Murai switch (ch) { 620af57ed9fSAtsushi Murai case '?': 621af57ed9fSAtsushi Murai ShowHelp(); 622af57ed9fSAtsushi Murai break; 623af57ed9fSAtsushi Murai case 'p': 624944f7098SBrian Somers 625af57ed9fSAtsushi Murai /* 626af57ed9fSAtsushi Murai * XXX: Should check carrier. 627af57ed9fSAtsushi Murai */ 628af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 629af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 630af57ed9fSAtsushi Murai PacketMode(); 631af57ed9fSAtsushi Murai } 632af57ed9fSAtsushi Murai break; 633af57ed9fSAtsushi Murai case '.': 634af57ed9fSAtsushi Murai TermMode = 1; 635927145beSBrian Somers aft_cmd = 1; 636c3899f8dSAtsushi Murai TtyCommandMode(1); 637af57ed9fSAtsushi Murai break; 638927145beSBrian Somers case 't': 639927145beSBrian Somers if (LogIsKept(LogDEBUG)) { 640927145beSBrian Somers ShowTimers(); 641927145beSBrian Somers break; 642927145beSBrian Somers } 643927145beSBrian Somers case 'm': 644927145beSBrian Somers if (LogIsKept(LogDEBUG)) { 645927145beSBrian Somers ShowMemMap(); 646927145beSBrian Somers break; 647927145beSBrian Somers } 648af57ed9fSAtsushi Murai default: 649af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 650927145beSBrian Somers LogPrintf(LogERROR, "error writing to modem.\n"); 651af57ed9fSAtsushi Murai break; 652af57ed9fSAtsushi Murai } 653af57ed9fSAtsushi Murai ttystate = 0; 654af57ed9fSAtsushi Murai break; 655af57ed9fSAtsushi Murai } 656af57ed9fSAtsushi Murai } 657af57ed9fSAtsushi Murai } 658af57ed9fSAtsushi Murai 659af57ed9fSAtsushi Murai 660af57ed9fSAtsushi Murai /* 661af57ed9fSAtsushi Murai * Here, we'll try to detect HDLC frame 662af57ed9fSAtsushi Murai */ 663af57ed9fSAtsushi Murai 664af57ed9fSAtsushi Murai static char *FrameHeaders[] = { 66553c9f6c0SAtsushi Murai "\176\377\003\300\041", 66653c9f6c0SAtsushi Murai "\176\377\175\043\300\041", 66753c9f6c0SAtsushi Murai "\176\177\175\043\100\041", 66853c9f6c0SAtsushi Murai "\176\175\337\175\043\300\041", 66953c9f6c0SAtsushi Murai "\176\175\137\175\043\100\041", 670af57ed9fSAtsushi Murai NULL, 671af57ed9fSAtsushi Murai }; 672af57ed9fSAtsushi Murai 67375240ed1SBrian Somers static u_char * 674944f7098SBrian Somers HdlcDetect(u_char * cp, int n) 675af57ed9fSAtsushi Murai { 67653c9f6c0SAtsushi Murai char *ptr, *fp, **hp; 677af57ed9fSAtsushi Murai 678af57ed9fSAtsushi Murai cp[n] = '\0'; /* be sure to null terminated */ 679af57ed9fSAtsushi Murai ptr = NULL; 680af57ed9fSAtsushi Murai for (hp = FrameHeaders; *hp; hp++) { 68153c9f6c0SAtsushi Murai fp = *hp; 68253c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 68353c9f6c0SAtsushi Murai fp++; 684ed6a16c1SPoul-Henning Kamp ptr = strstr((char *) cp, fp); 685ed6a16c1SPoul-Henning Kamp if (ptr) 686af57ed9fSAtsushi Murai break; 687af57ed9fSAtsushi Murai } 688af57ed9fSAtsushi Murai return ((u_char *) ptr); 689af57ed9fSAtsushi Murai } 690af57ed9fSAtsushi Murai 691af57ed9fSAtsushi Murai static struct pppTimer RedialTimer; 692af57ed9fSAtsushi Murai 693af57ed9fSAtsushi Murai static void 694af57ed9fSAtsushi Murai RedialTimeout() 695af57ed9fSAtsushi Murai { 696af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 697927145beSBrian Somers LogPrintf(LogPHASE, "Redialing timer expired.\n"); 698af57ed9fSAtsushi Murai } 699af57ed9fSAtsushi Murai 700af57ed9fSAtsushi Murai static void 701944f7098SBrian Somers StartRedialTimer(int Timeout) 702af57ed9fSAtsushi Murai { 703af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 704a9c6b5dfSAtsushi Murai 70543ea9d19SBrian Somers if (Timeout) { 706af57ed9fSAtsushi Murai RedialTimer.state = TIMER_STOPPED; 707a9c6b5dfSAtsushi Murai 70843ea9d19SBrian Somers if (Timeout > 0) 70943ea9d19SBrian Somers RedialTimer.load = Timeout * SECTICKS; 710a9c6b5dfSAtsushi Murai else 711a9c6b5dfSAtsushi Murai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 712a9c6b5dfSAtsushi Murai 713927145beSBrian Somers LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n", 71443ea9d19SBrian Somers RedialTimer.load / SECTICKS); 71543ea9d19SBrian Somers 716af57ed9fSAtsushi Murai RedialTimer.func = RedialTimeout; 717af57ed9fSAtsushi Murai StartTimer(&RedialTimer); 718af57ed9fSAtsushi Murai } 719a9c6b5dfSAtsushi Murai } 720af57ed9fSAtsushi Murai 721af57ed9fSAtsushi Murai 722af57ed9fSAtsushi Murai static void 723af57ed9fSAtsushi Murai DoLoop() 724af57ed9fSAtsushi Murai { 725af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 726780700e5SAndrey A. Chernov int pri, i, n, wfd, nfds; 727af57ed9fSAtsushi Murai struct sockaddr_in hisaddr; 728af57ed9fSAtsushi Murai struct timeval timeout, *tp; 729af57ed9fSAtsushi Murai int ssize = sizeof(hisaddr); 730af57ed9fSAtsushi Murai u_char *cp; 731af57ed9fSAtsushi Murai u_char rbuff[MAX_MRU]; 732a9c6b5dfSAtsushi Murai int tries; 73360e218e4SAtsushi Murai int qlen; 734368aee2bSBrian Somers int res; 735c3899f8dSAtsushi Murai pid_t pgroup; 736c3899f8dSAtsushi Murai 737c3899f8dSAtsushi Murai pgroup = getpgrp(); 738af57ed9fSAtsushi Murai 7396efd9292SBrian Somers if (mode & MODE_DIRECT) { 7400706ff38SBrian Somers LogPrintf(LogDEBUG, "Opening modem\n"); 7419780ef31SBrian Somers if (OpenModem() < 0) 742bc240299SBrian Somers return; 743927145beSBrian Somers LogPrintf(LogPHASE, "Packet mode enabled\n"); 744af57ed9fSAtsushi Murai PacketMode(); 745af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 746780700e5SAndrey A. Chernov if (modem < 0) 7479780ef31SBrian Somers while (OpenModem() < 0) 7489a571ec7SBrian Somers nointr_sleep(VarReconnectTimer); 749af57ed9fSAtsushi Murai } 750927145beSBrian Somers fflush(VarTerm); 751af57ed9fSAtsushi Murai 75284b8a6ebSAtsushi Murai timeout.tv_sec = 0; 753af57ed9fSAtsushi Murai timeout.tv_usec = 0; 75425aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 755af57ed9fSAtsushi Murai 7566e4959f0SBrian Somers if (mode & MODE_BACKGROUND) 75775240ed1SBrian Somers dial_up = 1; /* Bring the line up */ 7586e4959f0SBrian Somers else 75975240ed1SBrian Somers dial_up = 0; /* XXXX */ 760a9c6b5dfSAtsushi Murai tries = 0; 761af57ed9fSAtsushi Murai for (;;) { 762780700e5SAndrey A. Chernov nfds = 0; 763944f7098SBrian Somers FD_ZERO(&rfds); 764944f7098SBrian Somers FD_ZERO(&wfds); 765944f7098SBrian Somers FD_ZERO(&efds); 76684b8a6ebSAtsushi Murai 76784b8a6ebSAtsushi Murai /* 768944f7098SBrian Somers * If the link is down and we're in DDIAL mode, bring it back up. 769680026d6SNate Williams */ 770680026d6SNate Williams if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 77175240ed1SBrian Somers dial_up = 1; 772680026d6SNate Williams 773680026d6SNate Williams /* 774944f7098SBrian Somers * If we lost carrier and want to re-establish the connection due to the 775944f7098SBrian Somers * "set reconnect" value, we'd better bring the line back up. 77607030d97SBrian Somers */ 7776efd9292SBrian Somers if (LcpFsm.state <= ST_CLOSED) { 77875240ed1SBrian Somers if (!dial_up && reconnectState == RECON_TRUE) { 7796efd9292SBrian Somers if (++reconnectCount <= VarReconnectTries) { 780927145beSBrian Somers LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n", 7816efd9292SBrian Somers reconnectCount, VarReconnectTries); 78207030d97SBrian Somers StartRedialTimer(VarReconnectTimer); 78375240ed1SBrian Somers dial_up = 1; 784298091daSBrian Somers } else { 7856efd9292SBrian Somers if (VarReconnectTries) 786927145beSBrian Somers LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n", 787298091daSBrian Somers VarReconnectTries); 7886efd9292SBrian Somers reconnectCount = 0; 7896efd9292SBrian Somers if (mode & MODE_BACKGROUND) 7906efd9292SBrian Somers Cleanup(EX_DEAD); 7916efd9292SBrian Somers } 79225aa96acSBrian Somers reconnectState = RECON_ENVOKED; 79312ef29a8SBrian Somers } else if (mode & MODE_DEDICATED) 79412ef29a8SBrian Somers if (VarOpenMode == OPEN_ACTIVE) 79512ef29a8SBrian Somers PacketMode(); 79607030d97SBrian Somers } 79707030d97SBrian Somers 79807030d97SBrian Somers /* 799944f7098SBrian Somers * If Ip packet for output is enqueued and require dial up, Just do it! 80084b8a6ebSAtsushi Murai */ 80107030d97SBrian Somers if (dial_up && RedialTimer.state != TIMER_RUNNING) { 802927145beSBrian Somers LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem); 8039780ef31SBrian Somers if (OpenModem() < 0) { 8040706ff38SBrian Somers tries++; 805712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries) 8060706ff38SBrian Somers LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n", 8070706ff38SBrian Somers tries, VarDialTries); 8080706ff38SBrian Somers else 8090706ff38SBrian Somers LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries); 8100706ff38SBrian Somers 811712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) { 8120706ff38SBrian Somers if (mode & MODE_BACKGROUND) 8130706ff38SBrian Somers Cleanup(EX_DIAL); /* Can't get the modem */ 81475240ed1SBrian Somers dial_up = 0; 8150706ff38SBrian Somers reconnectState = RECON_UNKNOWN; 8160706ff38SBrian Somers reconnectCount = 0; 8170706ff38SBrian Somers tries = 0; 8180706ff38SBrian Somers } else 81943ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 82084b8a6ebSAtsushi Murai } else { 821944f7098SBrian Somers tries++; /* Tries are per number, not per list of 822944f7098SBrian Somers * numbers. */ 823712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries) 824712ae387SBrian Somers LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries); 825c0139fb2SBrian Somers else 826927145beSBrian Somers LogPrintf(LogCHAT, "Dial attempt %u\n", tries); 827712ae387SBrian Somers 828368aee2bSBrian Somers if ((res = DialModem()) == EX_DONE) { 8299a571ec7SBrian Somers nointr_sleep(1); /* little pause to allow peer starts */ 83084b8a6ebSAtsushi Murai ModemTimeout(); 83184b8a6ebSAtsushi Murai PacketMode(); 83275240ed1SBrian Somers dial_up = 0; 83325aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 834a9c6b5dfSAtsushi Murai tries = 0; 83584b8a6ebSAtsushi Murai } else { 8364ed9958fSBrian Somers if (mode & MODE_BACKGROUND) { 837368aee2bSBrian Somers if (VarNextPhone == NULL || res == EX_SIG) 8384ed9958fSBrian Somers Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 8394ed9958fSBrian Somers else 84043ea9d19SBrian Somers /* Try all numbers in background mode */ 84143ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 842368aee2bSBrian Somers } else if (!(mode & MODE_DDIAL) && 843368aee2bSBrian Somers ((VarDialTries && tries >= VarDialTries) || 844368aee2bSBrian Somers res == EX_SIG)) { 845c0139fb2SBrian Somers /* I give up ! Can't get through :( */ 84643ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 84775240ed1SBrian Somers dial_up = 0; 84825aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 84925aa96acSBrian Somers reconnectCount = 0; 850a9c6b5dfSAtsushi Murai tries = 0; 851c0139fb2SBrian Somers } else if (VarNextPhone == NULL) 852c0139fb2SBrian Somers /* Dial failed. Keep quite during redial wait period. */ 85343ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 854c0139fb2SBrian Somers else 85543ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 85684b8a6ebSAtsushi Murai } 85784b8a6ebSAtsushi Murai } 85884b8a6ebSAtsushi Murai } 85960e218e4SAtsushi Murai qlen = ModemQlen(); 86076bd0c0aSDoug Rabson 86176bd0c0aSDoug Rabson if (qlen == 0) { 86276bd0c0aSDoug Rabson IpStartOutput(); 86376bd0c0aSDoug Rabson qlen = ModemQlen(); 86476bd0c0aSDoug Rabson } 865780700e5SAndrey A. Chernov if (modem >= 0) { 866780700e5SAndrey A. Chernov if (modem + 1 > nfds) 867780700e5SAndrey A. Chernov nfds = modem + 1; 86884b8a6ebSAtsushi Murai FD_SET(modem, &rfds); 86984b8a6ebSAtsushi Murai FD_SET(modem, &efds); 87060e218e4SAtsushi Murai if (qlen > 0) { 87184b8a6ebSAtsushi Murai FD_SET(modem, &wfds); 87284b8a6ebSAtsushi Murai } 87384b8a6ebSAtsushi Murai } 874780700e5SAndrey A. Chernov if (server >= 0) { 875780700e5SAndrey A. Chernov if (server + 1 > nfds) 876780700e5SAndrey A. Chernov nfds = server + 1; 877780700e5SAndrey A. Chernov FD_SET(server, &rfds); 878780700e5SAndrey A. Chernov } 879af57ed9fSAtsushi Murai 880944f7098SBrian Somers /* 881944f7098SBrian Somers * *** IMPORTANT *** 882af57ed9fSAtsushi Murai * 883944f7098SBrian Somers * CPU is serviced every TICKUNIT micro seconds. This value must be chosen 884944f7098SBrian Somers * with great care. If this values is too big, it results loss of 885944f7098SBrian Somers * characters from modem and poor responce. If this values is too small, 886944f7098SBrian Somers * ppp process eats many CPU time. 887af57ed9fSAtsushi Murai */ 88853c9f6c0SAtsushi Murai #ifndef SIGALRM 8899a571ec7SBrian Somers nointr_usleep(TICKUNIT); 890af57ed9fSAtsushi Murai TimerService(); 891f5ff0f7cSBrian Somers #else 892f5ff0f7cSBrian Somers handle_signals(); 89353c9f6c0SAtsushi Murai #endif 89468d2b4d6SBruce Evans 89568d2b4d6SBruce Evans /* If there are aren't many packets queued, look for some more. */ 896780700e5SAndrey A. Chernov if (qlen < 20 && tun_in >= 0) { 897780700e5SAndrey A. Chernov if (tun_in + 1 > nfds) 898780700e5SAndrey A. Chernov nfds = tun_in + 1; 89984b8a6ebSAtsushi Murai FD_SET(tun_in, &rfds); 900780700e5SAndrey A. Chernov } 901780700e5SAndrey A. Chernov if (netfd >= 0) { 902780700e5SAndrey A. Chernov if (netfd + 1 > nfds) 903780700e5SAndrey A. Chernov nfds = netfd + 1; 904af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 905af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 906af57ed9fSAtsushi Murai } 90753c9f6c0SAtsushi Murai #ifndef SIGALRM 908944f7098SBrian Somers 909af57ed9fSAtsushi Murai /* 910944f7098SBrian Somers * Normally, select() will not block because modem is writable. In AUTO 911944f7098SBrian Somers * mode, select will block until we find packet from tun 912af57ed9fSAtsushi Murai */ 913af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL; 914780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 91553c9f6c0SAtsushi Murai #else 916944f7098SBrian Somers 91784b8a6ebSAtsushi Murai /* 918944f7098SBrian Somers * When SIGALRM timer is running, a select function will be return -1 and 919944f7098SBrian Somers * EINTR after a Time Service signal hundler is done. If the redial 920944f7098SBrian Somers * timer is not running and we are trying to dial, poll with a 0 value 921944f7098SBrian Somers * timer. 92284b8a6ebSAtsushi Murai */ 923a9c6b5dfSAtsushi Murai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 924780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 92553c9f6c0SAtsushi Murai #endif 9266b0b88d8SBrian Somers 927af57ed9fSAtsushi Murai if (i == 0) { 928af57ed9fSAtsushi Murai continue; 929af57ed9fSAtsushi Murai } 930534fe541SBrian Somers if (i < 0) { 931534fe541SBrian Somers if (errno == EINTR) { 932f5ff0f7cSBrian Somers handle_signals(); 933f5ff0f7cSBrian Somers continue; 93484b8a6ebSAtsushi Murai } 935afc7fa2cSBrian Somers LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 936af57ed9fSAtsushi Murai break; 937af57ed9fSAtsushi Murai } 938780700e5SAndrey A. Chernov if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 939927145beSBrian Somers LogPrintf(LogALERT, "Exception detected.\n"); 940af57ed9fSAtsushi Murai break; 941af57ed9fSAtsushi Murai } 942780700e5SAndrey A. Chernov if (server >= 0 && FD_ISSET(server, &rfds)) { 943927145beSBrian Somers LogPrintf(LogPHASE, "connected to client.\n"); 944af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *) & hisaddr, &ssize); 945e0d3e233SAndrey A. Chernov if (wfd < 0) { 946afc7fa2cSBrian Somers LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno)); 947e0d3e233SAndrey A. Chernov continue; 948e0d3e233SAndrey A. Chernov } 949780700e5SAndrey A. Chernov if (netfd >= 0) { 950af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 951af57ed9fSAtsushi Murai close(wfd); 952af57ed9fSAtsushi Murai continue; 953af57ed9fSAtsushi Murai } else 954af57ed9fSAtsushi Murai netfd = wfd; 955927145beSBrian Somers VarTerm = fdopen(netfd, "a+"); 9568ea8442cSBrian Somers LocalAuthInit(); 957af57ed9fSAtsushi Murai Greetings(); 958a1e8f937SBrian Somers IsInteractive(1); 959274e766cSBrian Somers Prompt(); 960af57ed9fSAtsushi Murai } 96112ef29a8SBrian Somers if (netfd >= 0 && FD_ISSET(netfd, &rfds) && 96212ef29a8SBrian Somers ((mode & MODE_OUTGOING_DAEMON) || pgroup == tcgetpgrp(0))) { 963af57ed9fSAtsushi Murai /* something to read from tty */ 964af57ed9fSAtsushi Murai ReadTty(); 965af57ed9fSAtsushi Murai } 966780700e5SAndrey A. Chernov if (modem >= 0) { 967af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 968af57ed9fSAtsushi Murai ModemStartOutput(modem); 969af57ed9fSAtsushi Murai } 970af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 97153c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 9729a571ec7SBrian Somers nointr_usleep(10000); 973af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 974af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 975af57ed9fSAtsushi Murai DownConnection(); 976af57ed9fSAtsushi Murai } else 977927145beSBrian Somers LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n); 978af57ed9fSAtsushi Murai 979af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 980944f7098SBrian Somers 981af57ed9fSAtsushi Murai /* 982af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 983af57ed9fSAtsushi Murai */ 984af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 985af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 986af57ed9fSAtsushi Murai if (cp) { 987944f7098SBrian Somers 988af57ed9fSAtsushi Murai /* 989af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 990af57ed9fSAtsushi Murai */ 991af57ed9fSAtsushi Murai if (cp != rbuff) { 992927145beSBrian Somers write(modem, rbuff, cp - rbuff); 993927145beSBrian Somers write(modem, "\r\n", 2); 994af57ed9fSAtsushi Murai } 995af57ed9fSAtsushi Murai PacketMode(); 996af57ed9fSAtsushi Murai } else 997927145beSBrian Somers write(fileno(VarTerm), rbuff, n); 998af57ed9fSAtsushi Murai } 999af57ed9fSAtsushi Murai } else { 1000af57ed9fSAtsushi Murai if (n > 0) 1001af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 1002af57ed9fSAtsushi Murai } 1003af57ed9fSAtsushi Murai } 1004af57ed9fSAtsushi Murai } 1005944f7098SBrian Somers if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read 1006944f7098SBrian Somers * from tun */ 1007af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 1008af57ed9fSAtsushi Murai if (n < 0) { 1009afc7fa2cSBrian Somers LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno)); 1010af57ed9fSAtsushi Murai continue; 1011af57ed9fSAtsushi Murai } 1012de451c68SBrian Somers if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) { 1013de451c68SBrian Somers /* we've been asked to send something addressed *to* us :( */ 1014de451c68SBrian Somers if (VarLoopback) { 1015de451c68SBrian Somers pri = PacketCheck(rbuff, n, FL_IN); 1016de451c68SBrian Somers if (pri >= 0) { 1017de451c68SBrian Somers struct mbuf *bp; 1018944f7098SBrian Somers 1019de451c68SBrian Somers if (mode & MODE_ALIAS) { 1020de451c68SBrian Somers VarPacketAliasIn(rbuff, sizeof rbuff); 1021de451c68SBrian Somers n = ntohs(((struct ip *) rbuff)->ip_len); 1022de451c68SBrian Somers } 1023de451c68SBrian Somers bp = mballoc(n, MB_IPIN); 102475240ed1SBrian Somers memcpy(MBUF_CTOP(bp), rbuff, n); 1025de451c68SBrian Somers IpInput(bp); 1026de451c68SBrian Somers LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n"); 1027de451c68SBrian Somers } 1028de451c68SBrian Somers continue; 1029de451c68SBrian Somers } else 1030de451c68SBrian Somers LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n"); 1031de451c68SBrian Somers } 1032de451c68SBrian Somers 1033af57ed9fSAtsushi Murai /* 1034af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 1035af57ed9fSAtsushi Murai * device until IPCP is opened. 1036af57ed9fSAtsushi Murai */ 1037af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 103884b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_DIAL); 1039af57ed9fSAtsushi Murai if (pri >= 0) { 1040a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10416ed9fb2fSBrian Somers VarPacketAliasOut(rbuff, sizeof rbuff); 1042a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *) rbuff)->ip_len); 1043a9f484e5SJordan K. Hubbard } 1044af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 104575240ed1SBrian Somers dial_up = 1; /* XXX */ 1046af57ed9fSAtsushi Murai } 1047af57ed9fSAtsushi Murai continue; 1048af57ed9fSAtsushi Murai } 104984b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_OUT); 1050a9f484e5SJordan K. Hubbard if (pri >= 0) { 1051a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10526ed9fb2fSBrian Somers VarPacketAliasOut(rbuff, sizeof rbuff); 1053a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *) rbuff)->ip_len); 1054a9f484e5SJordan K. Hubbard } 1055af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 1056af57ed9fSAtsushi Murai } 1057af57ed9fSAtsushi Murai } 1058a9f484e5SJordan K. Hubbard } 1059927145beSBrian Somers LogPrintf(LogDEBUG, "Job (DoLoop) done.\n"); 1060af57ed9fSAtsushi Murai } 1061