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 * 204ef16f24SBrian Somers * $Id: main.c,v 1.66 1997/06/24 21:25: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 */ 26af57ed9fSAtsushi Murai #include "fsm.h" 27af57ed9fSAtsushi Murai #include <fcntl.h> 28a9c6b5dfSAtsushi Murai #include <paths.h> 29af57ed9fSAtsushi Murai #include <sys/time.h> 30af57ed9fSAtsushi Murai #include <termios.h> 31c3b6ad66SBrian Somers #include <signal.h> 32af57ed9fSAtsushi Murai #include <sys/wait.h> 33af57ed9fSAtsushi Murai #include <errno.h> 34af57ed9fSAtsushi Murai #include <netdb.h> 359f202f0cSJordan K. Hubbard #include <unistd.h> 36af57ed9fSAtsushi Murai #include <sys/socket.h> 37af57ed9fSAtsushi Murai #include <arpa/inet.h> 38a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h> 39a9f484e5SJordan K. Hubbard #include <netinet/ip.h> 40af57ed9fSAtsushi Murai #include "modem.h" 41af57ed9fSAtsushi Murai #include "os.h" 42af57ed9fSAtsushi Murai #include "hdlc.h" 43ed6a16c1SPoul-Henning Kamp #include "ccp.h" 44af57ed9fSAtsushi Murai #include "lcp.h" 45af57ed9fSAtsushi Murai #include "ipcp.h" 466ed9fb2fSBrian Somers #include "loadalias.h" 47af57ed9fSAtsushi Murai #include "vars.h" 4853c9f6c0SAtsushi Murai #include "auth.h" 4984b8a6ebSAtsushi Murai #include "filter.h" 50ed6a16c1SPoul-Henning Kamp #include "systems.h" 51ed6a16c1SPoul-Henning Kamp #include "ip.h" 52f5ff0f7cSBrian Somers #include "sig.h" 534ef16f24SBrian Somers #include "server.h" 5453c9f6c0SAtsushi Murai 5541db6564SAtsushi Murai #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 56927145beSBrian Somers #define LAUTH_M2 "Warning: Manipulation is allowed by anyone\n" 5741db6564SAtsushi Murai 5853c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 5953c9f6c0SAtsushi Murai #ifdef O_NDELAY 6053c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 6153c9f6c0SAtsushi Murai #endif 6253c9f6c0SAtsushi Murai #endif 63af57ed9fSAtsushi Murai 64af57ed9fSAtsushi Murai extern void VjInit(), AsyncInit(); 65274e766cSBrian Somers extern void AsyncInput(); 66af57ed9fSAtsushi Murai extern int SelectSystem(); 67af57ed9fSAtsushi Murai 68af57ed9fSAtsushi Murai extern void DecodeCommand(), Prompt(); 69b0cdb3ceSJordan K. Hubbard extern int aft_cmd; 70af57ed9fSAtsushi Murai extern int IsInteractive(); 71af57ed9fSAtsushi Murai static void DoLoop(void); 72c3899f8dSAtsushi Murai static void TerminalStop(); 736efd9292SBrian Somers static char *ex_desc(); 74af57ed9fSAtsushi Murai 75af57ed9fSAtsushi Murai static struct termios oldtio; /* Original tty mode */ 76af57ed9fSAtsushi Murai static struct termios comtio; /* Command level tty mode */ 771dff3fc5SAndrey A. Chernov int TermMode; 786d14e2a8SJordan K. Hubbard static pid_t BGPid = 0; 7941c6c543SBrian Somers static char pid_filename[MAXPATHLEN]; 8041c6c543SBrian Somers static char if_filename[MAXPATHLEN]; 8163202ff1SAndrey A. Chernov int tunno; 82af57ed9fSAtsushi Murai 83af57ed9fSAtsushi Murai static void 84368aee2bSBrian Somers TtyInit(int DontWantInt) 85af57ed9fSAtsushi Murai { 86af57ed9fSAtsushi Murai struct termios newtio; 87af57ed9fSAtsushi Murai int stat; 88af57ed9fSAtsushi Murai 89af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 90274e766cSBrian Somers if (stat > 0) { 91af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 92274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 93274e766cSBrian Somers } 94af57ed9fSAtsushi Murai newtio = oldtio; 95af57ed9fSAtsushi Murai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 96af57ed9fSAtsushi Murai newtio.c_iflag = 0; 97af57ed9fSAtsushi Murai newtio.c_oflag &= ~OPOST; 98af57ed9fSAtsushi Murai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 99368aee2bSBrian Somers if (DontWantInt) 100af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 101af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 102af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 103af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 10453c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 105af57ed9fSAtsushi Murai comtio = newtio; 106af57ed9fSAtsushi Murai } 107af57ed9fSAtsushi Murai 108af57ed9fSAtsushi Murai /* 109af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 110af57ed9fSAtsushi Murai */ 111c3899f8dSAtsushi Murai void 112c3899f8dSAtsushi Murai TtyCommandMode(prompt) 113c3899f8dSAtsushi Murai int prompt; 114af57ed9fSAtsushi Murai { 115af57ed9fSAtsushi Murai struct termios newtio; 116af57ed9fSAtsushi Murai int stat; 117af57ed9fSAtsushi Murai 118af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 119af57ed9fSAtsushi Murai return; 12053c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 121c3899f8dSAtsushi Murai newtio.c_lflag |= (ECHO|ISIG|ICANON); 122af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 123af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 12453c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 125af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 126274e766cSBrian Somers if (stat > 0) { 127af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 128274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 129274e766cSBrian Somers } 130af57ed9fSAtsushi Murai TermMode = 0; 131274e766cSBrian Somers if(prompt) Prompt(); 132af57ed9fSAtsushi Murai } 133af57ed9fSAtsushi Murai 134af57ed9fSAtsushi Murai /* 135af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 136af57ed9fSAtsushi Murai */ 137af57ed9fSAtsushi Murai void 138af57ed9fSAtsushi Murai TtyTermMode() 139af57ed9fSAtsushi Murai { 140af57ed9fSAtsushi Murai int stat; 141af57ed9fSAtsushi Murai 14253c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 143af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 144274e766cSBrian Somers if (stat > 0) { 145af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 146274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 147274e766cSBrian Somers } 148af57ed9fSAtsushi Murai TermMode = 1; 149af57ed9fSAtsushi Murai } 150af57ed9fSAtsushi Murai 151af57ed9fSAtsushi Murai void 152c3899f8dSAtsushi Murai TtyOldMode() 153c3899f8dSAtsushi Murai { 154c3899f8dSAtsushi Murai int stat; 155c3899f8dSAtsushi Murai 156c3899f8dSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 157274e766cSBrian Somers if (stat > 0) { 158c3899f8dSAtsushi Murai stat &= ~O_NONBLOCK; 159274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 160274e766cSBrian Somers } 161c3899f8dSAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 162c3899f8dSAtsushi Murai } 163c3899f8dSAtsushi Murai 164c3899f8dSAtsushi Murai void 165af57ed9fSAtsushi Murai Cleanup(excode) 166af57ed9fSAtsushi Murai int excode; 167af57ed9fSAtsushi Murai { 168af57ed9fSAtsushi Murai 169af57ed9fSAtsushi Murai OsLinkdown(); 170af57ed9fSAtsushi Murai OsCloseLink(1); 171af57ed9fSAtsushi Murai sleep(1); 1726efd9292SBrian Somers if (mode & MODE_AUTO) 1736e4959f0SBrian Somers DeleteIfRoutes(1); 174aefd026aSBrian Somers (void)unlink(pid_filename); 175aefd026aSBrian Somers (void)unlink(if_filename); 176af57ed9fSAtsushi Murai OsInterfaceDown(1); 1776e4959f0SBrian Somers if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 1786e4959f0SBrian Somers char c = EX_ERRDEAD; 1796e4959f0SBrian Somers if (write(BGFiledes[1],&c,1) == 1) 180927145beSBrian Somers LogPrintf(LogPHASE,"Parent notified of failure.\n"); 1816e4959f0SBrian Somers else 182927145beSBrian Somers LogPrintf(LogPHASE,"Failed to notify parent of failure.\n"); 1836e4959f0SBrian Somers close(BGFiledes[1]); 1846e4959f0SBrian Somers } 185927145beSBrian Somers LogPrintf(LogPHASE, "PPP Terminated (%s).\n",ex_desc(excode)); 186af57ed9fSAtsushi Murai LogClose(); 1874ef16f24SBrian Somers ServerClose(); 188c3899f8dSAtsushi Murai TtyOldMode(); 189af57ed9fSAtsushi Murai 190af57ed9fSAtsushi Murai exit(excode); 191af57ed9fSAtsushi Murai } 192af57ed9fSAtsushi Murai 193af57ed9fSAtsushi Murai static void 1947a8ef19eSAndrey A. Chernov Hangup(signo) 1957a8ef19eSAndrey A. Chernov int signo; 196af57ed9fSAtsushi Murai { 197368aee2bSBrian Somers /* NOTE, these are manual, we've done a setsid() */ 198368aee2bSBrian Somers reconnect(RECON_FALSE); 199368aee2bSBrian Somers DownConnection(); 2006d14e2a8SJordan K. Hubbard } 201af57ed9fSAtsushi Murai 202af57ed9fSAtsushi Murai static void 2037a8ef19eSAndrey A. Chernov CloseSession(signo) 2047a8ef19eSAndrey A. Chernov int signo; 205af57ed9fSAtsushi Murai { 2066d14e2a8SJordan K. Hubbard if (BGPid) { 2076d14e2a8SJordan K. Hubbard kill (BGPid, SIGINT); 2086d14e2a8SJordan K. Hubbard exit (EX_TERM); 2096d14e2a8SJordan K. Hubbard } 210927145beSBrian Somers LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo); 21125aa96acSBrian Somers reconnect(RECON_FALSE); 212af57ed9fSAtsushi Murai LcpClose(); 213af57ed9fSAtsushi Murai Cleanup(EX_TERM); 214af57ed9fSAtsushi Murai } 215c3899f8dSAtsushi Murai 216c3899f8dSAtsushi Murai static void 217c3899f8dSAtsushi Murai TerminalCont() 218c3899f8dSAtsushi Murai { 219f5ff0f7cSBrian Somers pending_signal(SIGCONT, SIG_DFL); 220f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 221c3899f8dSAtsushi Murai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 222c3899f8dSAtsushi Murai } 223c3899f8dSAtsushi Murai 224c3899f8dSAtsushi Murai static void 225c3899f8dSAtsushi Murai TerminalStop(signo) 226c3899f8dSAtsushi Murai int signo; 227c3899f8dSAtsushi Murai { 228f5ff0f7cSBrian Somers pending_signal(SIGCONT, TerminalCont); 229c3899f8dSAtsushi Murai TtyOldMode(); 230f5ff0f7cSBrian Somers pending_signal(SIGTSTP, SIG_DFL); 231c3899f8dSAtsushi Murai kill(getpid(), signo); 232c3899f8dSAtsushi Murai } 233c3899f8dSAtsushi Murai 2344ef16f24SBrian Somers static void 2354ef16f24SBrian Somers SetUpServer(signo) 2364ef16f24SBrian Somers int signo; 2374ef16f24SBrian Somers { 2384ef16f24SBrian Somers int res; 2394ef16f24SBrian Somers if ((res = ServerTcpOpen(SERVER_PORT+tunno)) != 0) 2404ef16f24SBrian Somers LogPrintf(LogERROR, "Failed %d to open port %d\n", res, SERVER_PORT+tunno); 2414ef16f24SBrian Somers } 2424ef16f24SBrian Somers 2436efd9292SBrian Somers static char * 2446efd9292SBrian Somers ex_desc(int ex) 2456efd9292SBrian Somers { 2466efd9292SBrian Somers static char num[12]; 2476efd9292SBrian Somers static char *desc[] = { "normal", "start", "sock", 2486efd9292SBrian Somers "modem", "dial", "dead", "done", "reboot", "errdead", 2496efd9292SBrian Somers "hangup", "term", "nodial", "nologin" }; 2506efd9292SBrian Somers 2516efd9292SBrian Somers if (ex >= 0 && ex < sizeof(desc)/sizeof(*desc)) 2526efd9292SBrian Somers return desc[ex]; 2536efd9292SBrian Somers snprintf(num, sizeof num, "%d", ex); 2546efd9292SBrian Somers return num; 2556efd9292SBrian Somers } 256c3899f8dSAtsushi Murai 257af57ed9fSAtsushi Murai void 258af57ed9fSAtsushi Murai Usage() 259af57ed9fSAtsushi Murai { 260680026d6SNate Williams fprintf(stderr, 2616d14e2a8SJordan K. Hubbard "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 262af57ed9fSAtsushi Murai exit(EX_START); 263af57ed9fSAtsushi Murai } 264af57ed9fSAtsushi Murai 265af57ed9fSAtsushi Murai void 266af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 267af57ed9fSAtsushi Murai { 268af57ed9fSAtsushi Murai int optc; 269af57ed9fSAtsushi Murai char *cp; 270af57ed9fSAtsushi Murai 271af57ed9fSAtsushi Murai optc = 0; 272af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 273af57ed9fSAtsushi Murai cp = *argv + 1; 274af57ed9fSAtsushi Murai if (strcmp(cp, "auto") == 0) 275af57ed9fSAtsushi Murai mode |= MODE_AUTO; 2766d14e2a8SJordan K. Hubbard else if (strcmp(cp, "background") == 0) 2776efd9292SBrian Somers mode |= MODE_BACKGROUND|MODE_AUTO; 278af57ed9fSAtsushi Murai else if (strcmp(cp, "direct") == 0) 279af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 280af57ed9fSAtsushi Murai else if (strcmp(cp, "dedicated") == 0) 281af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 282680026d6SNate Williams else if (strcmp(cp, "ddial") == 0) 283680026d6SNate Williams mode |= MODE_DDIAL|MODE_AUTO; 284a9f484e5SJordan K. Hubbard else if (strcmp(cp, "alias") == 0) { 2856ed9fb2fSBrian Somers if (loadAliasHandlers(&VarAliasHandlers) == 0) 286a9f484e5SJordan K. Hubbard mode |= MODE_ALIAS; 2876ed9fb2fSBrian Somers else 288927145beSBrian Somers LogPrintf(LogWARN, "Cannot load alias library\n"); 289a9f484e5SJordan K. Hubbard optc--; /* this option isn't exclusive */ 290a9f484e5SJordan K. Hubbard } 291af57ed9fSAtsushi Murai else 292af57ed9fSAtsushi Murai Usage(); 293af57ed9fSAtsushi Murai optc++; 294af57ed9fSAtsushi Murai argv++; argc--; 295af57ed9fSAtsushi Murai } 296af57ed9fSAtsushi Murai if (argc > 1) { 297af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 298af57ed9fSAtsushi Murai exit(EX_START); 299af57ed9fSAtsushi Murai } 300af57ed9fSAtsushi Murai if (argc == 1) dstsystem = *argv; 301af57ed9fSAtsushi Murai 302af57ed9fSAtsushi Murai if (optc > 1) { 303af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 304af57ed9fSAtsushi Murai exit(EX_START); 305af57ed9fSAtsushi Murai } 306af57ed9fSAtsushi Murai } 307af57ed9fSAtsushi Murai 308af57ed9fSAtsushi Murai static void 309af57ed9fSAtsushi Murai Greetings() 310af57ed9fSAtsushi Murai { 311927145beSBrian Somers if (VarTerm) { 312927145beSBrian Somers fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n"); 313927145beSBrian Somers fflush(VarTerm); 314927145beSBrian Somers } 315af57ed9fSAtsushi Murai } 316af57ed9fSAtsushi Murai 3174ef16f24SBrian Somers int 318af57ed9fSAtsushi Murai main(argc, argv) 319af57ed9fSAtsushi Murai int argc; 320af57ed9fSAtsushi Murai char **argv; 321af57ed9fSAtsushi Murai { 322aefd026aSBrian Somers FILE *lockfile; 323927145beSBrian Somers char *name; 324af57ed9fSAtsushi Murai 3250706ff38SBrian Somers VarTerm = 0; 326927145beSBrian Somers name = rindex(argv[0], '/'); 327927145beSBrian Somers LogOpen(name ? name+1 : argv[0]); 328927145beSBrian Somers 329927145beSBrian Somers argc--; argv++; 330af57ed9fSAtsushi Murai mode = MODE_INTER; /* default operation is interactive mode */ 3314ef16f24SBrian Somers netfd = modem = tun_in = -1; 3324ef16f24SBrian Somers server = -2; 333af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 3341f3dee4cSBrian Somers if (!(mode & MODE_DIRECT)) 3350706ff38SBrian Somers VarTerm = stdout; 336af57ed9fSAtsushi Murai Greetings(); 337af57ed9fSAtsushi Murai GetUid(); 338af57ed9fSAtsushi Murai IpcpDefAddress(); 339af57ed9fSAtsushi Murai 340927145beSBrian Somers if (SelectSystem("default", CONFFILE) < 0 && VarTerm) 341927145beSBrian Somers fprintf(VarTerm, "Warning: No default entry is given in config file.\n"); 342af57ed9fSAtsushi Murai 343af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 3444ef16f24SBrian Somers LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno)); 3454ef16f24SBrian Somers return EX_START; 346af57ed9fSAtsushi Murai } 347af57ed9fSAtsushi Murai 3486efd9292SBrian Somers if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 349af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 350af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 351927145beSBrian Somers fprintf(VarTerm, "Interactive mode\n"); 352cc39a98fSBrian Somers netfd = STDOUT_FILENO; 353af57ed9fSAtsushi Murai } else if (mode & MODE_AUTO) { 354927145beSBrian Somers fprintf(VarTerm, "Automatic Dialer mode\n"); 355af57ed9fSAtsushi Murai if (dstsystem == NULL) { 356927145beSBrian Somers if (VarTerm) 357927145beSBrian Somers fprintf(VarTerm, "Destination system must be specified in" 3586efd9292SBrian Somers " auto, background or ddial mode.\n"); 3594ef16f24SBrian Somers return EX_START; 3606d14e2a8SJordan K. Hubbard } 361af57ed9fSAtsushi Murai } 362af57ed9fSAtsushi Murai 36353c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 364af57ed9fSAtsushi Murai 365927145beSBrian Somers pending_signal(SIGHUP, Hangup); 366f5ff0f7cSBrian Somers pending_signal(SIGTERM, CloseSession); 367f5ff0f7cSBrian Somers pending_signal(SIGINT, CloseSession); 368f5ff0f7cSBrian Somers pending_signal(SIGQUIT, CloseSession); 36953c9f6c0SAtsushi Murai #ifdef SIGPIPE 370e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 37153c9f6c0SAtsushi Murai #endif 37253c9f6c0SAtsushi Murai #ifdef SIGALRM 373f5ff0f7cSBrian Somers pending_signal(SIGALRM, SIG_IGN); 37453c9f6c0SAtsushi Murai #endif 3754ef16f24SBrian Somers if(mode & MODE_INTER) { 376c3899f8dSAtsushi Murai #ifdef SIGTSTP 377f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 378c3899f8dSAtsushi Murai #endif 379c3899f8dSAtsushi Murai #ifdef SIGTTIN 380f5ff0f7cSBrian Somers pending_signal(SIGTTIN, TerminalStop); 381c3899f8dSAtsushi Murai #endif 382c3899f8dSAtsushi Murai #ifdef SIGTTOU 383f5ff0f7cSBrian Somers pending_signal(SIGTTOU, SIG_IGN); 384c3899f8dSAtsushi Murai #endif 385c3899f8dSAtsushi Murai } 3864ef16f24SBrian Somers #ifdef SIGUSR1 3874ef16f24SBrian Somers if (mode != MODE_INTER) 3884ef16f24SBrian Somers pending_signal(SIGUSR1, SetUpServer); 3894ef16f24SBrian Somers #endif 390af57ed9fSAtsushi Murai 391af57ed9fSAtsushi Murai if (dstsystem) { 392af57ed9fSAtsushi Murai if (SelectSystem(dstsystem, CONFFILE) < 0) { 3930706ff38SBrian Somers LogPrintf(LogWARN, "Destination system not found in conf file.\n"); 394af57ed9fSAtsushi Murai Cleanup(EX_START); 395af57ed9fSAtsushi Murai } 396af57ed9fSAtsushi Murai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 3970706ff38SBrian Somers LogPrintf(LogWARN, "Must specify dstaddr with" 3986efd9292SBrian Somers " auto, background or ddial mode.\n"); 399af57ed9fSAtsushi Murai Cleanup(EX_START); 400af57ed9fSAtsushi Murai } 401af57ed9fSAtsushi Murai } 402af57ed9fSAtsushi Murai 4034ef16f24SBrian Somers if (ServerType() != NO_SERVER) 4044ef16f24SBrian Somers switch ( LocalAuthInit() ) { 4054ef16f24SBrian Somers case NOT_FOUND: 4064ef16f24SBrian Somers if (VarTerm) { 4074ef16f24SBrian Somers fprintf(VarTerm,LAUTH_M1); 4084ef16f24SBrian Somers fprintf(VarTerm,LAUTH_M2); 4094ef16f24SBrian Somers fflush(VarTerm); 4104ef16f24SBrian Somers } 4114ef16f24SBrian Somers /* Fall down */ 4124ef16f24SBrian Somers case VALID: 4134ef16f24SBrian Somers VarLocalAuth = LOCAL_AUTH; 4144ef16f24SBrian Somers break; 4154ef16f24SBrian Somers default: 4164ef16f24SBrian Somers break; 4174ef16f24SBrian Somers } 4186efd9292SBrian Somers 4194ef16f24SBrian Somers if (!(mode & MODE_INTER)) { 4206d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4216d14e2a8SJordan K. Hubbard if (pipe (BGFiledes)) { 422927145beSBrian Somers LogPrintf(LogERROR, "pipe: %s", strerror(errno)); 4236d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4246d14e2a8SJordan K. Hubbard } 4256d14e2a8SJordan K. Hubbard } 4266efd9292SBrian Somers 4274ef16f24SBrian Somers /* Create server socket and listen. */ 4284ef16f24SBrian Somers if (server == -2 && ServerTcpOpen(SERVER_PORT + tunno) != 0) 429af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 430af57ed9fSAtsushi Murai 431af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 4326d14e2a8SJordan K. Hubbard pid_t bgpid; 433a9c6b5dfSAtsushi Murai 4346d14e2a8SJordan K. Hubbard bgpid = fork (); 4356d14e2a8SJordan K. Hubbard if (bgpid == -1) { 436927145beSBrian Somers LogPrintf(LogERROR, "fork: %s", strerror(errno)); 4376d14e2a8SJordan K. Hubbard Cleanup (EX_SOCK); 4386d14e2a8SJordan K. Hubbard } 4396d14e2a8SJordan K. Hubbard if (bgpid) { 4406d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 441a9c6b5dfSAtsushi Murai 4426d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4436d14e2a8SJordan K. Hubbard /* Wait for our child to close its pipe before we exit. */ 4446d14e2a8SJordan K. Hubbard BGPid = bgpid; 4456e4959f0SBrian Somers close(BGFiledes[1]); 4466efd9292SBrian Somers if (read(BGFiledes[0], &c, 1) != 1) { 447927145beSBrian Somers fprintf(VarTerm, "Child exit, no status.\n"); 448927145beSBrian Somers LogPrintf (LogPHASE, "Parent: Child exit, no status.\n"); 4496efd9292SBrian Somers } else if (c == EX_NORMAL) { 450927145beSBrian Somers fprintf(VarTerm, "PPP enabled.\n"); 451927145beSBrian Somers LogPrintf (LogPHASE, "Parent: PPP enabled.\n"); 4526efd9292SBrian Somers } else { 453927145beSBrian Somers fprintf(VarTerm, "Child failed (%s).\n",ex_desc((int)c)); 454927145beSBrian Somers LogPrintf(LogPHASE, "Parent: Child failed (%s).\n", 45580e37c72SBrian Somers ex_desc((int)c)); 4566efd9292SBrian Somers } 4576e4959f0SBrian Somers close(BGFiledes[0]); 4586d14e2a8SJordan K. Hubbard } 4594ef16f24SBrian Somers return c; 4606e4959f0SBrian Somers } else if (mode & MODE_BACKGROUND) 4616e4959f0SBrian Somers close(BGFiledes[0]); 462aefd026aSBrian Somers } 4636d14e2a8SJordan K. Hubbard 464298091daSBrian Somers snprintf(pid_filename, sizeof (pid_filename), "%stun%d.pid", 4656d14e2a8SJordan K. Hubbard _PATH_VARRUN, tunno); 466aefd026aSBrian Somers (void)unlink(pid_filename); 467a9c6b5dfSAtsushi Murai 468aefd026aSBrian Somers if ((lockfile = fopen(pid_filename, "w")) != NULL) { 46941c6c543SBrian Somers fprintf(lockfile, "%d\n", (int)getpid()); 47041c6c543SBrian Somers fclose(lockfile); 471aefd026aSBrian Somers } else 472927145beSBrian Somers LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 473927145beSBrian Somers pid_filename, strerror(errno)); 47441c6c543SBrian Somers 47541c6c543SBrian Somers snprintf(if_filename, sizeof if_filename, "%s%s.if", 47641c6c543SBrian Somers _PATH_VARRUN, VarBaseDevice); 477aefd026aSBrian Somers (void)unlink(if_filename); 47841c6c543SBrian Somers 479aefd026aSBrian Somers if ((lockfile = fopen(if_filename, "w")) != NULL) { 48041c6c543SBrian Somers fprintf(lockfile, "tun%d\n", tunno); 48141c6c543SBrian Somers fclose(lockfile); 482aefd026aSBrian Somers } else 483927145beSBrian Somers LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 484927145beSBrian Somers if_filename, strerror(errno)); 485aefd026aSBrian Somers 486d656a4c5SBrian Somers VarTerm = 0; /* We know it's currently stdout */ 487d656a4c5SBrian Somers close(0); 488d656a4c5SBrian Somers close(2); 4890706ff38SBrian Somers 490af57ed9fSAtsushi Murai #ifdef DOTTYINIT 491d656a4c5SBrian Somers if (mode & (MODE_DIRECT|MODE_DEDICATED)) 492af57ed9fSAtsushi Murai #else 493d656a4c5SBrian Somers if (mode & MODE_DIRECT) 494af57ed9fSAtsushi Murai #endif 495368aee2bSBrian Somers TtyInit(1); 496d656a4c5SBrian Somers else { 497d656a4c5SBrian Somers setsid(); 498d656a4c5SBrian Somers close(1); 499d656a4c5SBrian Somers } 500af57ed9fSAtsushi Murai } else { 501368aee2bSBrian Somers TtyInit(0); 502c3899f8dSAtsushi Murai TtyCommandMode(1); 503af57ed9fSAtsushi Murai } 504927145beSBrian Somers LogPrintf(LogPHASE, "PPP Started.\n"); 505af57ed9fSAtsushi Murai 506af57ed9fSAtsushi Murai 507af57ed9fSAtsushi Murai do 508af57ed9fSAtsushi Murai DoLoop(); 509af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 510af57ed9fSAtsushi Murai 511af57ed9fSAtsushi Murai Cleanup(EX_DONE); 5124ef16f24SBrian Somers return 0; 513af57ed9fSAtsushi Murai } 514af57ed9fSAtsushi Murai 515af57ed9fSAtsushi Murai /* 5166d14e2a8SJordan K. Hubbard * Turn into packet mode, where we speak PPP. 517af57ed9fSAtsushi Murai */ 518af57ed9fSAtsushi Murai void 519af57ed9fSAtsushi Murai PacketMode() 520af57ed9fSAtsushi Murai { 521af57ed9fSAtsushi Murai if (RawModem(modem) < 0) { 522927145beSBrian Somers LogPrintf(LogWARN, "PacketMode: Not connected.\n"); 523af57ed9fSAtsushi Murai return; 524af57ed9fSAtsushi Murai } 525af57ed9fSAtsushi Murai 526af57ed9fSAtsushi Murai AsyncInit(); 527af57ed9fSAtsushi Murai VjInit(); 528af57ed9fSAtsushi Murai LcpInit(); 529af57ed9fSAtsushi Murai IpcpInit(); 530af57ed9fSAtsushi Murai CcpInit(); 531af57ed9fSAtsushi Murai LcpUp(); 532af57ed9fSAtsushi Murai 533af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 534af57ed9fSAtsushi Murai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 535c3899f8dSAtsushi Murai TtyCommandMode(1); 536927145beSBrian Somers if (VarTerm) { 537927145beSBrian Somers fprintf(VarTerm, "Packet mode.\n"); 538b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 539af57ed9fSAtsushi Murai } 540af57ed9fSAtsushi Murai } 541927145beSBrian Somers } 542af57ed9fSAtsushi Murai 543af57ed9fSAtsushi Murai static void 544af57ed9fSAtsushi Murai ShowHelp() 545af57ed9fSAtsushi Murai { 546030d3ce6SBrian Somers fprintf(stderr, "The following commands are available:\r\n"); 547030d3ce6SBrian Somers fprintf(stderr, " ~p\tEnter Packet mode\r\n"); 548030d3ce6SBrian Somers fprintf(stderr, " ~-\tDecrease log level\r\n"); 549030d3ce6SBrian Somers fprintf(stderr, " ~+\tIncrease log level\r\n"); 550030d3ce6SBrian Somers fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n"); 551030d3ce6SBrian Somers fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n"); 552030d3ce6SBrian Somers fprintf(stderr, " ~.\tTerminate program\r\n"); 553030d3ce6SBrian Somers fprintf(stderr, " ~?\tThis help\r\n"); 554af57ed9fSAtsushi Murai } 555af57ed9fSAtsushi Murai 556af57ed9fSAtsushi Murai static void 557af57ed9fSAtsushi Murai ReadTty() 558af57ed9fSAtsushi Murai { 559af57ed9fSAtsushi Murai int n; 560af57ed9fSAtsushi Murai char ch; 561af57ed9fSAtsushi Murai static int ttystate; 562927145beSBrian Somers FILE *oVarTerm; 563af57ed9fSAtsushi Murai #define MAXLINESIZE 200 564af57ed9fSAtsushi Murai char linebuff[MAXLINESIZE]; 565af57ed9fSAtsushi Murai 566927145beSBrian Somers LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n", 567927145beSBrian Somers TermMode, netfd, mode); 568af57ed9fSAtsushi Murai if (!TermMode) { 569af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff)-1); 57053c9f6c0SAtsushi Murai if (n > 0) { 571927145beSBrian Somers aft_cmd = 1; 572af57ed9fSAtsushi Murai DecodeCommand(linebuff, n, 1); 57353c9f6c0SAtsushi Murai } else { 574927145beSBrian Somers LogPrintf(LogPHASE, "client connection closed.\n"); 575e0d3e233SAndrey A. Chernov VarLocalAuth = LOCAL_NO_AUTH; 576af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 577927145beSBrian Somers oVarTerm = VarTerm; 578927145beSBrian Somers VarTerm = 0; 579927145beSBrian Somers if (oVarTerm && oVarTerm != stdout) 580927145beSBrian Somers fclose(oVarTerm); 581927145beSBrian Somers close(netfd); 582927145beSBrian Somers netfd = -1; 583af57ed9fSAtsushi Murai } 584af57ed9fSAtsushi Murai return; 585af57ed9fSAtsushi Murai } 586af57ed9fSAtsushi Murai 587af57ed9fSAtsushi Murai /* 588af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 589af57ed9fSAtsushi Murai */ 590927145beSBrian Somers n = read(fileno(VarTerm), &ch, 1); 591927145beSBrian Somers LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)", n); 592af57ed9fSAtsushi Murai 593af57ed9fSAtsushi Murai if (n > 0) { 594af57ed9fSAtsushi Murai switch (ttystate) { 595af57ed9fSAtsushi Murai case 0: 596af57ed9fSAtsushi Murai if (ch == '~') 597af57ed9fSAtsushi Murai ttystate++; 598af57ed9fSAtsushi Murai else 599af57ed9fSAtsushi Murai write(modem, &ch, n); 600af57ed9fSAtsushi Murai break; 601af57ed9fSAtsushi Murai case 1: 602af57ed9fSAtsushi Murai switch (ch) { 603af57ed9fSAtsushi Murai case '?': 604af57ed9fSAtsushi Murai ShowHelp(); 605af57ed9fSAtsushi Murai break; 606af57ed9fSAtsushi Murai case 'p': 607af57ed9fSAtsushi Murai /* 608af57ed9fSAtsushi Murai * XXX: Should check carrier. 609af57ed9fSAtsushi Murai */ 610af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 611af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 612af57ed9fSAtsushi Murai PacketMode(); 613af57ed9fSAtsushi Murai } 614af57ed9fSAtsushi Murai break; 615af57ed9fSAtsushi Murai case '.': 616af57ed9fSAtsushi Murai TermMode = 1; 617927145beSBrian Somers aft_cmd = 1; 618c3899f8dSAtsushi Murai TtyCommandMode(1); 619af57ed9fSAtsushi Murai break; 620927145beSBrian Somers case 't': 621927145beSBrian Somers if (LogIsKept(LogDEBUG)) { 622927145beSBrian Somers ShowTimers(); 623927145beSBrian Somers break; 624927145beSBrian Somers } 625927145beSBrian Somers case 'm': 626927145beSBrian Somers if (LogIsKept(LogDEBUG)) { 627927145beSBrian Somers ShowMemMap(); 628927145beSBrian Somers break; 629927145beSBrian Somers } 630af57ed9fSAtsushi Murai default: 631af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 632927145beSBrian Somers LogPrintf(LogERROR, "error writing to modem.\n"); 633af57ed9fSAtsushi Murai break; 634af57ed9fSAtsushi Murai } 635af57ed9fSAtsushi Murai ttystate = 0; 636af57ed9fSAtsushi Murai break; 637af57ed9fSAtsushi Murai } 638af57ed9fSAtsushi Murai } 639af57ed9fSAtsushi Murai } 640af57ed9fSAtsushi Murai 641af57ed9fSAtsushi Murai 642af57ed9fSAtsushi Murai /* 643af57ed9fSAtsushi Murai * Here, we'll try to detect HDLC frame 644af57ed9fSAtsushi Murai */ 645af57ed9fSAtsushi Murai 646af57ed9fSAtsushi Murai static char *FrameHeaders[] = { 64753c9f6c0SAtsushi Murai "\176\377\003\300\041", 64853c9f6c0SAtsushi Murai "\176\377\175\043\300\041", 64953c9f6c0SAtsushi Murai "\176\177\175\043\100\041", 65053c9f6c0SAtsushi Murai "\176\175\337\175\043\300\041", 65153c9f6c0SAtsushi Murai "\176\175\137\175\043\100\041", 652af57ed9fSAtsushi Murai NULL, 653af57ed9fSAtsushi Murai }; 654af57ed9fSAtsushi Murai 655af57ed9fSAtsushi Murai u_char * 656af57ed9fSAtsushi Murai HdlcDetect(cp, n) 657af57ed9fSAtsushi Murai u_char *cp; 658af57ed9fSAtsushi Murai int n; 659af57ed9fSAtsushi Murai { 66053c9f6c0SAtsushi Murai char *ptr, *fp, **hp; 661af57ed9fSAtsushi Murai 662af57ed9fSAtsushi Murai cp[n] = '\0'; /* be sure to null terminated */ 663af57ed9fSAtsushi Murai ptr = NULL; 664af57ed9fSAtsushi Murai for (hp = FrameHeaders; *hp; hp++) { 66553c9f6c0SAtsushi Murai fp = *hp; 66653c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 66753c9f6c0SAtsushi Murai fp++; 668ed6a16c1SPoul-Henning Kamp ptr = strstr((char *)cp, fp); 669ed6a16c1SPoul-Henning Kamp if (ptr) 670af57ed9fSAtsushi Murai break; 671af57ed9fSAtsushi Murai } 672af57ed9fSAtsushi Murai return((u_char *)ptr); 673af57ed9fSAtsushi Murai } 674af57ed9fSAtsushi Murai 675af57ed9fSAtsushi Murai static struct pppTimer RedialTimer; 676af57ed9fSAtsushi Murai 677af57ed9fSAtsushi Murai static void 678af57ed9fSAtsushi Murai RedialTimeout() 679af57ed9fSAtsushi Murai { 680af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 681927145beSBrian Somers LogPrintf(LogPHASE, "Redialing timer expired.\n"); 682af57ed9fSAtsushi Murai } 683af57ed9fSAtsushi Murai 684af57ed9fSAtsushi Murai static void 68543ea9d19SBrian Somers StartRedialTimer(Timeout) 68643ea9d19SBrian Somers int Timeout; 687af57ed9fSAtsushi Murai { 688af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 689a9c6b5dfSAtsushi Murai 69043ea9d19SBrian Somers if (Timeout) { 691af57ed9fSAtsushi Murai RedialTimer.state = TIMER_STOPPED; 692a9c6b5dfSAtsushi Murai 69343ea9d19SBrian Somers if (Timeout > 0) 69443ea9d19SBrian Somers RedialTimer.load = Timeout * SECTICKS; 695a9c6b5dfSAtsushi Murai else 696a9c6b5dfSAtsushi Murai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 697a9c6b5dfSAtsushi Murai 698927145beSBrian Somers LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n", 69943ea9d19SBrian Somers RedialTimer.load / SECTICKS); 70043ea9d19SBrian Somers 701af57ed9fSAtsushi Murai RedialTimer.func = RedialTimeout; 702af57ed9fSAtsushi Murai StartTimer(&RedialTimer); 703af57ed9fSAtsushi Murai } 704a9c6b5dfSAtsushi Murai } 705af57ed9fSAtsushi Murai 706af57ed9fSAtsushi Murai 707af57ed9fSAtsushi Murai static void 708af57ed9fSAtsushi Murai DoLoop() 709af57ed9fSAtsushi Murai { 710af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 711780700e5SAndrey A. Chernov int pri, i, n, wfd, nfds; 712af57ed9fSAtsushi Murai struct sockaddr_in hisaddr; 713af57ed9fSAtsushi Murai struct timeval timeout, *tp; 714af57ed9fSAtsushi Murai int ssize = sizeof(hisaddr); 715af57ed9fSAtsushi Murai u_char *cp; 716af57ed9fSAtsushi Murai u_char rbuff[MAX_MRU]; 71784b8a6ebSAtsushi Murai int dial_up; 718a9c6b5dfSAtsushi Murai int tries; 71960e218e4SAtsushi Murai int qlen; 720368aee2bSBrian Somers int res; 721c3899f8dSAtsushi Murai pid_t pgroup; 722c3899f8dSAtsushi Murai 723c3899f8dSAtsushi Murai pgroup = getpgrp(); 724af57ed9fSAtsushi Murai 7256efd9292SBrian Somers if (mode & MODE_DIRECT) { 7260706ff38SBrian Somers LogPrintf(LogDEBUG, "Opening modem\n"); 727af57ed9fSAtsushi Murai modem = OpenModem(mode); 728927145beSBrian Somers LogPrintf(LogPHASE, "Packet mode enabled\n"); 729af57ed9fSAtsushi Murai PacketMode(); 730af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 731780700e5SAndrey A. Chernov if (modem < 0) 732af57ed9fSAtsushi Murai modem = OpenModem(mode); 733af57ed9fSAtsushi Murai } 734af57ed9fSAtsushi Murai 735927145beSBrian Somers fflush(VarTerm); 736af57ed9fSAtsushi Murai 73784b8a6ebSAtsushi Murai timeout.tv_sec = 0; 738af57ed9fSAtsushi Murai timeout.tv_usec = 0; 73925aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 740af57ed9fSAtsushi Murai 7416e4959f0SBrian Somers if (mode & MODE_BACKGROUND) 7426e4959f0SBrian Somers dial_up = TRUE; /* Bring the line up */ 7436e4959f0SBrian Somers else 74484b8a6ebSAtsushi Murai dial_up = FALSE; /* XXXX */ 745a9c6b5dfSAtsushi Murai tries = 0; 746af57ed9fSAtsushi Murai for (;;) { 747780700e5SAndrey A. Chernov nfds = 0; 748af57ed9fSAtsushi Murai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 74984b8a6ebSAtsushi Murai 75084b8a6ebSAtsushi Murai /* 751680026d6SNate Williams * If the link is down and we're in DDIAL mode, bring it back 752680026d6SNate Williams * up. 753680026d6SNate Williams */ 754680026d6SNate Williams if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 755680026d6SNate Williams dial_up = TRUE; 756680026d6SNate Williams 757680026d6SNate Williams /* 75807030d97SBrian Somers * If we lost carrier and want to re-establish the connection 75907030d97SBrian Somers * due to the "set reconnect" value, we'd better bring the line 7606efd9292SBrian Somers * back up. 76107030d97SBrian Somers */ 7626efd9292SBrian Somers if (LcpFsm.state <= ST_CLOSED) { 76325aa96acSBrian Somers if (dial_up != TRUE && reconnectState == RECON_TRUE) { 7646efd9292SBrian Somers if (++reconnectCount <= VarReconnectTries) { 765927145beSBrian Somers LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n", 7666efd9292SBrian Somers reconnectCount, VarReconnectTries); 76707030d97SBrian Somers StartRedialTimer(VarReconnectTimer); 76807030d97SBrian Somers dial_up = TRUE; 769298091daSBrian Somers } else { 7706efd9292SBrian Somers if (VarReconnectTries) 771927145beSBrian Somers LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n", 772298091daSBrian Somers VarReconnectTries); 7736efd9292SBrian Somers reconnectCount = 0; 7746efd9292SBrian Somers if (mode & MODE_BACKGROUND) 7756efd9292SBrian Somers Cleanup(EX_DEAD); 7766efd9292SBrian Somers } 77725aa96acSBrian Somers reconnectState = RECON_ENVOKED; 7786efd9292SBrian Somers } 77907030d97SBrian Somers } 78007030d97SBrian Somers 78107030d97SBrian Somers /* 78284b8a6ebSAtsushi Murai * If Ip packet for output is enqueued and require dial up, 78384b8a6ebSAtsushi Murai * Just do it! 78484b8a6ebSAtsushi Murai */ 78507030d97SBrian Somers if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { 786927145beSBrian Somers LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem); 78784b8a6ebSAtsushi Murai modem = OpenModem(mode); 78884b8a6ebSAtsushi Murai if (modem < 0) { 7890706ff38SBrian Somers tries++; 790712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries) 7910706ff38SBrian Somers LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n", 7920706ff38SBrian Somers tries, VarDialTries); 7930706ff38SBrian Somers else 7940706ff38SBrian Somers LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries); 7950706ff38SBrian Somers 796712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) { 7970706ff38SBrian Somers if (mode & MODE_BACKGROUND) 7980706ff38SBrian Somers Cleanup(EX_DIAL); /* Can't get the modem */ 7990706ff38SBrian Somers dial_up = FALSE; 8000706ff38SBrian Somers reconnectState = RECON_UNKNOWN; 8010706ff38SBrian Somers reconnectCount = 0; 8020706ff38SBrian Somers tries = 0; 8030706ff38SBrian Somers } else 80443ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 80584b8a6ebSAtsushi Murai } else { 806c0139fb2SBrian Somers tries++; /* Tries are per number, not per list of numbers. */ 807712ae387SBrian Somers if (!(mode & MODE_DDIAL) && VarDialTries) 808712ae387SBrian Somers LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries); 809c0139fb2SBrian Somers else 810927145beSBrian Somers LogPrintf(LogCHAT, "Dial attempt %u\n", tries); 811712ae387SBrian Somers 812368aee2bSBrian Somers if ((res = DialModem()) == EX_DONE) { 81384b8a6ebSAtsushi Murai sleep(1); /* little pause to allow peer starts */ 81484b8a6ebSAtsushi Murai ModemTimeout(); 81584b8a6ebSAtsushi Murai PacketMode(); 81684b8a6ebSAtsushi Murai dial_up = FALSE; 81725aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 818a9c6b5dfSAtsushi Murai tries = 0; 81984b8a6ebSAtsushi Murai } else { 82084b8a6ebSAtsushi Murai CloseModem(); 8214ed9958fSBrian Somers if (mode & MODE_BACKGROUND) { 822368aee2bSBrian Somers if (VarNextPhone == NULL || res == EX_SIG) 8234ed9958fSBrian Somers Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 8244ed9958fSBrian Somers else 82543ea9d19SBrian Somers /* Try all numbers in background mode */ 82643ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 827368aee2bSBrian Somers } else if (!(mode & MODE_DDIAL) && 828368aee2bSBrian Somers ((VarDialTries && tries >= VarDialTries) || 829368aee2bSBrian Somers res == EX_SIG)) { 830c0139fb2SBrian Somers /* I give up ! Can't get through :( */ 83143ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 832a9c6b5dfSAtsushi Murai dial_up = FALSE; 83325aa96acSBrian Somers reconnectState = RECON_UNKNOWN; 83425aa96acSBrian Somers reconnectCount = 0; 835a9c6b5dfSAtsushi Murai tries = 0; 836c0139fb2SBrian Somers } else if (VarNextPhone == NULL) 837c0139fb2SBrian Somers /* Dial failed. Keep quite during redial wait period. */ 83843ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 839c0139fb2SBrian Somers else 84043ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 84184b8a6ebSAtsushi Murai } 84284b8a6ebSAtsushi Murai } 84384b8a6ebSAtsushi Murai } 84460e218e4SAtsushi Murai qlen = ModemQlen(); 84576bd0c0aSDoug Rabson 84676bd0c0aSDoug Rabson if (qlen == 0) { 84776bd0c0aSDoug Rabson IpStartOutput(); 84876bd0c0aSDoug Rabson qlen = ModemQlen(); 84976bd0c0aSDoug Rabson } 85076bd0c0aSDoug Rabson 851780700e5SAndrey A. Chernov if (modem >= 0) { 852780700e5SAndrey A. Chernov if (modem + 1 > nfds) 853780700e5SAndrey A. Chernov nfds = modem + 1; 85484b8a6ebSAtsushi Murai FD_SET(modem, &rfds); 85584b8a6ebSAtsushi Murai FD_SET(modem, &efds); 85660e218e4SAtsushi Murai if (qlen > 0) { 85784b8a6ebSAtsushi Murai FD_SET(modem, &wfds); 85884b8a6ebSAtsushi Murai } 85984b8a6ebSAtsushi Murai } 860780700e5SAndrey A. Chernov if (server >= 0) { 861780700e5SAndrey A. Chernov if (server + 1 > nfds) 862780700e5SAndrey A. Chernov nfds = server + 1; 863780700e5SAndrey A. Chernov FD_SET(server, &rfds); 864780700e5SAndrey A. Chernov } 865af57ed9fSAtsushi Murai 866af57ed9fSAtsushi Murai /* *** IMPORTANT *** 867af57ed9fSAtsushi Murai * 868af57ed9fSAtsushi Murai * CPU is serviced every TICKUNIT micro seconds. 869af57ed9fSAtsushi Murai * This value must be chosen with great care. If this values is 870af57ed9fSAtsushi Murai * too big, it results loss of characters from modem and poor responce. 871af57ed9fSAtsushi Murai * If this values is too small, ppp process eats many CPU time. 872af57ed9fSAtsushi Murai */ 87353c9f6c0SAtsushi Murai #ifndef SIGALRM 874af57ed9fSAtsushi Murai usleep(TICKUNIT); 875af57ed9fSAtsushi Murai TimerService(); 876f5ff0f7cSBrian Somers #else 877f5ff0f7cSBrian Somers handle_signals(); 87853c9f6c0SAtsushi Murai #endif 87968d2b4d6SBruce Evans 88068d2b4d6SBruce Evans /* If there are aren't many packets queued, look for some more. */ 881780700e5SAndrey A. Chernov if (qlen < 20 && tun_in >= 0) { 882780700e5SAndrey A. Chernov if (tun_in + 1 > nfds) 883780700e5SAndrey A. Chernov nfds = tun_in + 1; 88484b8a6ebSAtsushi Murai FD_SET(tun_in, &rfds); 885780700e5SAndrey A. Chernov } 88668d2b4d6SBruce Evans 887780700e5SAndrey A. Chernov if (netfd >= 0) { 888780700e5SAndrey A. Chernov if (netfd + 1 > nfds) 889780700e5SAndrey A. Chernov nfds = netfd + 1; 890af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 891af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 892af57ed9fSAtsushi Murai } 89384b8a6ebSAtsushi Murai 89453c9f6c0SAtsushi Murai #ifndef SIGALRM 895af57ed9fSAtsushi Murai /* 89684b8a6ebSAtsushi Murai * Normally, select() will not block because modem is writable. 89784b8a6ebSAtsushi Murai * In AUTO mode, select will block until we find packet from tun 898af57ed9fSAtsushi Murai */ 899af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 900780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 90153c9f6c0SAtsushi Murai #else 90284b8a6ebSAtsushi Murai /* 90384b8a6ebSAtsushi Murai * When SIGALRM timer is running, a select function will be 90484b8a6ebSAtsushi Murai * return -1 and EINTR after a Time Service signal hundler 905a9c6b5dfSAtsushi Murai * is done. If the redial timer is not running and we are 906a9c6b5dfSAtsushi Murai * trying to dial, poll with a 0 value timer. 90784b8a6ebSAtsushi Murai */ 908a9c6b5dfSAtsushi Murai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 909780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 91053c9f6c0SAtsushi Murai #endif 9116b0b88d8SBrian Somers 912af57ed9fSAtsushi Murai if ( i == 0 ) { 913af57ed9fSAtsushi Murai continue; 914af57ed9fSAtsushi Murai } 91553c9f6c0SAtsushi Murai 916534fe541SBrian Somers if ( i < 0 ) { 917534fe541SBrian Somers if ( errno == EINTR ) { 918f5ff0f7cSBrian Somers handle_signals(); 919f5ff0f7cSBrian Somers continue; 92084b8a6ebSAtsushi Murai } 921927145beSBrian Somers LogPrintf(LogERROR, "select: %s", strerror(errno)); 922af57ed9fSAtsushi Murai break; 923af57ed9fSAtsushi Murai } 92484b8a6ebSAtsushi Murai 925780700e5SAndrey A. Chernov if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 926927145beSBrian Somers LogPrintf(LogALERT, "Exception detected.\n"); 927af57ed9fSAtsushi Murai break; 928af57ed9fSAtsushi Murai } 929af57ed9fSAtsushi Murai 930780700e5SAndrey A. Chernov if (server >= 0 && FD_ISSET(server, &rfds)) { 931927145beSBrian Somers LogPrintf(LogPHASE, "connected to client.\n"); 932af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 933e0d3e233SAndrey A. Chernov if (wfd < 0) { 934927145beSBrian Somers LogPrintf(LogERROR, "accept: %s", strerror(errno)); 935e0d3e233SAndrey A. Chernov continue; 936e0d3e233SAndrey A. Chernov } 937780700e5SAndrey A. Chernov if (netfd >= 0) { 938af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 939af57ed9fSAtsushi Murai close(wfd); 940af57ed9fSAtsushi Murai continue; 941af57ed9fSAtsushi Murai } else 942af57ed9fSAtsushi Murai netfd = wfd; 943927145beSBrian Somers VarTerm = fdopen(netfd, "a+"); 944af57ed9fSAtsushi Murai mode |= MODE_INTER; 945af57ed9fSAtsushi Murai Greetings(); 94641db6564SAtsushi Murai switch ( LocalAuthInit() ) { 94741db6564SAtsushi Murai case NOT_FOUND: 948927145beSBrian Somers if (VarTerm) { 949927145beSBrian Somers fprintf(VarTerm,LAUTH_M1); 950927145beSBrian Somers fprintf(VarTerm,LAUTH_M2); 951927145beSBrian Somers fflush(VarTerm); 952927145beSBrian Somers } 95341db6564SAtsushi Murai /* Fall down */ 95441db6564SAtsushi Murai case VALID: 95541db6564SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 95641db6564SAtsushi Murai break; 95741db6564SAtsushi Murai default: 95841db6564SAtsushi Murai break; 95941db6564SAtsushi Murai } 960af57ed9fSAtsushi Murai (void) IsInteractive(); 961274e766cSBrian Somers Prompt(); 962af57ed9fSAtsushi Murai } 963af57ed9fSAtsushi Murai 964780700e5SAndrey A. Chernov if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 965f1884650SAtsushi Murai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 966af57ed9fSAtsushi Murai /* something to read from tty */ 967af57ed9fSAtsushi Murai ReadTty(); 968af57ed9fSAtsushi Murai } 969780700e5SAndrey A. Chernov if (modem >= 0) { 970af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 971af57ed9fSAtsushi Murai ModemStartOutput(modem); 972af57ed9fSAtsushi Murai } 973af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 97453c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 97553c9f6c0SAtsushi Murai usleep(10000); 976af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 977af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 978af57ed9fSAtsushi Murai DownConnection(); 979af57ed9fSAtsushi Murai } else 980927145beSBrian Somers LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n); 981af57ed9fSAtsushi Murai 982af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 983af57ed9fSAtsushi Murai /* 984af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 985af57ed9fSAtsushi Murai */ 986af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 987af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 988af57ed9fSAtsushi Murai if (cp) { 989af57ed9fSAtsushi Murai /* 990af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 991af57ed9fSAtsushi Murai */ 992af57ed9fSAtsushi Murai if (cp != rbuff) { 993927145beSBrian Somers write(modem, rbuff, cp - rbuff); 994927145beSBrian Somers write(modem, "\r\n", 2); 995af57ed9fSAtsushi Murai } 996af57ed9fSAtsushi Murai PacketMode(); 997af57ed9fSAtsushi Murai } else 998927145beSBrian Somers write(fileno(VarTerm), rbuff, n); 999af57ed9fSAtsushi Murai } 1000af57ed9fSAtsushi Murai } else { 1001af57ed9fSAtsushi Murai if (n > 0) 1002af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 1003af57ed9fSAtsushi Murai } 1004af57ed9fSAtsushi Murai } 1005af57ed9fSAtsushi Murai } 100684b8a6ebSAtsushi Murai 1007780700e5SAndrey A. Chernov if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 1008af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 1009af57ed9fSAtsushi Murai if (n < 0) { 1010927145beSBrian Somers LogPrintf(LogERROR, "read from tun: %s", strerror(errno)); 1011af57ed9fSAtsushi Murai continue; 1012af57ed9fSAtsushi Murai } 1013af57ed9fSAtsushi Murai /* 1014af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 1015af57ed9fSAtsushi Murai * device until IPCP is opened. 1016af57ed9fSAtsushi Murai */ 1017af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 101884b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_DIAL); 1019af57ed9fSAtsushi Murai if (pri >= 0) { 1020a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10216ed9fb2fSBrian Somers VarPacketAliasOut(rbuff, sizeof rbuff); 1022a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 1023a9f484e5SJordan K. Hubbard } 1024af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 102584b8a6ebSAtsushi Murai dial_up = TRUE; /* XXX */ 1026af57ed9fSAtsushi Murai } 1027af57ed9fSAtsushi Murai continue; 1028af57ed9fSAtsushi Murai } 102984b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_OUT); 1030a9f484e5SJordan K. Hubbard if (pri >= 0) { 1031a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10326ed9fb2fSBrian Somers VarPacketAliasOut(rbuff, sizeof rbuff); 1033a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 1034a9f484e5SJordan K. Hubbard } 1035af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 1036af57ed9fSAtsushi Murai } 1037af57ed9fSAtsushi Murai } 1038a9f484e5SJordan K. Hubbard } 1039927145beSBrian Somers LogPrintf(LogDEBUG, "Job (DoLoop) done.\n"); 1040af57ed9fSAtsushi Murai } 1041