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 * 20aefd026aSBrian Somers * $Id: main.c,v 1.48 1997/05/10 03:39:53 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" 46af57ed9fSAtsushi Murai #include "vars.h" 4753c9f6c0SAtsushi Murai #include "auth.h" 4884b8a6ebSAtsushi Murai #include "filter.h" 49ed6a16c1SPoul-Henning Kamp #include "systems.h" 50ed6a16c1SPoul-Henning Kamp #include "ip.h" 51a9f484e5SJordan K. Hubbard #include "alias.h" 52f5ff0f7cSBrian Somers #include "sig.h" 5353c9f6c0SAtsushi Murai 5441db6564SAtsushi Murai #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 55bea0b497SSatoshi Asami #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n" 5641db6564SAtsushi Murai 5753c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 5853c9f6c0SAtsushi Murai #ifdef O_NDELAY 5953c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 6053c9f6c0SAtsushi Murai #endif 6153c9f6c0SAtsushi Murai #endif 62af57ed9fSAtsushi Murai 63af57ed9fSAtsushi Murai extern void VjInit(), AsyncInit(); 64274e766cSBrian Somers extern void AsyncInput(); 65af57ed9fSAtsushi Murai extern int SelectSystem(); 66af57ed9fSAtsushi Murai 67af57ed9fSAtsushi Murai extern void DecodeCommand(), Prompt(); 68b0cdb3ceSJordan K. Hubbard extern int aft_cmd; 69af57ed9fSAtsushi Murai extern int IsInteractive(); 70af57ed9fSAtsushi Murai static void DoLoop(void); 71c3899f8dSAtsushi Murai static void TerminalStop(); 72af57ed9fSAtsushi Murai 73af57ed9fSAtsushi Murai static struct termios oldtio; /* Original tty mode */ 74af57ed9fSAtsushi Murai static struct termios comtio; /* Command level tty mode */ 751dff3fc5SAndrey A. Chernov int TermMode; 767b64106aSPoul-Henning Kamp static int server; 776d14e2a8SJordan K. Hubbard static pid_t BGPid = 0; 78af57ed9fSAtsushi Murai struct sockaddr_in ifsin; 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 84af57ed9fSAtsushi Murai TtyInit() 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; 99af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 100af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 101af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 102af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 10353c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 104af57ed9fSAtsushi Murai comtio = newtio; 105af57ed9fSAtsushi Murai } 106af57ed9fSAtsushi Murai 107af57ed9fSAtsushi Murai /* 108af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 109af57ed9fSAtsushi Murai */ 110c3899f8dSAtsushi Murai void 111c3899f8dSAtsushi Murai TtyCommandMode(prompt) 112c3899f8dSAtsushi Murai int prompt; 113af57ed9fSAtsushi Murai { 114af57ed9fSAtsushi Murai struct termios newtio; 115af57ed9fSAtsushi Murai int stat; 116af57ed9fSAtsushi Murai 117af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 118af57ed9fSAtsushi Murai return; 11953c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 120c3899f8dSAtsushi Murai newtio.c_lflag |= (ECHO|ISIG|ICANON); 121af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 122af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 12353c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 124af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 125274e766cSBrian Somers if (stat > 0) { 126af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 127274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 128274e766cSBrian Somers } 129af57ed9fSAtsushi Murai TermMode = 0; 130274e766cSBrian Somers if(prompt) Prompt(); 131af57ed9fSAtsushi Murai } 132af57ed9fSAtsushi Murai 133af57ed9fSAtsushi Murai /* 134af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 135af57ed9fSAtsushi Murai */ 136af57ed9fSAtsushi Murai void 137af57ed9fSAtsushi Murai TtyTermMode() 138af57ed9fSAtsushi Murai { 139af57ed9fSAtsushi Murai int stat; 140af57ed9fSAtsushi Murai 14153c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 142af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 143274e766cSBrian Somers if (stat > 0) { 144af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 145274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 146274e766cSBrian Somers } 147af57ed9fSAtsushi Murai TermMode = 1; 148af57ed9fSAtsushi Murai } 149af57ed9fSAtsushi Murai 150af57ed9fSAtsushi Murai void 151c3899f8dSAtsushi Murai TtyOldMode() 152c3899f8dSAtsushi Murai { 153c3899f8dSAtsushi Murai int stat; 154c3899f8dSAtsushi Murai 155c3899f8dSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 156274e766cSBrian Somers if (stat > 0) { 157c3899f8dSAtsushi Murai stat &= ~O_NONBLOCK; 158274e766cSBrian Somers (void)fcntl(0, F_SETFL, stat); 159274e766cSBrian Somers } 160c3899f8dSAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 161c3899f8dSAtsushi Murai } 162c3899f8dSAtsushi Murai 163c3899f8dSAtsushi Murai void 164af57ed9fSAtsushi Murai Cleanup(excode) 165af57ed9fSAtsushi Murai int excode; 166af57ed9fSAtsushi Murai { 167af57ed9fSAtsushi Murai 168af57ed9fSAtsushi Murai OsLinkdown(); 169af57ed9fSAtsushi Murai OsCloseLink(1); 170af57ed9fSAtsushi Murai sleep(1); 171aefd026aSBrian Somers if (mode & (MODE_AUTO | MODE_BACKGROUND)) 1726e4959f0SBrian Somers DeleteIfRoutes(1); 173aefd026aSBrian Somers (void)unlink(pid_filename); 174aefd026aSBrian Somers (void)unlink(if_filename); 175af57ed9fSAtsushi Murai OsInterfaceDown(1); 1766e4959f0SBrian Somers if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 1776e4959f0SBrian Somers char c = EX_ERRDEAD; 1786e4959f0SBrian Somers if (write(BGFiledes[1],&c,1) == 1) 1796e4959f0SBrian Somers LogPrintf(LOG_PHASE_BIT,"Parent notified of failure.\n"); 1806e4959f0SBrian Somers else 1816e4959f0SBrian Somers LogPrintf(LOG_PHASE_BIT,"Failed to notify parent of failure.\n"); 1826e4959f0SBrian Somers close(BGFiledes[1]); 1836e4959f0SBrian Somers } 1844ed9958fSBrian Somers LogPrintf(LOG_PHASE_BIT, "PPP Terminated %d.\n",excode); 185af57ed9fSAtsushi Murai LogClose(); 186780700e5SAndrey A. Chernov if (server >= 0) { 187af57ed9fSAtsushi Murai close(server); 188780700e5SAndrey A. Chernov server = -1; 189780700e5SAndrey A. Chernov } 190aefd026aSBrian Somers 191c3899f8dSAtsushi Murai TtyOldMode(); 192af57ed9fSAtsushi Murai 193af57ed9fSAtsushi Murai exit(excode); 194af57ed9fSAtsushi Murai } 195af57ed9fSAtsushi Murai 196af57ed9fSAtsushi Murai static void 1977a8ef19eSAndrey A. Chernov Hangup(signo) 1987a8ef19eSAndrey A. Chernov int signo; 199af57ed9fSAtsushi Murai { 200af83607cSAndrey A. Chernov if (signo == SIGSEGV) { 201af83607cSAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo); 202af83607cSAndrey A. Chernov LogClose(); 203af83607cSAndrey A. Chernov abort(); 204af83607cSAndrey A. Chernov } 2056d14e2a8SJordan K. Hubbard if (BGPid) { 206c6c740beSBrian Somers kill (BGPid, SIGTERM); 2076d14e2a8SJordan K. Hubbard exit (EX_HANGUP); 2086d14e2a8SJordan K. Hubbard } 2096d14e2a8SJordan K. Hubbard else { 2109c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo); 211af57ed9fSAtsushi Murai Cleanup(EX_HANGUP); 212af57ed9fSAtsushi Murai } 2136d14e2a8SJordan K. Hubbard } 214af57ed9fSAtsushi Murai 215af57ed9fSAtsushi Murai static void 2167a8ef19eSAndrey A. Chernov CloseSession(signo) 2177a8ef19eSAndrey A. Chernov int signo; 218af57ed9fSAtsushi Murai { 2196d14e2a8SJordan K. Hubbard if (BGPid) { 2206d14e2a8SJordan K. Hubbard kill (BGPid, SIGINT); 2216d14e2a8SJordan K. Hubbard exit (EX_TERM); 2226d14e2a8SJordan K. Hubbard } 2236d14e2a8SJordan K. Hubbard else { 2249c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo); 225af57ed9fSAtsushi Murai LcpClose(); 226af57ed9fSAtsushi Murai Cleanup(EX_TERM); 227af57ed9fSAtsushi Murai } 2286d14e2a8SJordan K. Hubbard } 229c3899f8dSAtsushi Murai 230c3899f8dSAtsushi Murai static void 231c3899f8dSAtsushi Murai TerminalCont() 232c3899f8dSAtsushi Murai { 233f5ff0f7cSBrian Somers pending_signal(SIGCONT, SIG_DFL); 234f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 235c3899f8dSAtsushi Murai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 236c3899f8dSAtsushi Murai } 237c3899f8dSAtsushi Murai 238c3899f8dSAtsushi Murai static void 239c3899f8dSAtsushi Murai TerminalStop(signo) 240c3899f8dSAtsushi Murai int signo; 241c3899f8dSAtsushi Murai { 242f5ff0f7cSBrian Somers pending_signal(SIGCONT, TerminalCont); 243c3899f8dSAtsushi Murai TtyOldMode(); 244f5ff0f7cSBrian Somers pending_signal(SIGTSTP, SIG_DFL); 245c3899f8dSAtsushi Murai kill(getpid(), signo); 246c3899f8dSAtsushi Murai } 247c3899f8dSAtsushi Murai 248c3899f8dSAtsushi Murai 249af57ed9fSAtsushi Murai void 250af57ed9fSAtsushi Murai Usage() 251af57ed9fSAtsushi Murai { 252680026d6SNate Williams fprintf(stderr, 2536d14e2a8SJordan K. Hubbard "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 254af57ed9fSAtsushi Murai exit(EX_START); 255af57ed9fSAtsushi Murai } 256af57ed9fSAtsushi Murai 257af57ed9fSAtsushi Murai void 258af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 259af57ed9fSAtsushi Murai { 260af57ed9fSAtsushi Murai int optc; 261af57ed9fSAtsushi Murai char *cp; 262af57ed9fSAtsushi Murai 263af57ed9fSAtsushi Murai optc = 0; 264af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 265af57ed9fSAtsushi Murai cp = *argv + 1; 266af57ed9fSAtsushi Murai if (strcmp(cp, "auto") == 0) 267af57ed9fSAtsushi Murai mode |= MODE_AUTO; 2686d14e2a8SJordan K. Hubbard else if (strcmp(cp, "background") == 0) 2696d14e2a8SJordan K. Hubbard mode |= MODE_BACKGROUND; 270af57ed9fSAtsushi Murai else if (strcmp(cp, "direct") == 0) 271af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 272af57ed9fSAtsushi Murai else if (strcmp(cp, "dedicated") == 0) 273af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 274680026d6SNate Williams else if (strcmp(cp, "ddial") == 0) 275680026d6SNate Williams mode |= MODE_DDIAL|MODE_AUTO; 276a9f484e5SJordan K. Hubbard else if (strcmp(cp, "alias") == 0) { 277a9f484e5SJordan K. Hubbard mode |= MODE_ALIAS; 278a9f484e5SJordan K. Hubbard optc--; /* this option isn't exclusive */ 279a9f484e5SJordan K. Hubbard } 280af57ed9fSAtsushi Murai else 281af57ed9fSAtsushi Murai Usage(); 282af57ed9fSAtsushi Murai optc++; 283af57ed9fSAtsushi Murai argv++; argc--; 284af57ed9fSAtsushi Murai } 285af57ed9fSAtsushi Murai if (argc > 1) { 286af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 287af57ed9fSAtsushi Murai exit(EX_START); 288af57ed9fSAtsushi Murai } 289af57ed9fSAtsushi Murai if (argc == 1) dstsystem = *argv; 290af57ed9fSAtsushi Murai 291af57ed9fSAtsushi Murai if (optc > 1) { 292af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 293af57ed9fSAtsushi Murai exit(EX_START); 294af57ed9fSAtsushi Murai } 295af57ed9fSAtsushi Murai } 296af57ed9fSAtsushi Murai 297af57ed9fSAtsushi Murai static void 298af57ed9fSAtsushi Murai Greetings() 299af57ed9fSAtsushi Murai { 300af57ed9fSAtsushi Murai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 301af57ed9fSAtsushi Murai fflush(stdout); 302af57ed9fSAtsushi Murai } 303af57ed9fSAtsushi Murai 304af57ed9fSAtsushi Murai void 305af57ed9fSAtsushi Murai main(argc, argv) 306af57ed9fSAtsushi Murai int argc; 307af57ed9fSAtsushi Murai char **argv; 308af57ed9fSAtsushi Murai { 309aefd026aSBrian Somers FILE *lockfile; 310af57ed9fSAtsushi Murai argc--; argv++; 311af57ed9fSAtsushi Murai 312af57ed9fSAtsushi Murai mode = MODE_INTER; /* default operation is interactive mode */ 313780700e5SAndrey A. Chernov netfd = server = modem = tun_in = -1; 314af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 315af57ed9fSAtsushi Murai Greetings(); 316af57ed9fSAtsushi Murai GetUid(); 317af57ed9fSAtsushi Murai IpcpDefAddress(); 318a9f484e5SJordan K. Hubbard InitAlias(); 319af57ed9fSAtsushi Murai 320af57ed9fSAtsushi Murai if (SelectSystem("default", CONFFILE) < 0) { 321af57ed9fSAtsushi Murai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 322af57ed9fSAtsushi Murai } 323af57ed9fSAtsushi Murai 32453c9f6c0SAtsushi Murai switch ( LocalAuthInit() ) { 32553c9f6c0SAtsushi Murai case NOT_FOUND: 32641db6564SAtsushi Murai fprintf(stderr,LAUTH_M1); 32741db6564SAtsushi Murai fprintf(stderr,LAUTH_M2); 32841db6564SAtsushi Murai fflush (stderr); 32941db6564SAtsushi Murai /* Fall down */ 33041db6564SAtsushi Murai case VALID: 33153c9f6c0SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 33253c9f6c0SAtsushi Murai break; 33353c9f6c0SAtsushi Murai default: 33453c9f6c0SAtsushi Murai break; 33553c9f6c0SAtsushi Murai } 33653c9f6c0SAtsushi Murai 337af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 338af57ed9fSAtsushi Murai perror("open_tun"); 339af57ed9fSAtsushi Murai exit(EX_START); 340af57ed9fSAtsushi Murai } 341af57ed9fSAtsushi Murai 3426d14e2a8SJordan K. Hubbard if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND)) 343af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 344af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 345af57ed9fSAtsushi Murai printf("Interactive mode\n"); 346780700e5SAndrey A. Chernov netfd = STDIN_FILENO; 347af57ed9fSAtsushi Murai } else if (mode & MODE_AUTO) { 348680026d6SNate Williams printf("Automatic Dialer mode\n"); 349af57ed9fSAtsushi Murai if (dstsystem == NULL) { 350680026d6SNate Williams fprintf(stderr, 351680026d6SNate Williams "Destination system must be specified in auto or ddial mode.\n"); 352af57ed9fSAtsushi Murai exit(EX_START); 353af57ed9fSAtsushi Murai } 3546d14e2a8SJordan K. Hubbard } else if (mode & MODE_BACKGROUND) { 3556d14e2a8SJordan K. Hubbard printf("Background mode\n"); 3566d14e2a8SJordan K. Hubbard if (dstsystem == NULL) { 3576d14e2a8SJordan K. Hubbard fprintf(stderr, "Destination system must be specified in background mode.\n"); 3586d14e2a8SJordan K. Hubbard exit(EX_START); 3596d14e2a8SJordan K. Hubbard } 360af57ed9fSAtsushi Murai } 361af57ed9fSAtsushi Murai 36253c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 363af57ed9fSAtsushi Murai 364c6c740beSBrian Somers pending_signal(SIGHUP, LogReOpen); 365f5ff0f7cSBrian Somers pending_signal(SIGTERM, CloseSession); 366f5ff0f7cSBrian Somers pending_signal(SIGINT, CloseSession); 367f5ff0f7cSBrian Somers pending_signal(SIGQUIT, CloseSession); 36853c9f6c0SAtsushi Murai #ifdef SIGSEGV 369d7f5ee41SAndrey A. Chernov signal(SIGSEGV, Hangup); 37053c9f6c0SAtsushi Murai #endif 37153c9f6c0SAtsushi Murai #ifdef SIGPIPE 372e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 37353c9f6c0SAtsushi Murai #endif 37453c9f6c0SAtsushi Murai #ifdef SIGALRM 375f5ff0f7cSBrian Somers pending_signal(SIGALRM, SIG_IGN); 37653c9f6c0SAtsushi Murai #endif 377c3899f8dSAtsushi Murai if(mode & MODE_INTER) 378c3899f8dSAtsushi Murai { 379c3899f8dSAtsushi Murai #ifdef SIGTSTP 380f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 381c3899f8dSAtsushi Murai #endif 382c3899f8dSAtsushi Murai #ifdef SIGTTIN 383f5ff0f7cSBrian Somers pending_signal(SIGTTIN, TerminalStop); 384c3899f8dSAtsushi Murai #endif 385c3899f8dSAtsushi Murai #ifdef SIGTTOU 386f5ff0f7cSBrian Somers pending_signal(SIGTTOU, SIG_IGN); 387c3899f8dSAtsushi Murai #endif 388c3899f8dSAtsushi Murai } 389af57ed9fSAtsushi Murai 390af57ed9fSAtsushi Murai if (dstsystem) { 391af57ed9fSAtsushi Murai if (SelectSystem(dstsystem, CONFFILE) < 0) { 392af57ed9fSAtsushi Murai fprintf(stderr, "Destination system not found in conf file.\n"); 393af57ed9fSAtsushi Murai Cleanup(EX_START); 394af57ed9fSAtsushi Murai } 395af57ed9fSAtsushi Murai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 396680026d6SNate Williams fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n"); 397af57ed9fSAtsushi Murai Cleanup(EX_START); 398af57ed9fSAtsushi Murai } 399af57ed9fSAtsushi Murai } 400af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) 401af57ed9fSAtsushi Murai printf("Packet mode enabled.\n"); 402af57ed9fSAtsushi Murai 403af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) { 404af57ed9fSAtsushi Murai int port = SERVER_PORT + tunno; 4056d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4066d14e2a8SJordan K. Hubbard if (pipe (BGFiledes)) { 4076d14e2a8SJordan K. Hubbard perror("pipe"); 4086d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4096d14e2a8SJordan K. Hubbard } 4106d14e2a8SJordan K. Hubbard } 4116d14e2a8SJordan K. Hubbard else { 412af57ed9fSAtsushi Murai /* 413af57ed9fSAtsushi Murai * Create server socket and listen at there. 414af57ed9fSAtsushi Murai */ 415af57ed9fSAtsushi Murai server = socket(PF_INET, SOCK_STREAM, 0); 416af57ed9fSAtsushi Murai if (server < 0) { 417af57ed9fSAtsushi Murai perror("socket"); 418af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 419af57ed9fSAtsushi Murai } 420af57ed9fSAtsushi Murai ifsin.sin_family = AF_INET; 421af57ed9fSAtsushi Murai ifsin.sin_addr.s_addr = INADDR_ANY; 422af57ed9fSAtsushi Murai ifsin.sin_port = htons(port); 423af57ed9fSAtsushi Murai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 424af57ed9fSAtsushi Murai perror("bind"); 425af57ed9fSAtsushi Murai if (errno == EADDRINUSE) 426af57ed9fSAtsushi Murai fprintf(stderr, "Wait for a while, then try again.\n"); 427af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 428af57ed9fSAtsushi Murai } 429274e766cSBrian Somers if (listen(server, 5) != 0) { 430274e766cSBrian Somers fprintf(stderr, "Unable to listen to socket - OS overload?\n"); 431274e766cSBrian Somers } 4326d14e2a8SJordan K. Hubbard } 433af57ed9fSAtsushi Murai 434af57ed9fSAtsushi Murai DupLog(); 435af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 4366d14e2a8SJordan K. Hubbard pid_t bgpid; 437a9c6b5dfSAtsushi Murai 4386d14e2a8SJordan K. Hubbard bgpid = fork (); 4396d14e2a8SJordan K. Hubbard if (bgpid == -1) { 4406d14e2a8SJordan K. Hubbard perror ("fork"); 4416d14e2a8SJordan K. Hubbard Cleanup (EX_SOCK); 4426d14e2a8SJordan K. Hubbard } 4436d14e2a8SJordan K. Hubbard if (bgpid) { 4446d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 445a9c6b5dfSAtsushi Murai 4466d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4476d14e2a8SJordan K. Hubbard /* Wait for our child to close its pipe before we exit. */ 4486d14e2a8SJordan K. Hubbard BGPid = bgpid; 4496e4959f0SBrian Somers close (BGFiledes[1]); 4506e4959f0SBrian Somers if (read(BGFiledes[0], &c, 1) != 1) 4516e4959f0SBrian Somers LogPrintf (LOG_PHASE_BIT, "Parent: Child exit, no status.\n"); 4526e4959f0SBrian Somers else if (c == EX_NORMAL) 4536e4959f0SBrian Somers LogPrintf (LOG_PHASE_BIT, "Parent: PPP enabled.\n"); 4546e4959f0SBrian Somers else 4556e4959f0SBrian Somers LogPrintf (LOG_PHASE_BIT, "Parent: Child failed %d.\n",(int)c); 4566e4959f0SBrian Somers close (BGFiledes[0]); 4576d14e2a8SJordan K. Hubbard } 4586d14e2a8SJordan K. Hubbard exit(c); 4596e4959f0SBrian Somers } else if (mode & MODE_BACKGROUND) 4606e4959f0SBrian Somers close(BGFiledes[0]); 461aefd026aSBrian Somers } 4626d14e2a8SJordan K. Hubbard 46341c6c543SBrian Somers snprintf(pid_filename, sizeof (pid_filename), "%s/tun%d.pid", 4646d14e2a8SJordan K. Hubbard _PATH_VARRUN, tunno); 465aefd026aSBrian Somers (void)unlink(pid_filename); 466a9c6b5dfSAtsushi Murai 467aefd026aSBrian Somers if ((lockfile = fopen(pid_filename, "w")) != NULL) { 46841c6c543SBrian Somers fprintf(lockfile, "%d\n", (int)getpid()); 46941c6c543SBrian Somers fclose(lockfile); 470aefd026aSBrian Somers } else 471aefd026aSBrian Somers logprintf("Warning: Can't create %s: %s\n", pid_filename, strerror(errno)); 47241c6c543SBrian Somers 47341c6c543SBrian Somers snprintf(if_filename, sizeof if_filename, "%s%s.if", 47441c6c543SBrian Somers _PATH_VARRUN, VarBaseDevice); 475aefd026aSBrian Somers (void)unlink(if_filename); 47641c6c543SBrian Somers 477aefd026aSBrian Somers if ((lockfile = fopen(if_filename, "w")) != NULL) { 47841c6c543SBrian Somers fprintf(lockfile, "tun%d\n", tunno); 47941c6c543SBrian Somers fclose(lockfile); 480aefd026aSBrian Somers } else 481aefd026aSBrian Somers logprintf("Warning: Can't create %s: %s\n", if_filename, strerror(errno)); 482aefd026aSBrian Somers 483780700e5SAndrey A. Chernov if (server >= 0) 4849c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port); 485af57ed9fSAtsushi Murai #ifdef DOTTYINIT 48653c9f6c0SAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 487af57ed9fSAtsushi Murai #else 488af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) { 489af57ed9fSAtsushi Murai #endif 490af57ed9fSAtsushi Murai TtyInit(); 491af57ed9fSAtsushi Murai } else { 492d91680eaSAndrey A. Chernov int fd; 493d91680eaSAndrey A. Chernov 494af57ed9fSAtsushi Murai setsid(); /* detach control tty */ 495d91680eaSAndrey A. Chernov if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 496d91680eaSAndrey A. Chernov (void)dup2(fd, STDIN_FILENO); 497d91680eaSAndrey A. Chernov (void)dup2(fd, STDOUT_FILENO); 498d91680eaSAndrey A. Chernov (void)dup2(fd, STDERR_FILENO); 499d91680eaSAndrey A. Chernov if (fd > 2) 500d91680eaSAndrey A. Chernov (void)close (fd); 501d91680eaSAndrey A. Chernov } 502af57ed9fSAtsushi Murai } 503af57ed9fSAtsushi Murai } else { 504af57ed9fSAtsushi Murai TtyInit(); 505c3899f8dSAtsushi Murai TtyCommandMode(1); 506af57ed9fSAtsushi Murai } 5079c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "PPP Started.\n"); 508af57ed9fSAtsushi Murai 509af57ed9fSAtsushi Murai 510af57ed9fSAtsushi Murai do 511af57ed9fSAtsushi Murai DoLoop(); 512af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 513af57ed9fSAtsushi Murai 514af57ed9fSAtsushi Murai Cleanup(EX_DONE); 515af57ed9fSAtsushi Murai } 516af57ed9fSAtsushi Murai 517af57ed9fSAtsushi Murai /* 5186d14e2a8SJordan K. Hubbard * Turn into packet mode, where we speak PPP. 519af57ed9fSAtsushi Murai */ 520af57ed9fSAtsushi Murai void 521af57ed9fSAtsushi Murai PacketMode() 522af57ed9fSAtsushi Murai { 523af57ed9fSAtsushi Murai if (RawModem(modem) < 0) { 524af57ed9fSAtsushi Murai fprintf(stderr, "Not connected.\r\n"); 525af57ed9fSAtsushi Murai return; 526af57ed9fSAtsushi Murai } 527af57ed9fSAtsushi Murai 528af57ed9fSAtsushi Murai AsyncInit(); 529af57ed9fSAtsushi Murai VjInit(); 530af57ed9fSAtsushi Murai LcpInit(); 531af57ed9fSAtsushi Murai IpcpInit(); 532af57ed9fSAtsushi Murai CcpInit(); 533af57ed9fSAtsushi Murai LcpUp(); 534af57ed9fSAtsushi Murai 535af57ed9fSAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 536af57ed9fSAtsushi Murai LcpOpen(OPEN_ACTIVE); 537af57ed9fSAtsushi Murai else 538af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 539af57ed9fSAtsushi Murai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 540c3899f8dSAtsushi Murai TtyCommandMode(1); 541af57ed9fSAtsushi Murai fprintf(stderr, "Packet mode.\r\n"); 542b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 543af57ed9fSAtsushi Murai } 544af57ed9fSAtsushi Murai } 545af57ed9fSAtsushi Murai 546af57ed9fSAtsushi Murai static void 547af57ed9fSAtsushi Murai ShowHelp() 548af57ed9fSAtsushi Murai { 549c3899f8dSAtsushi Murai fprintf(stderr, "The following commands are available:\r\n"); 550af57ed9fSAtsushi Murai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 5511dff3fc5SAndrey A. Chernov fprintf(stderr, " ~-\tDecrease log level\r\n"); 5521dff3fc5SAndrey A. Chernov fprintf(stderr, " ~+\tIncrease log level\r\n"); 553af57ed9fSAtsushi Murai fprintf(stderr, " ~.\tTerminate program\r\n"); 5541dff3fc5SAndrey A. Chernov fprintf(stderr, " ~?\tThis help\r\n"); 555af57ed9fSAtsushi Murai } 556af57ed9fSAtsushi Murai 557af57ed9fSAtsushi Murai static void 558af57ed9fSAtsushi Murai ReadTty() 559af57ed9fSAtsushi Murai { 560af57ed9fSAtsushi Murai int n; 561af57ed9fSAtsushi Murai char ch; 562af57ed9fSAtsushi Murai static int ttystate; 563af57ed9fSAtsushi Murai #define MAXLINESIZE 200 564af57ed9fSAtsushi Murai char linebuff[MAXLINESIZE]; 565af57ed9fSAtsushi Murai 566af57ed9fSAtsushi Murai #ifdef DEBUG 567af57ed9fSAtsushi Murai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 568af57ed9fSAtsushi Murai #endif 569af57ed9fSAtsushi Murai if (!TermMode) { 570af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff)-1); 571b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 57253c9f6c0SAtsushi Murai if (n > 0) { 573af57ed9fSAtsushi Murai DecodeCommand(linebuff, n, 1); 57453c9f6c0SAtsushi Murai } else { 575e0d3e233SAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "client connection closed.\n"); 576e0d3e233SAndrey A. Chernov VarLocalAuth = LOCAL_NO_AUTH; 577af57ed9fSAtsushi Murai close(netfd); 578e0d3e233SAndrey A. Chernov close(1); 579e0d3e233SAndrey A. Chernov dup2(2, 1); /* Have to have something here or the modem will be 1 */ 580af57ed9fSAtsushi Murai netfd = -1; 581af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 582af57ed9fSAtsushi Murai } 583af57ed9fSAtsushi Murai return; 584af57ed9fSAtsushi Murai } 585af57ed9fSAtsushi Murai 586af57ed9fSAtsushi Murai /* 587af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 588af57ed9fSAtsushi Murai */ 589af57ed9fSAtsushi Murai n = read(0, &ch, 1); 590af57ed9fSAtsushi Murai #ifdef DEBUG 591af57ed9fSAtsushi Murai logprintf("got %d bytes\n", n); 592af57ed9fSAtsushi Murai #endif 593af57ed9fSAtsushi Murai 594af57ed9fSAtsushi Murai if (n > 0) { 595af57ed9fSAtsushi Murai switch (ttystate) { 596af57ed9fSAtsushi Murai case 0: 597af57ed9fSAtsushi Murai if (ch == '~') 598af57ed9fSAtsushi Murai ttystate++; 599af57ed9fSAtsushi Murai else 600af57ed9fSAtsushi Murai write(modem, &ch, n); 601af57ed9fSAtsushi Murai break; 602af57ed9fSAtsushi Murai case 1: 603af57ed9fSAtsushi Murai switch (ch) { 604af57ed9fSAtsushi Murai case '?': 605af57ed9fSAtsushi Murai ShowHelp(); 606af57ed9fSAtsushi Murai break; 607af57ed9fSAtsushi Murai case '-': 608af57ed9fSAtsushi Murai if (loglevel > 0) { 609af57ed9fSAtsushi Murai loglevel--; 610af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 611af57ed9fSAtsushi Murai } 612af57ed9fSAtsushi Murai break; 613af57ed9fSAtsushi Murai case '+': 614af57ed9fSAtsushi Murai loglevel++; 615af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 616af57ed9fSAtsushi Murai break; 617af57ed9fSAtsushi Murai #ifdef DEBUG 618af57ed9fSAtsushi Murai case 'm': 619af57ed9fSAtsushi Murai ShowMemMap(); 620af57ed9fSAtsushi Murai break; 621af57ed9fSAtsushi Murai #endif 622af57ed9fSAtsushi Murai case 'p': 623af57ed9fSAtsushi Murai /* 624af57ed9fSAtsushi Murai * XXX: Should check carrier. 625af57ed9fSAtsushi Murai */ 626af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 627af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 628af57ed9fSAtsushi Murai PacketMode(); 629af57ed9fSAtsushi Murai } 630af57ed9fSAtsushi Murai break; 631af57ed9fSAtsushi Murai #ifdef DEBUG 632af57ed9fSAtsushi Murai case 't': 633af57ed9fSAtsushi Murai ShowTimers(); 634af57ed9fSAtsushi Murai break; 635af57ed9fSAtsushi Murai #endif 636af57ed9fSAtsushi Murai case '.': 637af57ed9fSAtsushi Murai TermMode = 1; 638c3899f8dSAtsushi Murai TtyCommandMode(1); 639af57ed9fSAtsushi Murai break; 640af57ed9fSAtsushi Murai default: 641af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 642af57ed9fSAtsushi Murai fprintf(stderr, "err in write.\r\n"); 643af57ed9fSAtsushi Murai break; 644af57ed9fSAtsushi Murai } 645af57ed9fSAtsushi Murai ttystate = 0; 646af57ed9fSAtsushi Murai break; 647af57ed9fSAtsushi Murai } 648af57ed9fSAtsushi Murai } 649af57ed9fSAtsushi Murai } 650af57ed9fSAtsushi Murai 651af57ed9fSAtsushi Murai 652af57ed9fSAtsushi Murai /* 653af57ed9fSAtsushi Murai * Here, we'll try to detect HDLC frame 654af57ed9fSAtsushi Murai */ 655af57ed9fSAtsushi Murai 656af57ed9fSAtsushi Murai static char *FrameHeaders[] = { 65753c9f6c0SAtsushi Murai "\176\377\003\300\041", 65853c9f6c0SAtsushi Murai "\176\377\175\043\300\041", 65953c9f6c0SAtsushi Murai "\176\177\175\043\100\041", 66053c9f6c0SAtsushi Murai "\176\175\337\175\043\300\041", 66153c9f6c0SAtsushi Murai "\176\175\137\175\043\100\041", 662af57ed9fSAtsushi Murai NULL, 663af57ed9fSAtsushi Murai }; 664af57ed9fSAtsushi Murai 665af57ed9fSAtsushi Murai u_char * 666af57ed9fSAtsushi Murai HdlcDetect(cp, n) 667af57ed9fSAtsushi Murai u_char *cp; 668af57ed9fSAtsushi Murai int n; 669af57ed9fSAtsushi Murai { 67053c9f6c0SAtsushi Murai char *ptr, *fp, **hp; 671af57ed9fSAtsushi Murai 672af57ed9fSAtsushi Murai cp[n] = '\0'; /* be sure to null terminated */ 673af57ed9fSAtsushi Murai ptr = NULL; 674af57ed9fSAtsushi Murai for (hp = FrameHeaders; *hp; hp++) { 67553c9f6c0SAtsushi Murai fp = *hp; 67653c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 67753c9f6c0SAtsushi Murai fp++; 678ed6a16c1SPoul-Henning Kamp ptr = strstr((char *)cp, fp); 679ed6a16c1SPoul-Henning Kamp if (ptr) 680af57ed9fSAtsushi Murai break; 681af57ed9fSAtsushi Murai } 682af57ed9fSAtsushi Murai return((u_char *)ptr); 683af57ed9fSAtsushi Murai } 684af57ed9fSAtsushi Murai 685af57ed9fSAtsushi Murai static struct pppTimer RedialTimer; 686af57ed9fSAtsushi Murai 687af57ed9fSAtsushi Murai static void 688af57ed9fSAtsushi Murai RedialTimeout() 689af57ed9fSAtsushi Murai { 690af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 6919c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Redialing timer expired.\n"); 692af57ed9fSAtsushi Murai } 693af57ed9fSAtsushi Murai 694af57ed9fSAtsushi Murai static void 69543ea9d19SBrian Somers StartRedialTimer(Timeout) 69643ea9d19SBrian Somers int Timeout; 697af57ed9fSAtsushi Murai { 698af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 699a9c6b5dfSAtsushi Murai 70043ea9d19SBrian Somers if (Timeout) { 701af57ed9fSAtsushi Murai RedialTimer.state = TIMER_STOPPED; 702a9c6b5dfSAtsushi Murai 70343ea9d19SBrian Somers if (Timeout > 0) 70443ea9d19SBrian Somers RedialTimer.load = Timeout * SECTICKS; 705a9c6b5dfSAtsushi Murai else 706a9c6b5dfSAtsushi Murai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 707a9c6b5dfSAtsushi Murai 70843ea9d19SBrian Somers LogPrintf(LOG_PHASE_BIT, "Enter pause (%d) for redialing.\n", 70943ea9d19SBrian Somers RedialTimer.load / SECTICKS); 71043ea9d19SBrian Somers 711af57ed9fSAtsushi Murai RedialTimer.func = RedialTimeout; 712af57ed9fSAtsushi Murai StartTimer(&RedialTimer); 713af57ed9fSAtsushi Murai } 714a9c6b5dfSAtsushi Murai } 715af57ed9fSAtsushi Murai 716af57ed9fSAtsushi Murai 717af57ed9fSAtsushi Murai static void 718af57ed9fSAtsushi Murai DoLoop() 719af57ed9fSAtsushi Murai { 720af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 721780700e5SAndrey A. Chernov int pri, i, n, wfd, nfds; 722af57ed9fSAtsushi Murai struct sockaddr_in hisaddr; 723af57ed9fSAtsushi Murai struct timeval timeout, *tp; 724af57ed9fSAtsushi Murai int ssize = sizeof(hisaddr); 725af57ed9fSAtsushi Murai u_char *cp; 726af57ed9fSAtsushi Murai u_char rbuff[MAX_MRU]; 72784b8a6ebSAtsushi Murai int dial_up; 728a9c6b5dfSAtsushi Murai int tries; 72960e218e4SAtsushi Murai int qlen; 730c3899f8dSAtsushi Murai pid_t pgroup; 731c3899f8dSAtsushi Murai 732c3899f8dSAtsushi Murai pgroup = getpgrp(); 733af57ed9fSAtsushi Murai 7346e4959f0SBrian Somers if (mode & (MODE_DIRECT|MODE_BACKGROUND)) { 735af57ed9fSAtsushi Murai modem = OpenModem(mode); 7369c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n"); 737b0cdb3ceSJordan K. Hubbard fflush(stderr); 738af57ed9fSAtsushi Murai PacketMode(); 739af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 740780700e5SAndrey A. Chernov if (modem < 0) 741af57ed9fSAtsushi Murai modem = OpenModem(mode); 742af57ed9fSAtsushi Murai } 743af57ed9fSAtsushi Murai 744af57ed9fSAtsushi Murai fflush(stdout); 745af57ed9fSAtsushi Murai 74684b8a6ebSAtsushi Murai timeout.tv_sec = 0; 747af57ed9fSAtsushi Murai timeout.tv_usec = 0; 74807030d97SBrian Somers lostCarrier = 0; 749af57ed9fSAtsushi Murai 7506e4959f0SBrian Somers if (mode & MODE_BACKGROUND) 7516e4959f0SBrian Somers dial_up = TRUE; /* Bring the line up */ 7526e4959f0SBrian Somers else 75384b8a6ebSAtsushi Murai dial_up = FALSE; /* XXXX */ 754a9c6b5dfSAtsushi Murai tries = 0; 755af57ed9fSAtsushi Murai for (;;) { 756780700e5SAndrey A. Chernov nfds = 0; 757af57ed9fSAtsushi Murai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 75884b8a6ebSAtsushi Murai 75984b8a6ebSAtsushi Murai /* 760680026d6SNate Williams * If the link is down and we're in DDIAL mode, bring it back 761680026d6SNate Williams * up. 762680026d6SNate Williams */ 763680026d6SNate Williams if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 764680026d6SNate Williams dial_up = TRUE; 765680026d6SNate Williams 766680026d6SNate Williams /* 76707030d97SBrian Somers * If we lost carrier and want to re-establish the connection 76807030d97SBrian Somers * due to the "set reconnect" value, we'd better bring the line 76907030d97SBrian Somers * back up now. 77007030d97SBrian Somers */ 77107030d97SBrian Somers if (LcpFsm.state <= ST_CLOSED && dial_up != TRUE 77207030d97SBrian Somers && lostCarrier && lostCarrier <= VarReconnectTries) { 77307030d97SBrian Somers LogPrintf(LOG_PHASE_BIT, "Connection lost, re-establish (%d/%d)\n", 77407030d97SBrian Somers lostCarrier, VarReconnectTries); 77507030d97SBrian Somers StartRedialTimer(VarReconnectTimer); 77607030d97SBrian Somers dial_up = TRUE; 77707030d97SBrian Somers } 77807030d97SBrian Somers 77907030d97SBrian Somers /* 78084b8a6ebSAtsushi Murai * If Ip packet for output is enqueued and require dial up, 78184b8a6ebSAtsushi Murai * Just do it! 78284b8a6ebSAtsushi Murai */ 78307030d97SBrian Somers if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { 78484b8a6ebSAtsushi Murai #ifdef DEBUG 78584b8a6ebSAtsushi Murai logprintf("going to dial: modem = %d\n", modem); 78684b8a6ebSAtsushi Murai #endif 78784b8a6ebSAtsushi Murai modem = OpenModem(mode); 78884b8a6ebSAtsushi Murai if (modem < 0) { 78943ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 79084b8a6ebSAtsushi Murai } else { 791c0139fb2SBrian Somers tries++; /* Tries are per number, not per list of numbers. */ 792c0139fb2SBrian Somers if (VarDialTries) 793c0139fb2SBrian Somers LogPrintf(LOG_CHAT_BIT, "Dial attempt %u of %d\n", tries, 794c0139fb2SBrian Somers VarDialTries); 795c0139fb2SBrian Somers else 7969c749ffbSPoul-Henning Kamp LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries); 79784b8a6ebSAtsushi Murai if (DialModem()) { 79884b8a6ebSAtsushi Murai sleep(1); /* little pause to allow peer starts */ 79984b8a6ebSAtsushi Murai ModemTimeout(); 80084b8a6ebSAtsushi Murai PacketMode(); 80184b8a6ebSAtsushi Murai dial_up = FALSE; 802a9c6b5dfSAtsushi Murai tries = 0; 80384b8a6ebSAtsushi Murai } else { 80484b8a6ebSAtsushi Murai CloseModem(); 8054ed9958fSBrian Somers if (mode & MODE_BACKGROUND) { 8064ed9958fSBrian Somers if (VarNextPhone == NULL) 8074ed9958fSBrian Somers Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 8084ed9958fSBrian Somers else 80943ea9d19SBrian Somers /* Try all numbers in background mode */ 81043ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 8114ed9958fSBrian Somers } else if (VarDialTries && tries >= VarDialTries) { 812c0139fb2SBrian Somers /* I give up ! Can't get through :( */ 81343ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 814a9c6b5dfSAtsushi Murai dial_up = FALSE; 815a9c6b5dfSAtsushi Murai tries = 0; 816c0139fb2SBrian Somers } else if (VarNextPhone == NULL) 817c0139fb2SBrian Somers /* Dial failed. Keep quite during redial wait period. */ 81843ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 819c0139fb2SBrian Somers else 82043ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 82184b8a6ebSAtsushi Murai } 82284b8a6ebSAtsushi Murai } 82384b8a6ebSAtsushi Murai } 82460e218e4SAtsushi Murai qlen = ModemQlen(); 82576bd0c0aSDoug Rabson 82676bd0c0aSDoug Rabson if (qlen == 0) { 82776bd0c0aSDoug Rabson IpStartOutput(); 82876bd0c0aSDoug Rabson qlen = ModemQlen(); 82976bd0c0aSDoug Rabson } 83076bd0c0aSDoug Rabson 831780700e5SAndrey A. Chernov if (modem >= 0) { 832780700e5SAndrey A. Chernov if (modem + 1 > nfds) 833780700e5SAndrey A. Chernov nfds = modem + 1; 83484b8a6ebSAtsushi Murai FD_SET(modem, &rfds); 83584b8a6ebSAtsushi Murai FD_SET(modem, &efds); 83660e218e4SAtsushi Murai if (qlen > 0) { 83784b8a6ebSAtsushi Murai FD_SET(modem, &wfds); 83884b8a6ebSAtsushi Murai } 83984b8a6ebSAtsushi Murai } 840780700e5SAndrey A. Chernov if (server >= 0) { 841780700e5SAndrey A. Chernov if (server + 1 > nfds) 842780700e5SAndrey A. Chernov nfds = server + 1; 843780700e5SAndrey A. Chernov FD_SET(server, &rfds); 844780700e5SAndrey A. Chernov } 845af57ed9fSAtsushi Murai 846af57ed9fSAtsushi Murai /* *** IMPORTANT *** 847af57ed9fSAtsushi Murai * 848af57ed9fSAtsushi Murai * CPU is serviced every TICKUNIT micro seconds. 849af57ed9fSAtsushi Murai * This value must be chosen with great care. If this values is 850af57ed9fSAtsushi Murai * too big, it results loss of characters from modem and poor responce. 851af57ed9fSAtsushi Murai * If this values is too small, ppp process eats many CPU time. 852af57ed9fSAtsushi Murai */ 85353c9f6c0SAtsushi Murai #ifndef SIGALRM 854af57ed9fSAtsushi Murai usleep(TICKUNIT); 855af57ed9fSAtsushi Murai TimerService(); 856f5ff0f7cSBrian Somers #else 857f5ff0f7cSBrian Somers handle_signals(); 85853c9f6c0SAtsushi Murai #endif 85968d2b4d6SBruce Evans 86068d2b4d6SBruce Evans /* If there are aren't many packets queued, look for some more. */ 861780700e5SAndrey A. Chernov if (qlen < 20 && tun_in >= 0) { 862780700e5SAndrey A. Chernov if (tun_in + 1 > nfds) 863780700e5SAndrey A. Chernov nfds = tun_in + 1; 86484b8a6ebSAtsushi Murai FD_SET(tun_in, &rfds); 865780700e5SAndrey A. Chernov } 86668d2b4d6SBruce Evans 867780700e5SAndrey A. Chernov if (netfd >= 0) { 868780700e5SAndrey A. Chernov if (netfd + 1 > nfds) 869780700e5SAndrey A. Chernov nfds = netfd + 1; 870af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 871af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 872af57ed9fSAtsushi Murai } 87384b8a6ebSAtsushi Murai 87453c9f6c0SAtsushi Murai #ifndef SIGALRM 875af57ed9fSAtsushi Murai /* 87684b8a6ebSAtsushi Murai * Normally, select() will not block because modem is writable. 87784b8a6ebSAtsushi Murai * In AUTO mode, select will block until we find packet from tun 878af57ed9fSAtsushi Murai */ 879af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 880780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 88153c9f6c0SAtsushi Murai #else 88284b8a6ebSAtsushi Murai /* 88384b8a6ebSAtsushi Murai * When SIGALRM timer is running, a select function will be 88484b8a6ebSAtsushi Murai * return -1 and EINTR after a Time Service signal hundler 885a9c6b5dfSAtsushi Murai * is done. If the redial timer is not running and we are 886a9c6b5dfSAtsushi Murai * trying to dial, poll with a 0 value timer. 88784b8a6ebSAtsushi Murai */ 888a9c6b5dfSAtsushi Murai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 889780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 89053c9f6c0SAtsushi Murai #endif 8916b0b88d8SBrian Somers 892af57ed9fSAtsushi Murai if ( i == 0 ) { 893af57ed9fSAtsushi Murai continue; 894af57ed9fSAtsushi Murai } 89553c9f6c0SAtsushi Murai 896534fe541SBrian Somers if ( i < 0 ) { 897534fe541SBrian Somers if ( errno == EINTR ) { 898f5ff0f7cSBrian Somers handle_signals(); 899f5ff0f7cSBrian Somers continue; 90084b8a6ebSAtsushi Murai } 901af57ed9fSAtsushi Murai perror("select"); 902af57ed9fSAtsushi Murai break; 903af57ed9fSAtsushi Murai } 90484b8a6ebSAtsushi Murai 905780700e5SAndrey A. Chernov if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 906af57ed9fSAtsushi Murai logprintf("Exception detected.\n"); 907af57ed9fSAtsushi Murai break; 908af57ed9fSAtsushi Murai } 909af57ed9fSAtsushi Murai 910780700e5SAndrey A. Chernov if (server >= 0 && FD_ISSET(server, &rfds)) { 911e0d3e233SAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "connected to client.\n"); 912af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 913e0d3e233SAndrey A. Chernov if (wfd < 0) { 914e0d3e233SAndrey A. Chernov perror("accept"); 915e0d3e233SAndrey A. Chernov continue; 916e0d3e233SAndrey A. Chernov } 917780700e5SAndrey A. Chernov if (netfd >= 0) { 918af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 919af57ed9fSAtsushi Murai close(wfd); 920af57ed9fSAtsushi Murai continue; 921af57ed9fSAtsushi Murai } else 922af57ed9fSAtsushi Murai netfd = wfd; 923e0d3e233SAndrey A. Chernov if (dup2(netfd, 1) < 0) { 924af57ed9fSAtsushi Murai perror("dup2"); 925e0d3e233SAndrey A. Chernov close(netfd); 926e0d3e233SAndrey A. Chernov netfd = -1; 927e0d3e233SAndrey A. Chernov continue; 928e0d3e233SAndrey A. Chernov } 929af57ed9fSAtsushi Murai mode |= MODE_INTER; 930af57ed9fSAtsushi Murai Greetings(); 93141db6564SAtsushi Murai switch ( LocalAuthInit() ) { 93241db6564SAtsushi Murai case NOT_FOUND: 93341db6564SAtsushi Murai fprintf(stdout,LAUTH_M1); 93441db6564SAtsushi Murai fprintf(stdout,LAUTH_M2); 93541db6564SAtsushi Murai fflush(stdout); 93641db6564SAtsushi Murai /* Fall down */ 93741db6564SAtsushi Murai case VALID: 93841db6564SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 93941db6564SAtsushi Murai break; 94041db6564SAtsushi Murai default: 94141db6564SAtsushi Murai break; 94241db6564SAtsushi Murai } 943af57ed9fSAtsushi Murai (void) IsInteractive(); 944274e766cSBrian Somers Prompt(); 945af57ed9fSAtsushi Murai } 946af57ed9fSAtsushi Murai 947780700e5SAndrey A. Chernov if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 948f1884650SAtsushi Murai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 949af57ed9fSAtsushi Murai /* something to read from tty */ 950af57ed9fSAtsushi Murai ReadTty(); 951af57ed9fSAtsushi Murai } 952780700e5SAndrey A. Chernov if (modem >= 0) { 953af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 954af57ed9fSAtsushi Murai ModemStartOutput(modem); 955af57ed9fSAtsushi Murai } 956af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 95753c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 95853c9f6c0SAtsushi Murai usleep(10000); 959af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 960af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 961af57ed9fSAtsushi Murai DownConnection(); 962af57ed9fSAtsushi Murai } else 963af57ed9fSAtsushi Murai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 964af57ed9fSAtsushi Murai 965af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 966af57ed9fSAtsushi Murai /* 967af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 968af57ed9fSAtsushi Murai */ 969af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 970af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 971af57ed9fSAtsushi Murai if (cp) { 972af57ed9fSAtsushi Murai /* 973af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 974af57ed9fSAtsushi Murai */ 975af57ed9fSAtsushi Murai if (cp != rbuff) { 976af57ed9fSAtsushi Murai write(1, rbuff, cp - rbuff); 977af57ed9fSAtsushi Murai write(1, "\r\n", 2); 978af57ed9fSAtsushi Murai } 979af57ed9fSAtsushi Murai PacketMode(); 980af57ed9fSAtsushi Murai } else 981af57ed9fSAtsushi Murai write(1, rbuff, n); 982af57ed9fSAtsushi Murai } 983af57ed9fSAtsushi Murai } else { 984af57ed9fSAtsushi Murai if (n > 0) 985af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 986af57ed9fSAtsushi Murai } 987af57ed9fSAtsushi Murai } 988af57ed9fSAtsushi Murai } 98984b8a6ebSAtsushi Murai 990780700e5SAndrey A. Chernov if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 991af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 992af57ed9fSAtsushi Murai if (n < 0) { 993af57ed9fSAtsushi Murai perror("read from tun"); 994af57ed9fSAtsushi Murai continue; 995af57ed9fSAtsushi Murai } 996af57ed9fSAtsushi Murai /* 997af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 998af57ed9fSAtsushi Murai * device until IPCP is opened. 999af57ed9fSAtsushi Murai */ 1000af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 100184b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_DIAL); 1002af57ed9fSAtsushi Murai if (pri >= 0) { 1003a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10043b92d2deSNate Williams PacketAliasOut((struct ip *)rbuff); 1005a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 1006a9f484e5SJordan K. Hubbard } 1007af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 100884b8a6ebSAtsushi Murai dial_up = TRUE; /* XXX */ 1009af57ed9fSAtsushi Murai } 1010af57ed9fSAtsushi Murai continue; 1011af57ed9fSAtsushi Murai } 101284b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_OUT); 1013a9f484e5SJordan K. Hubbard if (pri >= 0) { 1014a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10153b92d2deSNate Williams PacketAliasOut((struct ip *)rbuff); 1016a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 1017a9f484e5SJordan K. Hubbard } 1018af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 1019af57ed9fSAtsushi Murai } 1020af57ed9fSAtsushi Murai } 1021a9f484e5SJordan K. Hubbard } 1022af57ed9fSAtsushi Murai logprintf("job done.\n"); 1023af57ed9fSAtsushi Murai } 1024