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 * 2007030d97SBrian Somers * $Id: main.c,v 1.44 1997/04/14 23:48:15 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(); 64af57ed9fSAtsushi Murai extern void AsyncInput(), IpOutput(); 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 extern struct in_addr ifnetmask; 71af57ed9fSAtsushi Murai static void DoLoop(void); 72c3899f8dSAtsushi Murai static void TerminalStop(); 73af57ed9fSAtsushi Murai 74af57ed9fSAtsushi Murai static struct termios oldtio; /* Original tty mode */ 75af57ed9fSAtsushi Murai static struct termios comtio; /* Command level tty mode */ 761dff3fc5SAndrey A. Chernov int TermMode; 777b64106aSPoul-Henning Kamp static int server; 786d14e2a8SJordan K. Hubbard static pid_t BGPid = 0; 79af57ed9fSAtsushi Murai struct sockaddr_in ifsin; 80a9c6b5dfSAtsushi Murai char pid_filename[128]; 81af57ed9fSAtsushi Murai 82af57ed9fSAtsushi Murai static void 83af57ed9fSAtsushi Murai TtyInit() 84af57ed9fSAtsushi Murai { 85af57ed9fSAtsushi Murai struct termios newtio; 86af57ed9fSAtsushi Murai int stat; 87af57ed9fSAtsushi Murai 88af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 89af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 90af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 91af57ed9fSAtsushi Murai newtio = oldtio; 92af57ed9fSAtsushi Murai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 93af57ed9fSAtsushi Murai newtio.c_iflag = 0; 94af57ed9fSAtsushi Murai newtio.c_oflag &= ~OPOST; 95af57ed9fSAtsushi Murai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 96af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 97af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 98af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 99af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 10053c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 101af57ed9fSAtsushi Murai comtio = newtio; 102af57ed9fSAtsushi Murai } 103af57ed9fSAtsushi Murai 104af57ed9fSAtsushi Murai /* 105af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 106af57ed9fSAtsushi Murai */ 107c3899f8dSAtsushi Murai void 108c3899f8dSAtsushi Murai TtyCommandMode(prompt) 109c3899f8dSAtsushi Murai int prompt; 110af57ed9fSAtsushi Murai { 111af57ed9fSAtsushi Murai struct termios newtio; 112af57ed9fSAtsushi Murai int stat; 113af57ed9fSAtsushi Murai 114af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 115af57ed9fSAtsushi Murai return; 11653c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 117c3899f8dSAtsushi Murai newtio.c_lflag |= (ECHO|ISIG|ICANON); 118af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 119af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 12053c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 121af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 122af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 123af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 124af57ed9fSAtsushi Murai TermMode = 0; 125c3899f8dSAtsushi Murai if(prompt) Prompt(0); 126af57ed9fSAtsushi Murai } 127af57ed9fSAtsushi Murai 128af57ed9fSAtsushi Murai /* 129af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 130af57ed9fSAtsushi Murai */ 131af57ed9fSAtsushi Murai void 132af57ed9fSAtsushi Murai TtyTermMode() 133af57ed9fSAtsushi Murai { 134af57ed9fSAtsushi Murai int stat; 135af57ed9fSAtsushi Murai 13653c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 137af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 138af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 139af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 140af57ed9fSAtsushi Murai TermMode = 1; 141af57ed9fSAtsushi Murai } 142af57ed9fSAtsushi Murai 143af57ed9fSAtsushi Murai void 144c3899f8dSAtsushi Murai TtyOldMode() 145c3899f8dSAtsushi Murai { 146c3899f8dSAtsushi Murai int stat; 147c3899f8dSAtsushi Murai 148c3899f8dSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 149c3899f8dSAtsushi Murai stat &= ~O_NONBLOCK; 150c3899f8dSAtsushi Murai fcntl(0, F_SETFL, stat); 151c3899f8dSAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 152c3899f8dSAtsushi Murai } 153c3899f8dSAtsushi Murai 154c3899f8dSAtsushi Murai void 155af57ed9fSAtsushi Murai Cleanup(excode) 156af57ed9fSAtsushi Murai int excode; 157af57ed9fSAtsushi Murai { 158af57ed9fSAtsushi Murai 159af57ed9fSAtsushi Murai OsLinkdown(); 160af57ed9fSAtsushi Murai OsCloseLink(1); 161af57ed9fSAtsushi Murai sleep(1); 1626d14e2a8SJordan K. Hubbard if (mode & (MODE_AUTO | MODE_BACKGROUND)) { 1636e4959f0SBrian Somers DeleteIfRoutes(1); 164a9c6b5dfSAtsushi Murai unlink(pid_filename); 165a9c6b5dfSAtsushi Murai } 166af57ed9fSAtsushi Murai OsInterfaceDown(1); 1676e4959f0SBrian Somers if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 1686e4959f0SBrian Somers char c = EX_ERRDEAD; 1696e4959f0SBrian Somers if (write(BGFiledes[1],&c,1) == 1) 1706e4959f0SBrian Somers LogPrintf(LOG_PHASE_BIT,"Parent notified of failure.\n"); 1716e4959f0SBrian Somers else 1726e4959f0SBrian Somers LogPrintf(LOG_PHASE_BIT,"Failed to notify parent of failure.\n"); 1736e4959f0SBrian Somers close(BGFiledes[1]); 1746e4959f0SBrian Somers } 1754ed9958fSBrian Somers LogPrintf(LOG_PHASE_BIT, "PPP Terminated %d.\n",excode); 176af57ed9fSAtsushi Murai LogClose(); 177780700e5SAndrey A. Chernov if (server >= 0) { 178af57ed9fSAtsushi Murai close(server); 179780700e5SAndrey A. Chernov server = -1; 180780700e5SAndrey A. Chernov } 181c3899f8dSAtsushi Murai TtyOldMode(); 182af57ed9fSAtsushi Murai 183af57ed9fSAtsushi Murai exit(excode); 184af57ed9fSAtsushi Murai } 185af57ed9fSAtsushi Murai 186af57ed9fSAtsushi Murai static void 1877a8ef19eSAndrey A. Chernov Hangup(signo) 1887a8ef19eSAndrey A. Chernov int signo; 189af57ed9fSAtsushi Murai { 190af83607cSAndrey A. Chernov if (signo == SIGSEGV) { 191af83607cSAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo); 192af83607cSAndrey A. Chernov LogClose(); 193af83607cSAndrey A. Chernov abort(); 194af83607cSAndrey A. Chernov } 1956d14e2a8SJordan K. Hubbard if (BGPid) { 196c6c740beSBrian Somers kill (BGPid, SIGTERM); 1976d14e2a8SJordan K. Hubbard exit (EX_HANGUP); 1986d14e2a8SJordan K. Hubbard } 1996d14e2a8SJordan K. Hubbard else { 2009c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo); 201af57ed9fSAtsushi Murai Cleanup(EX_HANGUP); 202af57ed9fSAtsushi Murai } 2036d14e2a8SJordan K. Hubbard } 204af57ed9fSAtsushi Murai 205af57ed9fSAtsushi Murai static void 2067a8ef19eSAndrey A. Chernov CloseSession(signo) 2077a8ef19eSAndrey A. Chernov int signo; 208af57ed9fSAtsushi Murai { 2096d14e2a8SJordan K. Hubbard if (BGPid) { 2106d14e2a8SJordan K. Hubbard kill (BGPid, SIGINT); 2116d14e2a8SJordan K. Hubbard exit (EX_TERM); 2126d14e2a8SJordan K. Hubbard } 2136d14e2a8SJordan K. Hubbard else { 2149c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo); 215af57ed9fSAtsushi Murai LcpClose(); 216af57ed9fSAtsushi Murai Cleanup(EX_TERM); 217af57ed9fSAtsushi Murai } 2186d14e2a8SJordan K. Hubbard } 219c3899f8dSAtsushi Murai 220c3899f8dSAtsushi Murai static void 221c3899f8dSAtsushi Murai TerminalCont() 222c3899f8dSAtsushi Murai { 223f5ff0f7cSBrian Somers pending_signal(SIGCONT, SIG_DFL); 224f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 225c3899f8dSAtsushi Murai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 226c3899f8dSAtsushi Murai } 227c3899f8dSAtsushi Murai 228c3899f8dSAtsushi Murai static void 229c3899f8dSAtsushi Murai TerminalStop(signo) 230c3899f8dSAtsushi Murai int signo; 231c3899f8dSAtsushi Murai { 232f5ff0f7cSBrian Somers pending_signal(SIGCONT, TerminalCont); 233c3899f8dSAtsushi Murai TtyOldMode(); 234f5ff0f7cSBrian Somers pending_signal(SIGTSTP, SIG_DFL); 235c3899f8dSAtsushi Murai kill(getpid(), signo); 236c3899f8dSAtsushi Murai } 237c3899f8dSAtsushi Murai 238c3899f8dSAtsushi Murai 239af57ed9fSAtsushi Murai void 240af57ed9fSAtsushi Murai Usage() 241af57ed9fSAtsushi Murai { 242680026d6SNate Williams fprintf(stderr, 2436d14e2a8SJordan K. Hubbard "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 244af57ed9fSAtsushi Murai exit(EX_START); 245af57ed9fSAtsushi Murai } 246af57ed9fSAtsushi Murai 247af57ed9fSAtsushi Murai void 248af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 249af57ed9fSAtsushi Murai { 250af57ed9fSAtsushi Murai int optc; 251af57ed9fSAtsushi Murai char *cp; 252af57ed9fSAtsushi Murai 253af57ed9fSAtsushi Murai optc = 0; 254af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 255af57ed9fSAtsushi Murai cp = *argv + 1; 256af57ed9fSAtsushi Murai if (strcmp(cp, "auto") == 0) 257af57ed9fSAtsushi Murai mode |= MODE_AUTO; 2586d14e2a8SJordan K. Hubbard else if (strcmp(cp, "background") == 0) 2596d14e2a8SJordan K. Hubbard mode |= MODE_BACKGROUND; 260af57ed9fSAtsushi Murai else if (strcmp(cp, "direct") == 0) 261af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 262af57ed9fSAtsushi Murai else if (strcmp(cp, "dedicated") == 0) 263af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 264680026d6SNate Williams else if (strcmp(cp, "ddial") == 0) 265680026d6SNate Williams mode |= MODE_DDIAL|MODE_AUTO; 266a9f484e5SJordan K. Hubbard else if (strcmp(cp, "alias") == 0) { 267a9f484e5SJordan K. Hubbard mode |= MODE_ALIAS; 268a9f484e5SJordan K. Hubbard optc--; /* this option isn't exclusive */ 269a9f484e5SJordan K. Hubbard } 270af57ed9fSAtsushi Murai else 271af57ed9fSAtsushi Murai Usage(); 272af57ed9fSAtsushi Murai optc++; 273af57ed9fSAtsushi Murai argv++; argc--; 274af57ed9fSAtsushi Murai } 275af57ed9fSAtsushi Murai if (argc > 1) { 276af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 277af57ed9fSAtsushi Murai exit(EX_START); 278af57ed9fSAtsushi Murai } 279af57ed9fSAtsushi Murai if (argc == 1) dstsystem = *argv; 280af57ed9fSAtsushi Murai 281af57ed9fSAtsushi Murai if (optc > 1) { 282af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 283af57ed9fSAtsushi Murai exit(EX_START); 284af57ed9fSAtsushi Murai } 285af57ed9fSAtsushi Murai } 286af57ed9fSAtsushi Murai 287af57ed9fSAtsushi Murai static void 288af57ed9fSAtsushi Murai Greetings() 289af57ed9fSAtsushi Murai { 290af57ed9fSAtsushi Murai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 291af57ed9fSAtsushi Murai fflush(stdout); 292af57ed9fSAtsushi Murai } 293af57ed9fSAtsushi Murai 294af57ed9fSAtsushi Murai void 295af57ed9fSAtsushi Murai main(argc, argv) 296af57ed9fSAtsushi Murai int argc; 297af57ed9fSAtsushi Murai char **argv; 298af57ed9fSAtsushi Murai { 299af57ed9fSAtsushi Murai int tunno; 300af57ed9fSAtsushi Murai 301af57ed9fSAtsushi Murai argc--; argv++; 302af57ed9fSAtsushi Murai 303af57ed9fSAtsushi Murai mode = MODE_INTER; /* default operation is interactive mode */ 304780700e5SAndrey A. Chernov netfd = server = modem = tun_in = -1; 305af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 306af57ed9fSAtsushi Murai Greetings(); 307af57ed9fSAtsushi Murai GetUid(); 308af57ed9fSAtsushi Murai IpcpDefAddress(); 309a9f484e5SJordan K. Hubbard InitAlias(); 310af57ed9fSAtsushi Murai 311af57ed9fSAtsushi Murai if (SelectSystem("default", CONFFILE) < 0) { 312af57ed9fSAtsushi Murai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 313af57ed9fSAtsushi Murai } 314af57ed9fSAtsushi Murai 315af57ed9fSAtsushi Murai if (LogOpen()) 316af57ed9fSAtsushi Murai exit(EX_START); 317af57ed9fSAtsushi Murai 31853c9f6c0SAtsushi Murai switch ( LocalAuthInit() ) { 31953c9f6c0SAtsushi Murai case NOT_FOUND: 32041db6564SAtsushi Murai fprintf(stderr,LAUTH_M1); 32141db6564SAtsushi Murai fprintf(stderr,LAUTH_M2); 32241db6564SAtsushi Murai fflush (stderr); 32341db6564SAtsushi Murai /* Fall down */ 32441db6564SAtsushi Murai case VALID: 32553c9f6c0SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 32653c9f6c0SAtsushi Murai break; 32753c9f6c0SAtsushi Murai default: 32853c9f6c0SAtsushi Murai break; 32953c9f6c0SAtsushi Murai } 33053c9f6c0SAtsushi Murai 331af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 332af57ed9fSAtsushi Murai perror("open_tun"); 333af57ed9fSAtsushi Murai exit(EX_START); 334af57ed9fSAtsushi Murai } 335af57ed9fSAtsushi Murai 3366d14e2a8SJordan K. Hubbard if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND)) 337af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 338af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 339af57ed9fSAtsushi Murai printf("Interactive mode\n"); 340780700e5SAndrey A. Chernov netfd = STDIN_FILENO; 341af57ed9fSAtsushi Murai } else if (mode & MODE_AUTO) { 342680026d6SNate Williams printf("Automatic Dialer mode\n"); 343af57ed9fSAtsushi Murai if (dstsystem == NULL) { 344680026d6SNate Williams fprintf(stderr, 345680026d6SNate Williams "Destination system must be specified in auto or ddial mode.\n"); 346af57ed9fSAtsushi Murai exit(EX_START); 347af57ed9fSAtsushi Murai } 3486d14e2a8SJordan K. Hubbard } else if (mode & MODE_BACKGROUND) { 3496d14e2a8SJordan K. Hubbard printf("Background mode\n"); 3506d14e2a8SJordan K. Hubbard if (dstsystem == NULL) { 3516d14e2a8SJordan K. Hubbard fprintf(stderr, "Destination system must be specified in background mode.\n"); 3526d14e2a8SJordan K. Hubbard exit(EX_START); 3536d14e2a8SJordan K. Hubbard } 354af57ed9fSAtsushi Murai } 355af57ed9fSAtsushi Murai 35653c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 357af57ed9fSAtsushi Murai 358c6c740beSBrian Somers pending_signal(SIGHUP, LogReOpen); 359f5ff0f7cSBrian Somers pending_signal(SIGTERM, CloseSession); 360f5ff0f7cSBrian Somers pending_signal(SIGINT, CloseSession); 361f5ff0f7cSBrian Somers pending_signal(SIGQUIT, CloseSession); 36253c9f6c0SAtsushi Murai #ifdef SIGSEGV 363d7f5ee41SAndrey A. Chernov signal(SIGSEGV, Hangup); 36453c9f6c0SAtsushi Murai #endif 36553c9f6c0SAtsushi Murai #ifdef SIGPIPE 366e0d3e233SAndrey A. Chernov signal(SIGPIPE, SIG_IGN); 36753c9f6c0SAtsushi Murai #endif 36853c9f6c0SAtsushi Murai #ifdef SIGALRM 369f5ff0f7cSBrian Somers pending_signal(SIGALRM, SIG_IGN); 37053c9f6c0SAtsushi Murai #endif 371c3899f8dSAtsushi Murai if(mode & MODE_INTER) 372c3899f8dSAtsushi Murai { 373c3899f8dSAtsushi Murai #ifdef SIGTSTP 374f5ff0f7cSBrian Somers pending_signal(SIGTSTP, TerminalStop); 375c3899f8dSAtsushi Murai #endif 376c3899f8dSAtsushi Murai #ifdef SIGTTIN 377f5ff0f7cSBrian Somers pending_signal(SIGTTIN, TerminalStop); 378c3899f8dSAtsushi Murai #endif 379c3899f8dSAtsushi Murai #ifdef SIGTTOU 380f5ff0f7cSBrian Somers pending_signal(SIGTTOU, SIG_IGN); 381c3899f8dSAtsushi Murai #endif 382c3899f8dSAtsushi Murai } 383af57ed9fSAtsushi Murai 384af57ed9fSAtsushi Murai if (dstsystem) { 385af57ed9fSAtsushi Murai if (SelectSystem(dstsystem, CONFFILE) < 0) { 386af57ed9fSAtsushi Murai fprintf(stderr, "Destination system not found in conf file.\n"); 387af57ed9fSAtsushi Murai Cleanup(EX_START); 388af57ed9fSAtsushi Murai } 389af57ed9fSAtsushi Murai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 390680026d6SNate Williams fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n"); 391af57ed9fSAtsushi Murai Cleanup(EX_START); 392af57ed9fSAtsushi Murai } 393af57ed9fSAtsushi Murai } 394af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) 395af57ed9fSAtsushi Murai printf("Packet mode enabled.\n"); 396af57ed9fSAtsushi Murai 397af57ed9fSAtsushi Murai #ifdef notdef 398af57ed9fSAtsushi Murai if (mode & MODE_AUTO) { 399af57ed9fSAtsushi Murai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 400af57ed9fSAtsushi Murai } 401af57ed9fSAtsushi Murai #endif 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 } 429af57ed9fSAtsushi Murai listen(server, 5); 4306d14e2a8SJordan K. Hubbard } 431af57ed9fSAtsushi Murai 432af57ed9fSAtsushi Murai DupLog(); 433af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 434a9c6b5dfSAtsushi Murai int fd; 435a9c6b5dfSAtsushi Murai char pid[32]; 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]); 4616d14e2a8SJordan K. Hubbard 4626d14e2a8SJordan K. Hubbard snprintf(pid_filename, sizeof (pid_filename), "%s/ppp.tun%d.pid", 4636d14e2a8SJordan K. Hubbard _PATH_VARRUN, tunno); 464a9c6b5dfSAtsushi Murai unlink(pid_filename); 46599c02d39SWarner Losh snprintf(pid, sizeof(pid), "%d\n", (int)getpid()); 466a9c6b5dfSAtsushi Murai 467a9c6b5dfSAtsushi Murai if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1) 468a9c6b5dfSAtsushi Murai { 469a9c6b5dfSAtsushi Murai write(fd, pid, strlen(pid)); 470a9c6b5dfSAtsushi Murai close(fd); 471a9c6b5dfSAtsushi Murai } 472af57ed9fSAtsushi Murai } 473780700e5SAndrey A. Chernov if (server >= 0) 4749c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port); 475af57ed9fSAtsushi Murai #ifdef DOTTYINIT 47653c9f6c0SAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 477af57ed9fSAtsushi Murai #else 478af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) { 479af57ed9fSAtsushi Murai #endif 480af57ed9fSAtsushi Murai TtyInit(); 481af57ed9fSAtsushi Murai } else { 482d91680eaSAndrey A. Chernov int fd; 483d91680eaSAndrey A. Chernov 484af57ed9fSAtsushi Murai setsid(); /* detach control tty */ 485d91680eaSAndrey A. Chernov if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 486d91680eaSAndrey A. Chernov (void)dup2(fd, STDIN_FILENO); 487d91680eaSAndrey A. Chernov (void)dup2(fd, STDOUT_FILENO); 488d91680eaSAndrey A. Chernov (void)dup2(fd, STDERR_FILENO); 489d91680eaSAndrey A. Chernov if (fd > 2) 490d91680eaSAndrey A. Chernov (void)close (fd); 491d91680eaSAndrey A. Chernov } 492af57ed9fSAtsushi Murai } 493af57ed9fSAtsushi Murai } else { 494af57ed9fSAtsushi Murai TtyInit(); 495c3899f8dSAtsushi Murai TtyCommandMode(1); 496af57ed9fSAtsushi Murai } 4979c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "PPP Started.\n"); 498af57ed9fSAtsushi Murai 499af57ed9fSAtsushi Murai 500af57ed9fSAtsushi Murai do 501af57ed9fSAtsushi Murai DoLoop(); 502af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 503af57ed9fSAtsushi Murai 504af57ed9fSAtsushi Murai Cleanup(EX_DONE); 505af57ed9fSAtsushi Murai } 506af57ed9fSAtsushi Murai 507af57ed9fSAtsushi Murai /* 5086d14e2a8SJordan K. Hubbard * Turn into packet mode, where we speak PPP. 509af57ed9fSAtsushi Murai */ 510af57ed9fSAtsushi Murai void 511af57ed9fSAtsushi Murai PacketMode() 512af57ed9fSAtsushi Murai { 513af57ed9fSAtsushi Murai if (RawModem(modem) < 0) { 514af57ed9fSAtsushi Murai fprintf(stderr, "Not connected.\r\n"); 515af57ed9fSAtsushi Murai return; 516af57ed9fSAtsushi Murai } 517af57ed9fSAtsushi Murai 518af57ed9fSAtsushi Murai AsyncInit(); 519af57ed9fSAtsushi Murai VjInit(); 520af57ed9fSAtsushi Murai LcpInit(); 521af57ed9fSAtsushi Murai IpcpInit(); 522af57ed9fSAtsushi Murai CcpInit(); 523af57ed9fSAtsushi Murai LcpUp(); 524af57ed9fSAtsushi Murai 525af57ed9fSAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 526af57ed9fSAtsushi Murai LcpOpen(OPEN_ACTIVE); 527af57ed9fSAtsushi Murai else 528af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 529af57ed9fSAtsushi Murai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 530c3899f8dSAtsushi Murai TtyCommandMode(1); 531af57ed9fSAtsushi Murai fprintf(stderr, "Packet mode.\r\n"); 532b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 533af57ed9fSAtsushi Murai } 534af57ed9fSAtsushi Murai } 535af57ed9fSAtsushi Murai 536af57ed9fSAtsushi Murai static void 537af57ed9fSAtsushi Murai ShowHelp() 538af57ed9fSAtsushi Murai { 539c3899f8dSAtsushi Murai fprintf(stderr, "The following commands are available:\r\n"); 540af57ed9fSAtsushi Murai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 5411dff3fc5SAndrey A. Chernov fprintf(stderr, " ~-\tDecrease log level\r\n"); 5421dff3fc5SAndrey A. Chernov fprintf(stderr, " ~+\tIncrease log level\r\n"); 543af57ed9fSAtsushi Murai fprintf(stderr, " ~.\tTerminate program\r\n"); 5441dff3fc5SAndrey A. Chernov fprintf(stderr, " ~?\tThis help\r\n"); 545af57ed9fSAtsushi Murai } 546af57ed9fSAtsushi Murai 547af57ed9fSAtsushi Murai static void 548af57ed9fSAtsushi Murai ReadTty() 549af57ed9fSAtsushi Murai { 550af57ed9fSAtsushi Murai int n; 551af57ed9fSAtsushi Murai char ch; 552af57ed9fSAtsushi Murai static int ttystate; 553af57ed9fSAtsushi Murai #define MAXLINESIZE 200 554af57ed9fSAtsushi Murai char linebuff[MAXLINESIZE]; 555af57ed9fSAtsushi Murai 556af57ed9fSAtsushi Murai #ifdef DEBUG 557af57ed9fSAtsushi Murai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 558af57ed9fSAtsushi Murai #endif 559af57ed9fSAtsushi Murai if (!TermMode) { 560af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff)-1); 561b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 56253c9f6c0SAtsushi Murai if (n > 0) { 563af57ed9fSAtsushi Murai DecodeCommand(linebuff, n, 1); 56453c9f6c0SAtsushi Murai } else { 565e0d3e233SAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "client connection closed.\n"); 566e0d3e233SAndrey A. Chernov VarLocalAuth = LOCAL_NO_AUTH; 567af57ed9fSAtsushi Murai close(netfd); 568e0d3e233SAndrey A. Chernov close(1); 569e0d3e233SAndrey A. Chernov dup2(2, 1); /* Have to have something here or the modem will be 1 */ 570af57ed9fSAtsushi Murai netfd = -1; 571af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 572af57ed9fSAtsushi Murai } 573af57ed9fSAtsushi Murai return; 574af57ed9fSAtsushi Murai } 575af57ed9fSAtsushi Murai 576af57ed9fSAtsushi Murai /* 577af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 578af57ed9fSAtsushi Murai */ 579af57ed9fSAtsushi Murai n = read(0, &ch, 1); 580af57ed9fSAtsushi Murai #ifdef DEBUG 581af57ed9fSAtsushi Murai logprintf("got %d bytes\n", n); 582af57ed9fSAtsushi Murai #endif 583af57ed9fSAtsushi Murai 584af57ed9fSAtsushi Murai if (n > 0) { 585af57ed9fSAtsushi Murai switch (ttystate) { 586af57ed9fSAtsushi Murai case 0: 587af57ed9fSAtsushi Murai if (ch == '~') 588af57ed9fSAtsushi Murai ttystate++; 589af57ed9fSAtsushi Murai else 590af57ed9fSAtsushi Murai write(modem, &ch, n); 591af57ed9fSAtsushi Murai break; 592af57ed9fSAtsushi Murai case 1: 593af57ed9fSAtsushi Murai switch (ch) { 594af57ed9fSAtsushi Murai case '?': 595af57ed9fSAtsushi Murai ShowHelp(); 596af57ed9fSAtsushi Murai break; 597af57ed9fSAtsushi Murai case '-': 598af57ed9fSAtsushi Murai if (loglevel > 0) { 599af57ed9fSAtsushi Murai loglevel--; 600af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 601af57ed9fSAtsushi Murai } 602af57ed9fSAtsushi Murai break; 603af57ed9fSAtsushi Murai case '+': 604af57ed9fSAtsushi Murai loglevel++; 605af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 606af57ed9fSAtsushi Murai break; 607af57ed9fSAtsushi Murai #ifdef DEBUG 608af57ed9fSAtsushi Murai case 'm': 609af57ed9fSAtsushi Murai ShowMemMap(); 610af57ed9fSAtsushi Murai break; 611af57ed9fSAtsushi Murai #endif 612af57ed9fSAtsushi Murai case 'p': 613af57ed9fSAtsushi Murai /* 614af57ed9fSAtsushi Murai * XXX: Should check carrier. 615af57ed9fSAtsushi Murai */ 616af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 617af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 618af57ed9fSAtsushi Murai PacketMode(); 619af57ed9fSAtsushi Murai } 620af57ed9fSAtsushi Murai break; 621af57ed9fSAtsushi Murai #ifdef DEBUG 622af57ed9fSAtsushi Murai case 't': 623af57ed9fSAtsushi Murai ShowTimers(); 624af57ed9fSAtsushi Murai break; 625af57ed9fSAtsushi Murai #endif 626af57ed9fSAtsushi Murai case '.': 627af57ed9fSAtsushi Murai TermMode = 1; 628c3899f8dSAtsushi Murai TtyCommandMode(1); 629af57ed9fSAtsushi Murai break; 630af57ed9fSAtsushi Murai default: 631af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 632af57ed9fSAtsushi Murai fprintf(stderr, "err in write.\r\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); 6819c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "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 69843ea9d19SBrian Somers LogPrintf(LOG_PHASE_BIT, "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; 720c3899f8dSAtsushi Murai pid_t pgroup; 721c3899f8dSAtsushi Murai 722c3899f8dSAtsushi Murai pgroup = getpgrp(); 723af57ed9fSAtsushi Murai 7246e4959f0SBrian Somers if (mode & (MODE_DIRECT|MODE_BACKGROUND)) { 725af57ed9fSAtsushi Murai modem = OpenModem(mode); 7269c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n"); 727b0cdb3ceSJordan K. Hubbard fflush(stderr); 728af57ed9fSAtsushi Murai PacketMode(); 729af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 730780700e5SAndrey A. Chernov if (modem < 0) 731af57ed9fSAtsushi Murai modem = OpenModem(mode); 732af57ed9fSAtsushi Murai } 733af57ed9fSAtsushi Murai 734af57ed9fSAtsushi Murai fflush(stdout); 735af57ed9fSAtsushi Murai 73684b8a6ebSAtsushi Murai timeout.tv_sec = 0; 737af57ed9fSAtsushi Murai timeout.tv_usec = 0; 73807030d97SBrian Somers lostCarrier = 0; 739af57ed9fSAtsushi Murai 7406e4959f0SBrian Somers if (mode & MODE_BACKGROUND) 7416e4959f0SBrian Somers dial_up = TRUE; /* Bring the line up */ 7426e4959f0SBrian Somers else 74384b8a6ebSAtsushi Murai dial_up = FALSE; /* XXXX */ 744a9c6b5dfSAtsushi Murai tries = 0; 745af57ed9fSAtsushi Murai for (;;) { 746780700e5SAndrey A. Chernov nfds = 0; 747af57ed9fSAtsushi Murai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 74884b8a6ebSAtsushi Murai 74984b8a6ebSAtsushi Murai /* 750680026d6SNate Williams * If the link is down and we're in DDIAL mode, bring it back 751680026d6SNate Williams * up. 752680026d6SNate Williams */ 753680026d6SNate Williams if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 754680026d6SNate Williams dial_up = TRUE; 755680026d6SNate Williams 756680026d6SNate Williams /* 75707030d97SBrian Somers * If we lost carrier and want to re-establish the connection 75807030d97SBrian Somers * due to the "set reconnect" value, we'd better bring the line 75907030d97SBrian Somers * back up now. 76007030d97SBrian Somers */ 76107030d97SBrian Somers if (LcpFsm.state <= ST_CLOSED && dial_up != TRUE 76207030d97SBrian Somers && lostCarrier && lostCarrier <= VarReconnectTries) { 76307030d97SBrian Somers LogPrintf(LOG_PHASE_BIT, "Connection lost, re-establish (%d/%d)\n", 76407030d97SBrian Somers lostCarrier, VarReconnectTries); 76507030d97SBrian Somers StartRedialTimer(VarReconnectTimer); 76607030d97SBrian Somers dial_up = TRUE; 76707030d97SBrian Somers } 76807030d97SBrian Somers 76907030d97SBrian Somers /* 77084b8a6ebSAtsushi Murai * If Ip packet for output is enqueued and require dial up, 77184b8a6ebSAtsushi Murai * Just do it! 77284b8a6ebSAtsushi Murai */ 77307030d97SBrian Somers if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { 77484b8a6ebSAtsushi Murai #ifdef DEBUG 77584b8a6ebSAtsushi Murai logprintf("going to dial: modem = %d\n", modem); 77684b8a6ebSAtsushi Murai #endif 77784b8a6ebSAtsushi Murai modem = OpenModem(mode); 77884b8a6ebSAtsushi Murai if (modem < 0) { 77943ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 78084b8a6ebSAtsushi Murai } else { 781c0139fb2SBrian Somers tries++; /* Tries are per number, not per list of numbers. */ 782c0139fb2SBrian Somers if (VarDialTries) 783c0139fb2SBrian Somers LogPrintf(LOG_CHAT_BIT, "Dial attempt %u of %d\n", tries, 784c0139fb2SBrian Somers VarDialTries); 785c0139fb2SBrian Somers else 7869c749ffbSPoul-Henning Kamp LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries); 78784b8a6ebSAtsushi Murai if (DialModem()) { 78884b8a6ebSAtsushi Murai sleep(1); /* little pause to allow peer starts */ 78984b8a6ebSAtsushi Murai ModemTimeout(); 79084b8a6ebSAtsushi Murai PacketMode(); 79184b8a6ebSAtsushi Murai dial_up = FALSE; 792a9c6b5dfSAtsushi Murai tries = 0; 79384b8a6ebSAtsushi Murai } else { 79484b8a6ebSAtsushi Murai CloseModem(); 7954ed9958fSBrian Somers if (mode & MODE_BACKGROUND) { 7964ed9958fSBrian Somers if (VarNextPhone == NULL) 7974ed9958fSBrian Somers Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 7984ed9958fSBrian Somers else 79943ea9d19SBrian Somers /* Try all numbers in background mode */ 80043ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 8014ed9958fSBrian Somers } else if (VarDialTries && tries >= VarDialTries) { 802c0139fb2SBrian Somers /* I give up ! Can't get through :( */ 80343ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 804a9c6b5dfSAtsushi Murai dial_up = FALSE; 805a9c6b5dfSAtsushi Murai tries = 0; 806c0139fb2SBrian Somers } else if (VarNextPhone == NULL) 807c0139fb2SBrian Somers /* Dial failed. Keep quite during redial wait period. */ 80843ea9d19SBrian Somers StartRedialTimer(VarRedialTimeout); 809c0139fb2SBrian Somers else 81043ea9d19SBrian Somers StartRedialTimer(VarRedialNextTimeout); 81184b8a6ebSAtsushi Murai } 81284b8a6ebSAtsushi Murai } 81384b8a6ebSAtsushi Murai } 81460e218e4SAtsushi Murai qlen = ModemQlen(); 81576bd0c0aSDoug Rabson 81676bd0c0aSDoug Rabson if (qlen == 0) { 81776bd0c0aSDoug Rabson IpStartOutput(); 81876bd0c0aSDoug Rabson qlen = ModemQlen(); 81976bd0c0aSDoug Rabson } 82076bd0c0aSDoug Rabson 821780700e5SAndrey A. Chernov if (modem >= 0) { 822780700e5SAndrey A. Chernov if (modem + 1 > nfds) 823780700e5SAndrey A. Chernov nfds = modem + 1; 82484b8a6ebSAtsushi Murai FD_SET(modem, &rfds); 82584b8a6ebSAtsushi Murai FD_SET(modem, &efds); 82660e218e4SAtsushi Murai if (qlen > 0) { 82784b8a6ebSAtsushi Murai FD_SET(modem, &wfds); 82884b8a6ebSAtsushi Murai } 82984b8a6ebSAtsushi Murai } 830780700e5SAndrey A. Chernov if (server >= 0) { 831780700e5SAndrey A. Chernov if (server + 1 > nfds) 832780700e5SAndrey A. Chernov nfds = server + 1; 833780700e5SAndrey A. Chernov FD_SET(server, &rfds); 834780700e5SAndrey A. Chernov } 835af57ed9fSAtsushi Murai 836af57ed9fSAtsushi Murai /* *** IMPORTANT *** 837af57ed9fSAtsushi Murai * 838af57ed9fSAtsushi Murai * CPU is serviced every TICKUNIT micro seconds. 839af57ed9fSAtsushi Murai * This value must be chosen with great care. If this values is 840af57ed9fSAtsushi Murai * too big, it results loss of characters from modem and poor responce. 841af57ed9fSAtsushi Murai * If this values is too small, ppp process eats many CPU time. 842af57ed9fSAtsushi Murai */ 84353c9f6c0SAtsushi Murai #ifndef SIGALRM 844af57ed9fSAtsushi Murai usleep(TICKUNIT); 845af57ed9fSAtsushi Murai TimerService(); 846f5ff0f7cSBrian Somers #else 847f5ff0f7cSBrian Somers handle_signals(); 84853c9f6c0SAtsushi Murai #endif 84968d2b4d6SBruce Evans 85068d2b4d6SBruce Evans /* If there are aren't many packets queued, look for some more. */ 851780700e5SAndrey A. Chernov if (qlen < 20 && tun_in >= 0) { 852780700e5SAndrey A. Chernov if (tun_in + 1 > nfds) 853780700e5SAndrey A. Chernov nfds = tun_in + 1; 85484b8a6ebSAtsushi Murai FD_SET(tun_in, &rfds); 855780700e5SAndrey A. Chernov } 85668d2b4d6SBruce Evans 857780700e5SAndrey A. Chernov if (netfd >= 0) { 858780700e5SAndrey A. Chernov if (netfd + 1 > nfds) 859780700e5SAndrey A. Chernov nfds = netfd + 1; 860af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 861af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 862af57ed9fSAtsushi Murai } 86384b8a6ebSAtsushi Murai 86453c9f6c0SAtsushi Murai #ifndef SIGALRM 865af57ed9fSAtsushi Murai /* 86684b8a6ebSAtsushi Murai * Normally, select() will not block because modem is writable. 86784b8a6ebSAtsushi Murai * In AUTO mode, select will block until we find packet from tun 868af57ed9fSAtsushi Murai */ 869af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 870780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 87153c9f6c0SAtsushi Murai #else 87284b8a6ebSAtsushi Murai /* 87384b8a6ebSAtsushi Murai * When SIGALRM timer is running, a select function will be 87484b8a6ebSAtsushi Murai * return -1 and EINTR after a Time Service signal hundler 875a9c6b5dfSAtsushi Murai * is done. If the redial timer is not running and we are 876a9c6b5dfSAtsushi Murai * trying to dial, poll with a 0 value timer. 87784b8a6ebSAtsushi Murai */ 878a9c6b5dfSAtsushi Murai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 879780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 88053c9f6c0SAtsushi Murai #endif 8816b0b88d8SBrian Somers 882af57ed9fSAtsushi Murai if ( i == 0 ) { 883af57ed9fSAtsushi Murai continue; 884af57ed9fSAtsushi Murai } 88553c9f6c0SAtsushi Murai 886534fe541SBrian Somers if ( i < 0 ) { 887534fe541SBrian Somers if ( errno == EINTR ) { 888f5ff0f7cSBrian Somers handle_signals(); 889f5ff0f7cSBrian Somers continue; 89084b8a6ebSAtsushi Murai } 891af57ed9fSAtsushi Murai perror("select"); 892af57ed9fSAtsushi Murai break; 893af57ed9fSAtsushi Murai } 89484b8a6ebSAtsushi Murai 895780700e5SAndrey A. Chernov if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 896af57ed9fSAtsushi Murai logprintf("Exception detected.\n"); 897af57ed9fSAtsushi Murai break; 898af57ed9fSAtsushi Murai } 899af57ed9fSAtsushi Murai 900780700e5SAndrey A. Chernov if (server >= 0 && FD_ISSET(server, &rfds)) { 901e0d3e233SAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "connected to client.\n"); 902af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 903e0d3e233SAndrey A. Chernov if (wfd < 0) { 904e0d3e233SAndrey A. Chernov perror("accept"); 905e0d3e233SAndrey A. Chernov continue; 906e0d3e233SAndrey A. Chernov } 907780700e5SAndrey A. Chernov if (netfd >= 0) { 908af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 909af57ed9fSAtsushi Murai close(wfd); 910af57ed9fSAtsushi Murai continue; 911af57ed9fSAtsushi Murai } else 912af57ed9fSAtsushi Murai netfd = wfd; 913e0d3e233SAndrey A. Chernov if (dup2(netfd, 1) < 0) { 914af57ed9fSAtsushi Murai perror("dup2"); 915e0d3e233SAndrey A. Chernov close(netfd); 916e0d3e233SAndrey A. Chernov netfd = -1; 917e0d3e233SAndrey A. Chernov continue; 918e0d3e233SAndrey A. Chernov } 919af57ed9fSAtsushi Murai mode |= MODE_INTER; 920af57ed9fSAtsushi Murai Greetings(); 92141db6564SAtsushi Murai switch ( LocalAuthInit() ) { 92241db6564SAtsushi Murai case NOT_FOUND: 92341db6564SAtsushi Murai fprintf(stdout,LAUTH_M1); 92441db6564SAtsushi Murai fprintf(stdout,LAUTH_M2); 92541db6564SAtsushi Murai fflush(stdout); 92641db6564SAtsushi Murai /* Fall down */ 92741db6564SAtsushi Murai case VALID: 92841db6564SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 92941db6564SAtsushi Murai break; 93041db6564SAtsushi Murai default: 93141db6564SAtsushi Murai break; 93241db6564SAtsushi Murai } 933af57ed9fSAtsushi Murai (void) IsInteractive(); 934af57ed9fSAtsushi Murai Prompt(0); 935af57ed9fSAtsushi Murai } 936af57ed9fSAtsushi Murai 937780700e5SAndrey A. Chernov if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 938f1884650SAtsushi Murai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 939af57ed9fSAtsushi Murai /* something to read from tty */ 940af57ed9fSAtsushi Murai ReadTty(); 941af57ed9fSAtsushi Murai } 942780700e5SAndrey A. Chernov if (modem >= 0) { 943af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 944af57ed9fSAtsushi Murai ModemStartOutput(modem); 945af57ed9fSAtsushi Murai } 946af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 94753c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 94853c9f6c0SAtsushi Murai usleep(10000); 949af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 950af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 951af57ed9fSAtsushi Murai DownConnection(); 952af57ed9fSAtsushi Murai } else 953af57ed9fSAtsushi Murai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 954af57ed9fSAtsushi Murai 955af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 956af57ed9fSAtsushi Murai /* 957af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 958af57ed9fSAtsushi Murai */ 959af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 960af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 961af57ed9fSAtsushi Murai if (cp) { 962af57ed9fSAtsushi Murai /* 963af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 964af57ed9fSAtsushi Murai */ 965af57ed9fSAtsushi Murai if (cp != rbuff) { 966af57ed9fSAtsushi Murai write(1, rbuff, cp - rbuff); 967af57ed9fSAtsushi Murai write(1, "\r\n", 2); 968af57ed9fSAtsushi Murai } 969af57ed9fSAtsushi Murai PacketMode(); 970af57ed9fSAtsushi Murai #ifdef notdef 971af57ed9fSAtsushi Murai AsyncInput(cp, n - (cp - rbuff)); 972af57ed9fSAtsushi Murai #endif 973af57ed9fSAtsushi Murai } else 974af57ed9fSAtsushi Murai write(1, rbuff, n); 975af57ed9fSAtsushi Murai } 976af57ed9fSAtsushi Murai } else { 977af57ed9fSAtsushi Murai if (n > 0) 978af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 979af57ed9fSAtsushi Murai #ifdef notdef 980af57ed9fSAtsushi Murai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 981af57ed9fSAtsushi Murai #endif 982af57ed9fSAtsushi Murai } 983af57ed9fSAtsushi Murai } 984af57ed9fSAtsushi Murai } 98584b8a6ebSAtsushi Murai 986780700e5SAndrey A. Chernov if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 987af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 988af57ed9fSAtsushi Murai if (n < 0) { 989af57ed9fSAtsushi Murai perror("read from tun"); 990af57ed9fSAtsushi Murai continue; 991af57ed9fSAtsushi Murai } 992af57ed9fSAtsushi Murai /* 993af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 994af57ed9fSAtsushi Murai * device until IPCP is opened. 995af57ed9fSAtsushi Murai */ 996af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 99784b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_DIAL); 998af57ed9fSAtsushi Murai if (pri >= 0) { 999a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10003b92d2deSNate Williams PacketAliasOut((struct ip *)rbuff); 1001a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 1002a9f484e5SJordan K. Hubbard } 1003af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 100484b8a6ebSAtsushi Murai dial_up = TRUE; /* XXX */ 1005af57ed9fSAtsushi Murai } 1006af57ed9fSAtsushi Murai continue; 1007af57ed9fSAtsushi Murai } 100884b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_OUT); 1009a9f484e5SJordan K. Hubbard if (pri >= 0) { 1010a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 10113b92d2deSNate Williams PacketAliasOut((struct ip *)rbuff); 1012a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 1013a9f484e5SJordan K. Hubbard } 1014af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 1015af57ed9fSAtsushi Murai } 1016af57ed9fSAtsushi Murai } 1017a9f484e5SJordan K. Hubbard } 1018af57ed9fSAtsushi Murai logprintf("job done.\n"); 1019af57ed9fSAtsushi Murai } 1020