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 * 205106c671SBrian Somers * $Id: main.c,v 1.88 1997/11/08 00:28:09 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" 7253c9f6c0SAtsushi Murai 7353c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 7453c9f6c0SAtsushi Murai #ifdef O_NDELAY 7553c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 7653c9f6c0SAtsushi Murai #endif 7753c9f6c0SAtsushi Murai #endif 78af57ed9fSAtsushi Murai 7975240ed1SBrian Somers int TermMode = 0; 8075240ed1SBrian Somers int tunno = 0; 81af57ed9fSAtsushi Murai 82af57ed9fSAtsushi Murai static struct termios oldtio; /* Original tty mode */ 83af57ed9fSAtsushi Murai static struct termios comtio; /* Command level tty mode */ 846d14e2a8SJordan K. Hubbard static pid_t BGPid = 0; 8541c6c543SBrian Somers static char pid_filename[MAXPATHLEN]; 8676c5241dSBrian Somers static int dial_up; 87af57ed9fSAtsushi Murai 8875240ed1SBrian Somers static void DoLoop(void); 8975240ed1SBrian Somers static void TerminalStop(int); 9075240ed1SBrian Somers static char *ex_desc(int); 9175240ed1SBrian Somers 92af57ed9fSAtsushi Murai static void 93368aee2bSBrian Somers TtyInit(int DontWantInt) 94af57ed9fSAtsushi Murai { 95af57ed9fSAtsushi Murai struct termios newtio; 96af57ed9fSAtsushi Murai int stat; 97af57ed9fSAtsushi Murai 98af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 99274e766cSBrian Somers if (stat > 0) { 100af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 101274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 102274e766cSBrian Somers } 103af57ed9fSAtsushi Murai newtio = oldtio; 104af57ed9fSAtsushi Murai newtio.c_lflag &= ~(ECHO | ISIG | ICANON); 105af57ed9fSAtsushi Murai newtio.c_iflag = 0; 106af57ed9fSAtsushi Murai newtio.c_oflag &= ~OPOST; 107af57ed9fSAtsushi Murai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 108368aee2bSBrian Somers if (DontWantInt) 109af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 110af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 111af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 112af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 11353c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 114af57ed9fSAtsushi Murai comtio = newtio; 115af57ed9fSAtsushi Murai } 116af57ed9fSAtsushi Murai 117af57ed9fSAtsushi Murai /* 118af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 119af57ed9fSAtsushi Murai */ 120c3899f8dSAtsushi Murai void 121944f7098SBrian Somers TtyCommandMode(int prompt) 122af57ed9fSAtsushi Murai { 123af57ed9fSAtsushi Murai struct termios newtio; 124af57ed9fSAtsushi Murai int stat; 125af57ed9fSAtsushi Murai 126af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 127af57ed9fSAtsushi Murai return; 12853c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 129c3899f8dSAtsushi Murai newtio.c_lflag |= (ECHO | ISIG | ICANON); 130af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 131af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 13253c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 133af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 134274e766cSBrian Somers if (stat > 0) { 135af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 136274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 137274e766cSBrian Somers } 138af57ed9fSAtsushi Murai TermMode = 0; 139944f7098SBrian Somers if (prompt) 140944f7098SBrian Somers Prompt(); 141af57ed9fSAtsushi Murai } 142af57ed9fSAtsushi Murai 143af57ed9fSAtsushi Murai /* 144af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 145af57ed9fSAtsushi Murai */ 146af57ed9fSAtsushi Murai void 147af57ed9fSAtsushi Murai TtyTermMode() 148af57ed9fSAtsushi Murai { 149af57ed9fSAtsushi Murai int stat; 150af57ed9fSAtsushi Murai 15153c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 152af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 153274e766cSBrian Somers if (stat > 0) { 154af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 155274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 156274e766cSBrian Somers } 157af57ed9fSAtsushi Murai TermMode = 1; 158af57ed9fSAtsushi Murai } 159af57ed9fSAtsushi Murai 160af57ed9fSAtsushi Murai void 161c3899f8dSAtsushi Murai TtyOldMode() 162c3899f8dSAtsushi Murai { 163c3899f8dSAtsushi Murai int stat; 164c3899f8dSAtsushi Murai 165c3899f8dSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 166274e766cSBrian Somers if (stat > 0) { 167c3899f8dSAtsushi Murai stat &= ~O_NONBLOCK; 168274e766cSBrian Somers (void) fcntl(0, F_SETFL, stat); 169274e766cSBrian Somers } 170c3899f8dSAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 171c3899f8dSAtsushi Murai } 172c3899f8dSAtsushi Murai 173c3899f8dSAtsushi Murai void 174944f7098SBrian Somers Cleanup(int excode) 175af57ed9fSAtsushi Murai { 1760fe7ca31SBrian Somers OsInterfaceDown(1); 1770fe7ca31SBrian Somers HangupModem(1); 1789a571ec7SBrian Somers nointr_sleep(1); 1796efd9292SBrian Somers if (mode & MODE_AUTO) 1806e4959f0SBrian Somers DeleteIfRoutes(1); 1815106c671SBrian Somers ID0unlink(pid_filename); 1826e4959f0SBrian Somers if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 1836e4959f0SBrian Somers char c = EX_ERRDEAD; 184944f7098SBrian Somers 1856e4959f0SBrian Somers if (write(BGFiledes[1], &c, 1) == 1) 186927145beSBrian Somers LogPrintf(LogPHASE, "Parent notified of failure.\n"); 1876e4959f0SBrian Somers else 188927145beSBrian Somers LogPrintf(LogPHASE, "Failed to notify parent of failure.\n"); 1896e4959f0SBrian Somers close(BGFiledes[1]); 1906e4959f0SBrian Somers } 191927145beSBrian Somers LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); 1924ef16f24SBrian Somers ServerClose(); 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() */ 203873725ccSBrian Somers LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo); 204944f7098SBrian Somers reconnectState = RECON_FALSE; 205944f7098SBrian Somers reconnectCount = 0; 206368aee2bSBrian Somers DownConnection(); 20775240ed1SBrian Somers dial_up = 0; 2086d14e2a8SJordan K. Hubbard } 209af57ed9fSAtsushi Murai 210af57ed9fSAtsushi Murai static void 211944f7098SBrian Somers CloseSession(int signo) 212af57ed9fSAtsushi Murai { 2136d14e2a8SJordan K. Hubbard if (BGPid) { 2146d14e2a8SJordan K. Hubbard kill(BGPid, SIGINT); 2156d14e2a8SJordan K. Hubbard exit(EX_TERM); 2166d14e2a8SJordan K. Hubbard } 217927145beSBrian Somers LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo); 21825aa96acSBrian Somers reconnect(RECON_FALSE); 219af57ed9fSAtsushi Murai LcpClose(); 220af57ed9fSAtsushi Murai Cleanup(EX_TERM); 221af57ed9fSAtsushi Murai } 222c3899f8dSAtsushi Murai 223c3899f8dSAtsushi Murai static void 224c3899f8dSAtsushi Murai TerminalCont() 225c3899f8dSAtsushi Murai { 226f5ff0f7cSBrian Somers pending_signal(SIGCONT, SIG_DFL); 227f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 228c3899f8dSAtsushi Murai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 229c3899f8dSAtsushi Murai } 230c3899f8dSAtsushi Murai 231c3899f8dSAtsushi Murai static void 232944f7098SBrian Somers TerminalStop(int signo) 233c3899f8dSAtsushi Murai { 234f5ff0f7cSBrian Somers pending_signal(SIGCONT, TerminalCont); 235c3899f8dSAtsushi Murai TtyOldMode(); 236f5ff0f7cSBrian Somers pending_signal(SIGTSTP, SIG_DFL); 237c3899f8dSAtsushi Murai kill(getpid(), signo); 238c3899f8dSAtsushi Murai } 239c3899f8dSAtsushi Murai 2404ef16f24SBrian Somers static void 241944f7098SBrian Somers SetUpServer(int signo) 2424ef16f24SBrian Somers { 2434ef16f24SBrian Somers int res; 244944f7098SBrian Somers 2454ef16f24SBrian Somers if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0) 246683cef3cSBrian Somers LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n", 247683cef3cSBrian Somers res, SERVER_PORT + tunno); 2484ef16f24SBrian Somers } 2494ef16f24SBrian Somers 2506efd9292SBrian Somers static char * 2516efd9292SBrian Somers ex_desc(int ex) 2526efd9292SBrian Somers { 2536efd9292SBrian Somers static char num[12]; 2546efd9292SBrian Somers static char *desc[] = {"normal", "start", "sock", 2556efd9292SBrian Somers "modem", "dial", "dead", "done", "reboot", "errdead", 2566efd9292SBrian Somers "hangup", "term", "nodial", "nologin"}; 2576efd9292SBrian Somers 2586efd9292SBrian Somers if (ex >= 0 && ex < sizeof(desc) / sizeof(*desc)) 2596efd9292SBrian Somers return desc[ex]; 2606efd9292SBrian Somers snprintf(num, sizeof num, "%d", ex); 2616efd9292SBrian Somers return num; 2626efd9292SBrian Somers } 263c3899f8dSAtsushi Murai 26475240ed1SBrian Somers static void 265af57ed9fSAtsushi Murai Usage() 266af57ed9fSAtsushi Murai { 267680026d6SNate Williams fprintf(stderr, 2686d14e2a8SJordan K. Hubbard "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 269af57ed9fSAtsushi Murai exit(EX_START); 270af57ed9fSAtsushi Murai } 271af57ed9fSAtsushi Murai 27275240ed1SBrian Somers static void 273af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 274af57ed9fSAtsushi Murai { 275af57ed9fSAtsushi Murai int optc; 276af57ed9fSAtsushi Murai char *cp; 277af57ed9fSAtsushi Murai 278af57ed9fSAtsushi Murai optc = 0; 279af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 280af57ed9fSAtsushi Murai cp = *argv + 1; 281af57ed9fSAtsushi Murai if (strcmp(cp, "auto") == 0) 282af57ed9fSAtsushi Murai mode |= MODE_AUTO; 2836d14e2a8SJordan K. Hubbard else if (strcmp(cp, "background") == 0) 2846efd9292SBrian Somers mode |= MODE_BACKGROUND | MODE_AUTO; 285af57ed9fSAtsushi Murai else if (strcmp(cp, "direct") == 0) 286af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 287af57ed9fSAtsushi Murai else if (strcmp(cp, "dedicated") == 0) 288af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 289680026d6SNate Williams else if (strcmp(cp, "ddial") == 0) 290680026d6SNate Williams mode |= MODE_DDIAL | MODE_AUTO; 291a9f484e5SJordan K. Hubbard else if (strcmp(cp, "alias") == 0) { 2926ed9fb2fSBrian Somers if (loadAliasHandlers(&VarAliasHandlers) == 0) 293a9f484e5SJordan K. Hubbard mode |= MODE_ALIAS; 2946ed9fb2fSBrian Somers else 295927145beSBrian Somers LogPrintf(LogWARN, "Cannot load alias library\n"); 296a9f484e5SJordan K. Hubbard optc--; /* this option isn't exclusive */ 297944f7098SBrian Somers } else 298af57ed9fSAtsushi Murai Usage(); 299af57ed9fSAtsushi Murai optc++; 300944f7098SBrian Somers argv++; 301944f7098SBrian Somers argc--; 302af57ed9fSAtsushi Murai } 303af57ed9fSAtsushi Murai if (argc > 1) { 304af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 305af57ed9fSAtsushi Murai exit(EX_START); 306af57ed9fSAtsushi Murai } 307944f7098SBrian Somers if (argc == 1) 308944f7098SBrian Somers dstsystem = *argv; 309af57ed9fSAtsushi Murai 310af57ed9fSAtsushi Murai if (optc > 1) { 311af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 312af57ed9fSAtsushi Murai exit(EX_START); 313af57ed9fSAtsushi Murai } 314af57ed9fSAtsushi Murai } 315af57ed9fSAtsushi Murai 316af57ed9fSAtsushi Murai static void 317af57ed9fSAtsushi Murai Greetings() 318af57ed9fSAtsushi Murai { 319927145beSBrian Somers if (VarTerm) { 320927145beSBrian Somers fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n"); 321927145beSBrian Somers fflush(VarTerm); 322927145beSBrian Somers } 323af57ed9fSAtsushi Murai } 324af57ed9fSAtsushi Murai 3254ef16f24SBrian Somers int 326944f7098SBrian Somers main(int argc, char **argv) 327af57ed9fSAtsushi Murai { 328aefd026aSBrian Somers FILE *lockfile; 329927145beSBrian Somers char *name; 330af57ed9fSAtsushi Murai 3310706ff38SBrian Somers VarTerm = 0; 33275240ed1SBrian Somers name = strrchr(argv[0], '/'); 333927145beSBrian Somers LogOpen(name ? name + 1 : argv[0]); 334927145beSBrian Somers 335944f7098SBrian Somers argc--; 336944f7098SBrian Somers argv++; 337af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 338683cef3cSBrian Somers if (!(mode & MODE_DIRECT)) { 339683cef3cSBrian Somers if (getuid() != 0) { 340683cef3cSBrian Somers fprintf(stderr, "You may only run ppp in client mode as user id 0\n"); 341683cef3cSBrian Somers LogClose(); 342683cef3cSBrian Somers return EX_NOPERM; 343683cef3cSBrian Somers } 3440706ff38SBrian Somers VarTerm = stdout; 345683cef3cSBrian Somers } 3465106c671SBrian Somers ID0init(); 347af57ed9fSAtsushi Murai Greetings(); 348af57ed9fSAtsushi Murai IpcpDefAddress(); 349683cef3cSBrian Somers LocalAuthInit(); 350af57ed9fSAtsushi Murai 351927145beSBrian Somers if (SelectSystem("default", CONFFILE) < 0 && VarTerm) 352927145beSBrian Somers fprintf(VarTerm, "Warning: No default entry is given in config file.\n"); 353af57ed9fSAtsushi Murai 354af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 3554ef16f24SBrian Somers LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno)); 3564ef16f24SBrian Somers return EX_START; 357af57ed9fSAtsushi Murai } 3586efd9292SBrian Somers if (mode & (MODE_AUTO | MODE_DIRECT | MODE_DEDICATED)) 359af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 360af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 361927145beSBrian Somers fprintf(VarTerm, "Interactive mode\n"); 362cc39a98fSBrian Somers netfd = STDOUT_FILENO; 363af57ed9fSAtsushi Murai } else if (mode & MODE_AUTO) { 364927145beSBrian Somers fprintf(VarTerm, "Automatic Dialer mode\n"); 365af57ed9fSAtsushi Murai if (dstsystem == NULL) { 366927145beSBrian Somers if (VarTerm) 367927145beSBrian Somers fprintf(VarTerm, "Destination system must be specified in" 3686efd9292SBrian Somers " auto, background or ddial mode.\n"); 3694ef16f24SBrian Somers return EX_START; 3706d14e2a8SJordan K. Hubbard } 371af57ed9fSAtsushi Murai } 37253c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 373af57ed9fSAtsushi Murai 374873725ccSBrian Somers pending_signal(SIGHUP, CloseSession); 375f5ff0f7cSBrian Somers pending_signal(SIGTERM, CloseSession); 376873725ccSBrian Somers pending_signal(SIGINT, CloseConnection); 377f5ff0f7cSBrian Somers pending_signal(SIGQUIT, CloseSession); 37853c9f6c0SAtsushi Murai #ifdef SIGPIPE 379e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 38053c9f6c0SAtsushi Murai #endif 38153c9f6c0SAtsushi Murai #ifdef SIGALRM 382f5ff0f7cSBrian Somers pending_signal(SIGALRM, SIG_IGN); 38353c9f6c0SAtsushi Murai #endif 3844ef16f24SBrian Somers if (mode & MODE_INTER) { 385c3899f8dSAtsushi Murai #ifdef SIGTSTP 386f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 387c3899f8dSAtsushi Murai #endif 388c3899f8dSAtsushi Murai #ifdef SIGTTIN 389f5ff0f7cSBrian Somers pending_signal(SIGTTIN, TerminalStop); 390c3899f8dSAtsushi Murai #endif 391c3899f8dSAtsushi Murai #ifdef SIGTTOU 392f5ff0f7cSBrian Somers pending_signal(SIGTTOU, SIG_IGN); 393c3899f8dSAtsushi Murai #endif 394c3899f8dSAtsushi Murai } 3954ef16f24SBrian Somers #ifdef SIGUSR1 3964ef16f24SBrian Somers if (mode != MODE_INTER) 3974ef16f24SBrian Somers pending_signal(SIGUSR1, SetUpServer); 3984ef16f24SBrian Somers #endif 399af57ed9fSAtsushi Murai 400af57ed9fSAtsushi Murai if (dstsystem) { 401af57ed9fSAtsushi Murai if (SelectSystem(dstsystem, CONFFILE) < 0) { 4020706ff38SBrian Somers LogPrintf(LogWARN, "Destination system not found in conf file.\n"); 403af57ed9fSAtsushi Murai Cleanup(EX_START); 404af57ed9fSAtsushi Murai } 405af57ed9fSAtsushi Murai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 4060706ff38SBrian Somers LogPrintf(LogWARN, "Must specify dstaddr with" 4076efd9292SBrian Somers " auto, background or ddial mode.\n"); 408af57ed9fSAtsushi Murai Cleanup(EX_START); 409af57ed9fSAtsushi Murai } 410af57ed9fSAtsushi Murai } 4116efd9292SBrian Somers 4124ef16f24SBrian Somers if (!(mode & MODE_INTER)) { 4136d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4146d14e2a8SJordan K. Hubbard if (pipe(BGFiledes)) { 415afc7fa2cSBrian Somers LogPrintf(LogERROR, "pipe: %s\n", strerror(errno)); 4166d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4176d14e2a8SJordan K. Hubbard } 4186d14e2a8SJordan K. Hubbard } 41975240ed1SBrian Somers /* Create server socket and listen (initial value is -2) */ 420683cef3cSBrian Somers if (server == -2) 421683cef3cSBrian Somers ServerTcpOpen(SERVER_PORT + tunno); 422af57ed9fSAtsushi Murai 423af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 4246d14e2a8SJordan K. Hubbard pid_t bgpid; 425a9c6b5dfSAtsushi Murai 4266d14e2a8SJordan K. Hubbard bgpid = fork(); 4276d14e2a8SJordan K. Hubbard if (bgpid == -1) { 428afc7fa2cSBrian Somers LogPrintf(LogERROR, "fork: %s\n", strerror(errno)); 4296d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4306d14e2a8SJordan K. Hubbard } 4316d14e2a8SJordan K. Hubbard if (bgpid) { 4326d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 433a9c6b5dfSAtsushi Murai 4346d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4356d14e2a8SJordan K. Hubbard /* Wait for our child to close its pipe before we exit. */ 4366d14e2a8SJordan K. Hubbard BGPid = bgpid; 4376e4959f0SBrian Somers close(BGFiledes[1]); 4386efd9292SBrian Somers if (read(BGFiledes[0], &c, 1) != 1) { 439927145beSBrian Somers fprintf(VarTerm, "Child exit, no status.\n"); 440927145beSBrian Somers LogPrintf(LogPHASE, "Parent: Child exit, no status.\n"); 4416efd9292SBrian Somers } else if (c == EX_NORMAL) { 442927145beSBrian Somers fprintf(VarTerm, "PPP enabled.\n"); 443927145beSBrian Somers LogPrintf(LogPHASE, "Parent: PPP enabled.\n"); 4446efd9292SBrian Somers } else { 445927145beSBrian Somers fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c)); 446927145beSBrian Somers LogPrintf(LogPHASE, "Parent: Child failed (%s).\n", 44780e37c72SBrian Somers ex_desc((int) c)); 4486efd9292SBrian Somers } 4496e4959f0SBrian Somers close(BGFiledes[0]); 4506d14e2a8SJordan K. Hubbard } 4514ef16f24SBrian Somers return c; 4526e4959f0SBrian Somers } else if (mode & MODE_BACKGROUND) 4536e4959f0SBrian Somers close(BGFiledes[0]); 454aefd026aSBrian Somers } 455aefd026aSBrian Somers 456d656a4c5SBrian Somers VarTerm = 0; /* We know it's currently stdout */ 457fd2bc5ebSBrian Somers close(1); 458d656a4c5SBrian Somers close(2); 4590706ff38SBrian Somers 460af57ed9fSAtsushi Murai #ifdef DOTTYINIT 461d656a4c5SBrian Somers if (mode & (MODE_DIRECT | MODE_DEDICATED)) 462af57ed9fSAtsushi Murai #else 463d656a4c5SBrian Somers if (mode & MODE_DIRECT) 464af57ed9fSAtsushi Murai #endif 465368aee2bSBrian Somers TtyInit(1); 466d656a4c5SBrian Somers else { 467d656a4c5SBrian Somers setsid(); 468fd2bc5ebSBrian Somers close(0); 469d656a4c5SBrian Somers } 470af57ed9fSAtsushi Murai } else { 471368aee2bSBrian Somers TtyInit(0); 472c3899f8dSAtsushi Murai TtyCommandMode(1); 473af57ed9fSAtsushi Murai } 47435495becSBrian Somers 47535495becSBrian Somers snprintf(pid_filename, sizeof(pid_filename), "%stun%d.pid", 47635495becSBrian Somers _PATH_VARRUN, tunno); 4775106c671SBrian Somers lockfile = ID0fopen(pid_filename, "w"); 4785106c671SBrian Somers if (lockfile != NULL) { 47935495becSBrian Somers fprintf(lockfile, "%d\n", (int) getpid()); 48035495becSBrian Somers fclose(lockfile); 48135495becSBrian Somers } else 48235495becSBrian Somers LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 48335495becSBrian Somers pid_filename, strerror(errno)); 48435495becSBrian Somers 485927145beSBrian Somers LogPrintf(LogPHASE, "PPP Started.\n"); 486af57ed9fSAtsushi Murai 487af57ed9fSAtsushi Murai 488af57ed9fSAtsushi Murai do 489af57ed9fSAtsushi Murai DoLoop(); 490af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 491af57ed9fSAtsushi Murai 492af57ed9fSAtsushi Murai Cleanup(EX_DONE); 4934ef16f24SBrian Somers return 0; 494af57ed9fSAtsushi Murai } 495af57ed9fSAtsushi Murai 496af57ed9fSAtsushi Murai /* 4976d14e2a8SJordan K. Hubbard * Turn into packet mode, where we speak PPP. 498af57ed9fSAtsushi Murai */ 499af57ed9fSAtsushi Murai void 500af57ed9fSAtsushi Murai PacketMode() 501af57ed9fSAtsushi Murai { 5029780ef31SBrian Somers if (RawModem() < 0) { 503927145beSBrian Somers LogPrintf(LogWARN, "PacketMode: Not connected.\n"); 504af57ed9fSAtsushi Murai return; 505af57ed9fSAtsushi Murai } 506af57ed9fSAtsushi Murai AsyncInit(); 50703604f35SBrian Somers VjInit(15); 508af57ed9fSAtsushi Murai LcpInit(); 509af57ed9fSAtsushi Murai IpcpInit(); 510af57ed9fSAtsushi Murai CcpInit(); 511af57ed9fSAtsushi Murai LcpUp(); 512af57ed9fSAtsushi Murai 513af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 514af57ed9fSAtsushi Murai if ((mode & (MODE_INTER | MODE_AUTO)) == MODE_INTER) { 515c3899f8dSAtsushi Murai TtyCommandMode(1); 516927145beSBrian Somers if (VarTerm) { 517927145beSBrian Somers fprintf(VarTerm, "Packet mode.\n"); 518b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 519af57ed9fSAtsushi Murai } 520af57ed9fSAtsushi Murai } 521927145beSBrian Somers } 522af57ed9fSAtsushi Murai 523af57ed9fSAtsushi Murai static void 524af57ed9fSAtsushi Murai ShowHelp() 525af57ed9fSAtsushi Murai { 526030d3ce6SBrian Somers fprintf(stderr, "The following commands are available:\r\n"); 527030d3ce6SBrian Somers fprintf(stderr, " ~p\tEnter Packet mode\r\n"); 528030d3ce6SBrian Somers fprintf(stderr, " ~-\tDecrease log level\r\n"); 529030d3ce6SBrian Somers fprintf(stderr, " ~+\tIncrease log level\r\n"); 530030d3ce6SBrian Somers fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n"); 531030d3ce6SBrian Somers fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n"); 532030d3ce6SBrian Somers fprintf(stderr, " ~.\tTerminate program\r\n"); 533030d3ce6SBrian Somers fprintf(stderr, " ~?\tThis help\r\n"); 534af57ed9fSAtsushi Murai } 535af57ed9fSAtsushi Murai 536af57ed9fSAtsushi Murai static void 537af57ed9fSAtsushi Murai ReadTty() 538af57ed9fSAtsushi Murai { 539af57ed9fSAtsushi Murai int n; 540af57ed9fSAtsushi Murai char ch; 541af57ed9fSAtsushi Murai static int ttystate; 542927145beSBrian Somers FILE *oVarTerm; 543944f7098SBrian Somers 544af57ed9fSAtsushi Murai #define MAXLINESIZE 200 545af57ed9fSAtsushi Murai char linebuff[MAXLINESIZE]; 546af57ed9fSAtsushi Murai 547927145beSBrian Somers LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n", 548927145beSBrian Somers TermMode, netfd, mode); 549af57ed9fSAtsushi Murai if (!TermMode) { 550af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff) - 1); 55153c9f6c0SAtsushi Murai if (n > 0) { 552927145beSBrian Somers aft_cmd = 1; 553a1e8f937SBrian Somers if (linebuff[n-1] == '\n') 554a1e8f937SBrian Somers linebuff[--n] = '\0'; 555a1e8f937SBrian Somers if (n) { 556a1e8f937SBrian Somers if (IsInteractive(0)) 557a1e8f937SBrian Somers LogPrintf(LogCOMMAND, "%s\n", linebuff); 558a1e8f937SBrian Somers else 559331953abSBrian Somers LogPrintf(LogCOMMAND, "Client: %s\n", linebuff); 560af57ed9fSAtsushi Murai DecodeCommand(linebuff, n, 1); 561a1e8f937SBrian Somers } else 562a1e8f937SBrian Somers Prompt(); 56353c9f6c0SAtsushi Murai } else { 564927145beSBrian Somers LogPrintf(LogPHASE, "client connection closed.\n"); 565e0d3e233SAndrey A. Chernov VarLocalAuth = LOCAL_NO_AUTH; 566af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 567927145beSBrian Somers oVarTerm = VarTerm; 568927145beSBrian Somers VarTerm = 0; 569927145beSBrian Somers if (oVarTerm && oVarTerm != stdout) 570927145beSBrian Somers fclose(oVarTerm); 571927145beSBrian Somers close(netfd); 572927145beSBrian Somers netfd = -1; 573af57ed9fSAtsushi Murai } 574af57ed9fSAtsushi Murai return; 575af57ed9fSAtsushi Murai } 576af57ed9fSAtsushi Murai 577af57ed9fSAtsushi Murai /* 578af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 579af57ed9fSAtsushi Murai */ 580927145beSBrian Somers n = read(fileno(VarTerm), &ch, 1); 581afc7fa2cSBrian Somers LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n); 582af57ed9fSAtsushi Murai 583af57ed9fSAtsushi Murai if (n > 0) { 584af57ed9fSAtsushi Murai switch (ttystate) { 585af57ed9fSAtsushi Murai case 0: 586af57ed9fSAtsushi Murai if (ch == '~') 587af57ed9fSAtsushi Murai ttystate++; 588af57ed9fSAtsushi Murai else 589af57ed9fSAtsushi Murai write(modem, &ch, n); 590af57ed9fSAtsushi Murai break; 591af57ed9fSAtsushi Murai case 1: 592af57ed9fSAtsushi Murai switch (ch) { 593af57ed9fSAtsushi Murai case '?': 594af57ed9fSAtsushi Murai ShowHelp(); 595af57ed9fSAtsushi Murai break; 596af57ed9fSAtsushi Murai case 'p': 597944f7098SBrian Somers 598af57ed9fSAtsushi Murai /* 599af57ed9fSAtsushi Murai * XXX: Should check carrier. 600af57ed9fSAtsushi Murai */ 601af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 602af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 603af57ed9fSAtsushi Murai PacketMode(); 604af57ed9fSAtsushi Murai } 605af57ed9fSAtsushi Murai break; 606af57ed9fSAtsushi Murai case '.': 607af57ed9fSAtsushi Murai TermMode = 1; 608927145beSBrian Somers aft_cmd = 1; 609c3899f8dSAtsushi Murai TtyCommandMode(1); 610af57ed9fSAtsushi Murai break; 611927145beSBrian Somers case 't': 612927145beSBrian Somers if (LogIsKept(LogDEBUG)) { 613927145beSBrian Somers ShowTimers(); 614927145beSBrian Somers break; 615927145beSBrian Somers } 616927145beSBrian Somers case 'm': 617927145beSBrian Somers if (LogIsKept(LogDEBUG)) { 618927145beSBrian Somers ShowMemMap(); 619927145beSBrian Somers break; 620927145beSBrian Somers } 621af57ed9fSAtsushi Murai default: 622af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 623927145beSBrian Somers LogPrintf(LogERROR, "error writing to modem.\n"); 624af57ed9fSAtsushi Murai break; 625af57ed9fSAtsushi Murai } 626af57ed9fSAtsushi Murai ttystate = 0; 627af57ed9fSAtsushi Murai break; 628af57ed9fSAtsushi Murai } 629af57ed9fSAtsushi Murai } 630af57ed9fSAtsushi Murai } 631af57ed9fSAtsushi Murai 632af57ed9fSAtsushi Murai 633af57ed9fSAtsushi Murai /* 634af57ed9fSAtsushi Murai * Here, we'll try to detect HDLC frame 635af57ed9fSAtsushi Murai */ 636af57ed9fSAtsushi Murai 637af57ed9fSAtsushi Murai static char *FrameHeaders[] = { 63853c9f6c0SAtsushi Murai "\176\377\003\300\041", 63953c9f6c0SAtsushi Murai "\176\377\175\043\300\041", 64053c9f6c0SAtsushi Murai "\176\177\175\043\100\041", 64153c9f6c0SAtsushi Murai "\176\175\337\175\043\300\041", 64253c9f6c0SAtsushi Murai "\176\175\137\175\043\100\041", 643af57ed9fSAtsushi Murai NULL, 644af57ed9fSAtsushi Murai }; 645af57ed9fSAtsushi Murai 64675240ed1SBrian Somers static u_char * 647944f7098SBrian Somers HdlcDetect(u_char * cp, int n) 648af57ed9fSAtsushi Murai { 64953c9f6c0SAtsushi Murai char *ptr, *fp, **hp; 650af57ed9fSAtsushi Murai 651af57ed9fSAtsushi Murai cp[n] = '\0'; /* be sure to null terminated */ 652af57ed9fSAtsushi Murai ptr = NULL; 653af57ed9fSAtsushi Murai for (hp = FrameHeaders; *hp; hp++) { 65453c9f6c0SAtsushi Murai fp = *hp; 65553c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 65653c9f6c0SAtsushi Murai fp++; 657ed6a16c1SPoul-Henning Kamp ptr = strstr((char *) cp, fp); 658ed6a16c1SPoul-Henning Kamp if (ptr) 659af57ed9fSAtsushi Murai break; 660af57ed9fSAtsushi Murai } 661af57ed9fSAtsushi Murai return ((u_char *) ptr); 662af57ed9fSAtsushi Murai } 663af57ed9fSAtsushi Murai 664af57ed9fSAtsushi Murai static struct pppTimer RedialTimer; 665af57ed9fSAtsushi Murai 666af57ed9fSAtsushi Murai static void 667af57ed9fSAtsushi Murai RedialTimeout() 668af57ed9fSAtsushi Murai { 669af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 670927145beSBrian Somers LogPrintf(LogPHASE, "Redialing timer expired.\n"); 671af57ed9fSAtsushi Murai } 672af57ed9fSAtsushi Murai 673af57ed9fSAtsushi Murai static void 674944f7098SBrian Somers StartRedialTimer(int Timeout) 675af57ed9fSAtsushi Murai { 676af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 677a9c6b5dfSAtsushi Murai 67843ea9d19SBrian Somers if (Timeout) { 679af57ed9fSAtsushi Murai RedialTimer.state = TIMER_STOPPED; 680a9c6b5dfSAtsushi Murai 68143ea9d19SBrian Somers if (Timeout > 0) 68243ea9d19SBrian Somers RedialTimer.load = Timeout * SECTICKS; 683a9c6b5dfSAtsushi Murai else 684a9c6b5dfSAtsushi Murai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 685a9c6b5dfSAtsushi Murai 686927145beSBrian Somers LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n", 68743ea9d19SBrian Somers RedialTimer.load / SECTICKS); 68843ea9d19SBrian Somers 689af57ed9fSAtsushi Murai RedialTimer.func = RedialTimeout; 690af57ed9fSAtsushi Murai StartTimer(&RedialTimer); 691af57ed9fSAtsushi Murai } 692a9c6b5dfSAtsushi Murai } 693af57ed9fSAtsushi Murai 694af57ed9fSAtsushi Murai 695af57ed9fSAtsushi Murai static void 696af57ed9fSAtsushi Murai DoLoop() 697af57ed9fSAtsushi Murai { 698af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 699780700e5SAndrey A. Chernov int pri, i, n, wfd, nfds; 700af57ed9fSAtsushi Murai struct sockaddr_in hisaddr; 701af57ed9fSAtsushi Murai struct timeval timeout, *tp; 702af57ed9fSAtsushi Murai int ssize = sizeof(hisaddr); 703af57ed9fSAtsushi Murai u_char *cp; 704af57ed9fSAtsushi Murai u_char rbuff[MAX_MRU]; 705a9c6b5dfSAtsushi Murai int tries; 70660e218e4SAtsushi Murai int qlen; 707368aee2bSBrian Somers int res; 708c3899f8dSAtsushi Murai pid_t pgroup; 709c3899f8dSAtsushi Murai 710c3899f8dSAtsushi Murai pgroup = getpgrp(); 711af57ed9fSAtsushi Murai 7126efd9292SBrian Somers if (mode & MODE_DIRECT) { 7130706ff38SBrian Somers LogPrintf(LogDEBUG, "Opening modem\n"); 7149780ef31SBrian Somers if (OpenModem() < 0) 715bc240299SBrian Somers return; 716927145beSBrian Somers LogPrintf(LogPHASE, "Packet mode enabled\n"); 717af57ed9fSAtsushi Murai PacketMode(); 718af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 719780700e5SAndrey A. Chernov if (modem < 0) 7209780ef31SBrian Somers while (OpenModem() < 0) 7219a571ec7SBrian Somers nointr_sleep(VarReconnectTimer); 722af57ed9fSAtsushi Murai } 723927145beSBrian Somers fflush(VarTerm); 724af57ed9fSAtsushi Murai 72584b8a6ebSAtsushi Murai timeout.tv_sec = 0; 726af57ed9fSAtsushi Murai timeout.tv_usec = 0; 72725aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 728af57ed9fSAtsushi Murai 7296e4959f0SBrian Somers if (mode & MODE_BACKGROUND) 73075240ed1SBrian Somers dial_up = 1; /* Bring the line up */ 7316e4959f0SBrian Somers else 73275240ed1SBrian Somers dial_up = 0; /* XXXX */ 733a9c6b5dfSAtsushi Murai tries = 0; 734af57ed9fSAtsushi Murai for (;;) { 735780700e5SAndrey A. Chernov nfds = 0; 736944f7098SBrian Somers FD_ZERO(&rfds); 737944f7098SBrian Somers FD_ZERO(&wfds); 738944f7098SBrian Somers FD_ZERO(&efds); 73984b8a6ebSAtsushi Murai 74084b8a6ebSAtsushi Murai /* 741944f7098SBrian Somers * If the link is down and we're in DDIAL mode, bring it back up. 742680026d6SNate Williams */ 743680026d6SNate Williams if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 74475240ed1SBrian Somers dial_up = 1; 745680026d6SNate Williams 746680026d6SNate Williams /* 747944f7098SBrian Somers * If we lost carrier and want to re-establish the connection due to the 748944f7098SBrian Somers * "set reconnect" value, we'd better bring the line back up. 74907030d97SBrian Somers */ 7506efd9292SBrian Somers if (LcpFsm.state <= ST_CLOSED) { 75175240ed1SBrian Somers if (!dial_up && reconnectState == RECON_TRUE) { 7526efd9292SBrian Somers if (++reconnectCount <= VarReconnectTries) { 753927145beSBrian Somers LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n", 7546efd9292SBrian Somers reconnectCount, VarReconnectTries); 75507030d97SBrian Somers StartRedialTimer(VarReconnectTimer); 75675240ed1SBrian Somers dial_up = 1; 757298091daSBrian Somers } else { 7586efd9292SBrian Somers if (VarReconnectTries) 759927145beSBrian Somers LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n", 760298091daSBrian Somers VarReconnectTries); 7616efd9292SBrian Somers reconnectCount = 0; 7626efd9292SBrian Somers if (mode & MODE_BACKGROUND) 7636efd9292SBrian Somers Cleanup(EX_DEAD); 7646efd9292SBrian Somers } 76525aa96acSBrian Somers reconnectState = RECON_ENVOKED; 7666efd9292SBrian Somers } 76707030d97SBrian Somers } 76807030d97SBrian Somers 76907030d97SBrian Somers /* 770944f7098SBrian Somers * If Ip packet for output is enqueued and require dial up, Just do it! 77184b8a6ebSAtsushi Murai */ 77207030d97SBrian Somers if (dial_up && RedialTimer.state != TIMER_RUNNING) { 773927145beSBrian Somers LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem); 7749780ef31SBrian Somers if (OpenModem() < 0) { 7750706ff38SBrian Somers tries++; 776712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries) 7770706ff38SBrian Somers LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n", 7780706ff38SBrian Somers tries, VarDialTries); 7790706ff38SBrian Somers else 7800706ff38SBrian Somers LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries); 7810706ff38SBrian Somers 782712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) { 7830706ff38SBrian Somers if (mode & MODE_BACKGROUND) 7840706ff38SBrian Somers Cleanup(EX_DIAL); /* Can't get the modem */ 78575240ed1SBrian Somers dial_up = 0; 7860706ff38SBrian Somers reconnectState = RECON_UNKNOWN; 7870706ff38SBrian Somers reconnectCount = 0; 7880706ff38SBrian Somers tries = 0; 7890706ff38SBrian Somers } else 79043ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 79184b8a6ebSAtsushi Murai } else { 792944f7098SBrian Somers tries++; /* Tries are per number, not per list of 793944f7098SBrian Somers * numbers. */ 794712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries) 795712ae387SBrian Somers LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries); 796c0139fb2SBrian Somers else 797927145beSBrian Somers LogPrintf(LogCHAT, "Dial attempt %u\n", tries); 798712ae387SBrian Somers 799368aee2bSBrian Somers if ((res = DialModem()) == EX_DONE) { 8009a571ec7SBrian Somers nointr_sleep(1); /* little pause to allow peer starts */ 80184b8a6ebSAtsushi Murai ModemTimeout(); 80284b8a6ebSAtsushi Murai PacketMode(); 80375240ed1SBrian Somers dial_up = 0; 80425aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 805a9c6b5dfSAtsushi Murai tries = 0; 80684b8a6ebSAtsushi Murai } else { 8074ed9958fSBrian Somers if (mode & MODE_BACKGROUND) { 808368aee2bSBrian Somers if (VarNextPhone == NULL || res == EX_SIG) 8094ed9958fSBrian Somers Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 8104ed9958fSBrian Somers else 81143ea9d19SBrian Somers /* Try all numbers in background mode */ 81243ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 813368aee2bSBrian Somers } else if (!(mode & MODE_DDIAL) && 814368aee2bSBrian Somers ((VarDialTries && tries >= VarDialTries) || 815368aee2bSBrian Somers res == EX_SIG)) { 816c0139fb2SBrian Somers /* I give up ! Can't get through :( */ 81743ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 81875240ed1SBrian Somers dial_up = 0; 81925aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 82025aa96acSBrian Somers reconnectCount = 0; 821a9c6b5dfSAtsushi Murai tries = 0; 822c0139fb2SBrian Somers } else if (VarNextPhone == NULL) 823c0139fb2SBrian Somers /* Dial failed. Keep quite during redial wait period. */ 82443ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 825c0139fb2SBrian Somers else 82643ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 82784b8a6ebSAtsushi Murai } 82884b8a6ebSAtsushi Murai } 82984b8a6ebSAtsushi Murai } 83060e218e4SAtsushi Murai qlen = ModemQlen(); 83176bd0c0aSDoug Rabson 83276bd0c0aSDoug Rabson if (qlen == 0) { 83376bd0c0aSDoug Rabson IpStartOutput(); 83476bd0c0aSDoug Rabson qlen = ModemQlen(); 83576bd0c0aSDoug Rabson } 836780700e5SAndrey A. Chernov if (modem >= 0) { 837780700e5SAndrey A. Chernov if (modem + 1 > nfds) 838780700e5SAndrey A. Chernov nfds = modem + 1; 83984b8a6ebSAtsushi Murai FD_SET(modem, &rfds); 84084b8a6ebSAtsushi Murai FD_SET(modem, &efds); 84160e218e4SAtsushi Murai if (qlen > 0) { 84284b8a6ebSAtsushi Murai FD_SET(modem, &wfds); 84384b8a6ebSAtsushi Murai } 84484b8a6ebSAtsushi Murai } 845780700e5SAndrey A. Chernov if (server >= 0) { 846780700e5SAndrey A. Chernov if (server + 1 > nfds) 847780700e5SAndrey A. Chernov nfds = server + 1; 848780700e5SAndrey A. Chernov FD_SET(server, &rfds); 849780700e5SAndrey A. Chernov } 850af57ed9fSAtsushi Murai 851944f7098SBrian Somers /* 852944f7098SBrian Somers * *** IMPORTANT *** 853af57ed9fSAtsushi Murai * 854944f7098SBrian Somers * CPU is serviced every TICKUNIT micro seconds. This value must be chosen 855944f7098SBrian Somers * with great care. If this values is too big, it results loss of 856944f7098SBrian Somers * characters from modem and poor responce. If this values is too small, 857944f7098SBrian Somers * ppp process eats many CPU time. 858af57ed9fSAtsushi Murai */ 85953c9f6c0SAtsushi Murai #ifndef SIGALRM 8609a571ec7SBrian Somers nointr_usleep(TICKUNIT); 861af57ed9fSAtsushi Murai TimerService(); 862f5ff0f7cSBrian Somers #else 863f5ff0f7cSBrian Somers handle_signals(); 86453c9f6c0SAtsushi Murai #endif 86568d2b4d6SBruce Evans 86668d2b4d6SBruce Evans /* If there are aren't many packets queued, look for some more. */ 867780700e5SAndrey A. Chernov if (qlen < 20 && tun_in >= 0) { 868780700e5SAndrey A. Chernov if (tun_in + 1 > nfds) 869780700e5SAndrey A. Chernov nfds = tun_in + 1; 87084b8a6ebSAtsushi Murai FD_SET(tun_in, &rfds); 871780700e5SAndrey A. Chernov } 872780700e5SAndrey A. Chernov if (netfd >= 0) { 873780700e5SAndrey A. Chernov if (netfd + 1 > nfds) 874780700e5SAndrey A. Chernov nfds = netfd + 1; 875af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 876af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 877af57ed9fSAtsushi Murai } 87853c9f6c0SAtsushi Murai #ifndef SIGALRM 879944f7098SBrian Somers 880af57ed9fSAtsushi Murai /* 881944f7098SBrian Somers * Normally, select() will not block because modem is writable. In AUTO 882944f7098SBrian Somers * mode, select will block until we find packet from tun 883af57ed9fSAtsushi Murai */ 884af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL; 885780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 88653c9f6c0SAtsushi Murai #else 887944f7098SBrian Somers 88884b8a6ebSAtsushi Murai /* 889944f7098SBrian Somers * When SIGALRM timer is running, a select function will be return -1 and 890944f7098SBrian Somers * EINTR after a Time Service signal hundler is done. If the redial 891944f7098SBrian Somers * timer is not running and we are trying to dial, poll with a 0 value 892944f7098SBrian Somers * timer. 89384b8a6ebSAtsushi Murai */ 894a9c6b5dfSAtsushi Murai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 895780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 89653c9f6c0SAtsushi Murai #endif 8976b0b88d8SBrian Somers 898af57ed9fSAtsushi Murai if (i == 0) { 899af57ed9fSAtsushi Murai continue; 900af57ed9fSAtsushi Murai } 901534fe541SBrian Somers if (i < 0) { 902534fe541SBrian Somers if (errno == EINTR) { 903f5ff0f7cSBrian Somers handle_signals(); 904f5ff0f7cSBrian Somers continue; 90584b8a6ebSAtsushi Murai } 906afc7fa2cSBrian Somers LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno)); 907af57ed9fSAtsushi Murai break; 908af57ed9fSAtsushi Murai } 909780700e5SAndrey A. Chernov if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 910927145beSBrian Somers LogPrintf(LogALERT, "Exception detected.\n"); 911af57ed9fSAtsushi Murai break; 912af57ed9fSAtsushi Murai } 913780700e5SAndrey A. Chernov if (server >= 0 && FD_ISSET(server, &rfds)) { 914927145beSBrian Somers LogPrintf(LogPHASE, "connected to client.\n"); 915af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *) & hisaddr, &ssize); 916e0d3e233SAndrey A. Chernov if (wfd < 0) { 917afc7fa2cSBrian Somers LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno)); 918e0d3e233SAndrey A. Chernov continue; 919e0d3e233SAndrey A. Chernov } 920780700e5SAndrey A. Chernov if (netfd >= 0) { 921af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 922af57ed9fSAtsushi Murai close(wfd); 923af57ed9fSAtsushi Murai continue; 924af57ed9fSAtsushi Murai } else 925af57ed9fSAtsushi Murai netfd = wfd; 926927145beSBrian Somers VarTerm = fdopen(netfd, "a+"); 927af57ed9fSAtsushi Murai mode |= MODE_INTER; 928af57ed9fSAtsushi Murai Greetings(); 929a1e8f937SBrian Somers IsInteractive(1); 930274e766cSBrian Somers Prompt(); 931af57ed9fSAtsushi Murai } 932780700e5SAndrey A. Chernov if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 933f1884650SAtsushi Murai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 934af57ed9fSAtsushi Murai /* something to read from tty */ 935af57ed9fSAtsushi Murai ReadTty(); 936af57ed9fSAtsushi Murai } 937780700e5SAndrey A. Chernov if (modem >= 0) { 938af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 939af57ed9fSAtsushi Murai ModemStartOutput(modem); 940af57ed9fSAtsushi Murai } 941af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 94253c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 9439a571ec7SBrian Somers nointr_usleep(10000); 944af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 945af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 946af57ed9fSAtsushi Murai DownConnection(); 947af57ed9fSAtsushi Murai } else 948927145beSBrian Somers LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n); 949af57ed9fSAtsushi Murai 950af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 951944f7098SBrian Somers 952af57ed9fSAtsushi Murai /* 953af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 954af57ed9fSAtsushi Murai */ 955af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 956af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 957af57ed9fSAtsushi Murai if (cp) { 958944f7098SBrian Somers 959af57ed9fSAtsushi Murai /* 960af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 961af57ed9fSAtsushi Murai */ 962af57ed9fSAtsushi Murai if (cp != rbuff) { 963927145beSBrian Somers write(modem, rbuff, cp - rbuff); 964927145beSBrian Somers write(modem, "\r\n", 2); 965af57ed9fSAtsushi Murai } 966af57ed9fSAtsushi Murai PacketMode(); 967af57ed9fSAtsushi Murai } else 968927145beSBrian Somers write(fileno(VarTerm), rbuff, n); 969af57ed9fSAtsushi Murai } 970af57ed9fSAtsushi Murai } else { 971af57ed9fSAtsushi Murai if (n > 0) 972af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 973af57ed9fSAtsushi Murai } 974af57ed9fSAtsushi Murai } 975af57ed9fSAtsushi Murai } 976944f7098SBrian Somers if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read 977944f7098SBrian Somers * from tun */ 978af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 979af57ed9fSAtsushi Murai if (n < 0) { 980afc7fa2cSBrian Somers LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno)); 981af57ed9fSAtsushi Murai continue; 982af57ed9fSAtsushi Murai } 983de451c68SBrian Somers if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) { 984de451c68SBrian Somers /* we've been asked to send something addressed *to* us :( */ 985de451c68SBrian Somers if (VarLoopback) { 986de451c68SBrian Somers pri = PacketCheck(rbuff, n, FL_IN); 987de451c68SBrian Somers if (pri >= 0) { 988de451c68SBrian Somers struct mbuf *bp; 989944f7098SBrian Somers 990de451c68SBrian Somers if (mode & MODE_ALIAS) { 991de451c68SBrian Somers VarPacketAliasIn(rbuff, sizeof rbuff); 992de451c68SBrian Somers n = ntohs(((struct ip *) rbuff)->ip_len); 993de451c68SBrian Somers } 994de451c68SBrian Somers bp = mballoc(n, MB_IPIN); 99575240ed1SBrian Somers memcpy(MBUF_CTOP(bp), rbuff, n); 996de451c68SBrian Somers IpInput(bp); 997de451c68SBrian Somers LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n"); 998de451c68SBrian Somers } 999de451c68SBrian Somers continue; 1000de451c68SBrian Somers } else 1001de451c68SBrian Somers LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n"); 1002de451c68SBrian Somers } 1003de451c68SBrian Somers 1004af57ed9fSAtsushi Murai /* 1005af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 1006af57ed9fSAtsushi Murai * device until IPCP is opened. 1007af57ed9fSAtsushi Murai */ 1008af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 100984b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_DIAL); 1010af57ed9fSAtsushi Murai if (pri >= 0) { 1011a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10126ed9fb2fSBrian Somers VarPacketAliasOut(rbuff, sizeof rbuff); 1013a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *) rbuff)->ip_len); 1014a9f484e5SJordan K. Hubbard } 1015af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 101675240ed1SBrian Somers dial_up = 1; /* XXX */ 1017af57ed9fSAtsushi Murai } 1018af57ed9fSAtsushi Murai continue; 1019af57ed9fSAtsushi Murai } 102084b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_OUT); 1021a9f484e5SJordan K. Hubbard if (pri >= 0) { 1022a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10236ed9fb2fSBrian Somers VarPacketAliasOut(rbuff, sizeof rbuff); 1024a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *) rbuff)->ip_len); 1025a9f484e5SJordan K. Hubbard } 1026af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 1027af57ed9fSAtsushi Murai } 1028af57ed9fSAtsushi Murai } 1029a9f484e5SJordan K. Hubbard } 1030927145beSBrian Somers LogPrintf(LogDEBUG, "Job (DoLoop) done.\n"); 1031af57ed9fSAtsushi Murai } 1032