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 * 20780700e5SAndrey A. Chernov * $Id: main.c,v 1.36 1997/03/09 20:03:39 ache 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" 5253c9f6c0SAtsushi Murai 5341db6564SAtsushi Murai #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 54bea0b497SSatoshi Asami #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n" 5541db6564SAtsushi Murai 5653c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 5753c9f6c0SAtsushi Murai #ifdef O_NDELAY 5853c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 5953c9f6c0SAtsushi Murai #endif 6053c9f6c0SAtsushi Murai #endif 61af57ed9fSAtsushi Murai 62af57ed9fSAtsushi Murai extern void VjInit(), AsyncInit(); 63af57ed9fSAtsushi Murai extern void AsyncInput(), IpOutput(); 64af57ed9fSAtsushi Murai extern int SelectSystem(); 65af57ed9fSAtsushi Murai 66af57ed9fSAtsushi Murai extern void DecodeCommand(), Prompt(); 67b0cdb3ceSJordan K. Hubbard extern int aft_cmd; 68af57ed9fSAtsushi Murai extern int IsInteractive(); 69af57ed9fSAtsushi Murai extern struct in_addr ifnetmask; 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; 79a9c6b5dfSAtsushi Murai char pid_filename[128]; 80af57ed9fSAtsushi Murai 81af57ed9fSAtsushi Murai static void 82af57ed9fSAtsushi Murai TtyInit() 83af57ed9fSAtsushi Murai { 84af57ed9fSAtsushi Murai struct termios newtio; 85af57ed9fSAtsushi Murai int stat; 86af57ed9fSAtsushi Murai 87af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 88af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 89af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 90af57ed9fSAtsushi Murai newtio = oldtio; 91af57ed9fSAtsushi Murai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 92af57ed9fSAtsushi Murai newtio.c_iflag = 0; 93af57ed9fSAtsushi Murai newtio.c_oflag &= ~OPOST; 94af57ed9fSAtsushi Murai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 95af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 96af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 97af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 98af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 9953c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 100af57ed9fSAtsushi Murai comtio = newtio; 101af57ed9fSAtsushi Murai } 102af57ed9fSAtsushi Murai 103af57ed9fSAtsushi Murai /* 104af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 105af57ed9fSAtsushi Murai */ 106c3899f8dSAtsushi Murai void 107c3899f8dSAtsushi Murai TtyCommandMode(prompt) 108c3899f8dSAtsushi Murai int prompt; 109af57ed9fSAtsushi Murai { 110af57ed9fSAtsushi Murai struct termios newtio; 111af57ed9fSAtsushi Murai int stat; 112af57ed9fSAtsushi Murai 113af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 114af57ed9fSAtsushi Murai return; 11553c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 116c3899f8dSAtsushi Murai newtio.c_lflag |= (ECHO|ISIG|ICANON); 117af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 118af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 11953c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 120af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 121af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 122af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 123af57ed9fSAtsushi Murai TermMode = 0; 124c3899f8dSAtsushi Murai if(prompt) Prompt(0); 125af57ed9fSAtsushi Murai } 126af57ed9fSAtsushi Murai 127af57ed9fSAtsushi Murai /* 128af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 129af57ed9fSAtsushi Murai */ 130af57ed9fSAtsushi Murai void 131af57ed9fSAtsushi Murai TtyTermMode() 132af57ed9fSAtsushi Murai { 133af57ed9fSAtsushi Murai int stat; 134af57ed9fSAtsushi Murai 13553c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 136af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 137af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 138af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 139af57ed9fSAtsushi Murai TermMode = 1; 140af57ed9fSAtsushi Murai } 141af57ed9fSAtsushi Murai 142af57ed9fSAtsushi Murai void 143c3899f8dSAtsushi Murai TtyOldMode() 144c3899f8dSAtsushi Murai { 145c3899f8dSAtsushi Murai int stat; 146c3899f8dSAtsushi Murai 147c3899f8dSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 148c3899f8dSAtsushi Murai stat &= ~O_NONBLOCK; 149c3899f8dSAtsushi Murai fcntl(0, F_SETFL, stat); 150c3899f8dSAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 151c3899f8dSAtsushi Murai } 152c3899f8dSAtsushi Murai 153c3899f8dSAtsushi Murai void 154af57ed9fSAtsushi Murai Cleanup(excode) 155af57ed9fSAtsushi Murai int excode; 156af57ed9fSAtsushi Murai { 157af57ed9fSAtsushi Murai 158af57ed9fSAtsushi Murai OsLinkdown(); 159af57ed9fSAtsushi Murai OsCloseLink(1); 160af57ed9fSAtsushi Murai sleep(1); 161a9c6b5dfSAtsushi Murai if (mode & MODE_AUTO) { 162af57ed9fSAtsushi Murai DeleteIfRoutes(1); 1636d14e2a8SJordan K. Hubbard } 1646d14e2a8SJordan K. Hubbard if (mode & (MODE_AUTO | MODE_BACKGROUND)) { 165a9c6b5dfSAtsushi Murai unlink(pid_filename); 166a9c6b5dfSAtsushi Murai } 167af57ed9fSAtsushi Murai OsInterfaceDown(1); 1689c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "PPP Terminated.\n"); 169af57ed9fSAtsushi Murai LogClose(); 170780700e5SAndrey A. Chernov if (server >= 0) { 171af57ed9fSAtsushi Murai close(server); 172780700e5SAndrey A. Chernov server = -1; 173780700e5SAndrey A. Chernov } 174c3899f8dSAtsushi Murai TtyOldMode(); 175af57ed9fSAtsushi Murai 176af57ed9fSAtsushi Murai exit(excode); 177af57ed9fSAtsushi Murai } 178af57ed9fSAtsushi Murai 179af57ed9fSAtsushi Murai static void 1807a8ef19eSAndrey A. Chernov Hangup(signo) 1817a8ef19eSAndrey A. Chernov int signo; 182af57ed9fSAtsushi Murai { 183af83607cSAndrey A. Chernov if (signo == SIGSEGV) { 184af83607cSAndrey A. Chernov LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo); 185af83607cSAndrey A. Chernov LogClose(); 186af83607cSAndrey A. Chernov abort(); 187af83607cSAndrey A. Chernov } 1886d14e2a8SJordan K. Hubbard if (BGPid) { 1896d14e2a8SJordan K. Hubbard kill (BGPid, SIGHUP); 1906d14e2a8SJordan K. Hubbard exit (EX_HANGUP); 1916d14e2a8SJordan K. Hubbard } 1926d14e2a8SJordan K. Hubbard else { 1939c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo); 194af57ed9fSAtsushi Murai Cleanup(EX_HANGUP); 195af57ed9fSAtsushi Murai } 1966d14e2a8SJordan K. Hubbard } 197af57ed9fSAtsushi Murai 198af57ed9fSAtsushi Murai static void 1997a8ef19eSAndrey A. Chernov CloseSession(signo) 2007a8ef19eSAndrey A. Chernov int signo; 201af57ed9fSAtsushi Murai { 2026d14e2a8SJordan K. Hubbard if (BGPid) { 2036d14e2a8SJordan K. Hubbard kill (BGPid, SIGINT); 2046d14e2a8SJordan K. Hubbard exit (EX_TERM); 2056d14e2a8SJordan K. Hubbard } 2066d14e2a8SJordan K. Hubbard else { 2079c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo); 208af57ed9fSAtsushi Murai LcpClose(); 209af57ed9fSAtsushi Murai Cleanup(EX_TERM); 210af57ed9fSAtsushi Murai } 2116d14e2a8SJordan K. Hubbard } 212c3899f8dSAtsushi Murai 213c3899f8dSAtsushi Murai static void 214c3899f8dSAtsushi Murai TerminalCont() 215c3899f8dSAtsushi Murai { 216bbea88d0SAndrey A. Chernov (void)signal(SIGCONT, SIG_DFL); 217bbea88d0SAndrey A. Chernov (void)signal(SIGTSTP, TerminalStop); 218c3899f8dSAtsushi Murai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 219c3899f8dSAtsushi Murai } 220c3899f8dSAtsushi Murai 221c3899f8dSAtsushi Murai static void 222c3899f8dSAtsushi Murai TerminalStop(signo) 223c3899f8dSAtsushi Murai int signo; 224c3899f8dSAtsushi Murai { 225bbea88d0SAndrey A. Chernov (void)signal(SIGCONT, TerminalCont); 226c3899f8dSAtsushi Murai TtyOldMode(); 227bbea88d0SAndrey A. Chernov signal(SIGTSTP, SIG_DFL); 228c3899f8dSAtsushi Murai kill(getpid(), signo); 229c3899f8dSAtsushi Murai } 230c3899f8dSAtsushi Murai 231c3899f8dSAtsushi Murai 232af57ed9fSAtsushi Murai void 233af57ed9fSAtsushi Murai Usage() 234af57ed9fSAtsushi Murai { 235680026d6SNate Williams fprintf(stderr, 2366d14e2a8SJordan K. Hubbard "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 237af57ed9fSAtsushi Murai exit(EX_START); 238af57ed9fSAtsushi Murai } 239af57ed9fSAtsushi Murai 240af57ed9fSAtsushi Murai void 241af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 242af57ed9fSAtsushi Murai { 243af57ed9fSAtsushi Murai int optc; 244af57ed9fSAtsushi Murai char *cp; 245af57ed9fSAtsushi Murai 246af57ed9fSAtsushi Murai optc = 0; 247af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 248af57ed9fSAtsushi Murai cp = *argv + 1; 249af57ed9fSAtsushi Murai if (strcmp(cp, "auto") == 0) 250af57ed9fSAtsushi Murai mode |= MODE_AUTO; 2516d14e2a8SJordan K. Hubbard else if (strcmp(cp, "background") == 0) 2526d14e2a8SJordan K. Hubbard mode |= MODE_BACKGROUND; 253af57ed9fSAtsushi Murai else if (strcmp(cp, "direct") == 0) 254af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 255af57ed9fSAtsushi Murai else if (strcmp(cp, "dedicated") == 0) 256af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 257680026d6SNate Williams else if (strcmp(cp, "ddial") == 0) 258680026d6SNate Williams mode |= MODE_DDIAL|MODE_AUTO; 259a9f484e5SJordan K. Hubbard else if (strcmp(cp, "alias") == 0) { 260a9f484e5SJordan K. Hubbard mode |= MODE_ALIAS; 261a9f484e5SJordan K. Hubbard optc--; /* this option isn't exclusive */ 262a9f484e5SJordan K. Hubbard } 263af57ed9fSAtsushi Murai else 264af57ed9fSAtsushi Murai Usage(); 265af57ed9fSAtsushi Murai optc++; 266af57ed9fSAtsushi Murai argv++; argc--; 267af57ed9fSAtsushi Murai } 268af57ed9fSAtsushi Murai if (argc > 1) { 269af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 270af57ed9fSAtsushi Murai exit(EX_START); 271af57ed9fSAtsushi Murai } 272af57ed9fSAtsushi Murai if (argc == 1) dstsystem = *argv; 273af57ed9fSAtsushi Murai 274af57ed9fSAtsushi Murai if (optc > 1) { 275af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 276af57ed9fSAtsushi Murai exit(EX_START); 277af57ed9fSAtsushi Murai } 278af57ed9fSAtsushi Murai } 279af57ed9fSAtsushi Murai 280af57ed9fSAtsushi Murai static void 281af57ed9fSAtsushi Murai Greetings() 282af57ed9fSAtsushi Murai { 283af57ed9fSAtsushi Murai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 284af57ed9fSAtsushi Murai fflush(stdout); 285af57ed9fSAtsushi Murai } 286af57ed9fSAtsushi Murai 287af57ed9fSAtsushi Murai void 288af57ed9fSAtsushi Murai main(argc, argv) 289af57ed9fSAtsushi Murai int argc; 290af57ed9fSAtsushi Murai char **argv; 291af57ed9fSAtsushi Murai { 292af57ed9fSAtsushi Murai int tunno; 293af57ed9fSAtsushi Murai 294af57ed9fSAtsushi Murai argc--; argv++; 295af57ed9fSAtsushi Murai 296af57ed9fSAtsushi Murai mode = MODE_INTER; /* default operation is interactive mode */ 297780700e5SAndrey A. Chernov netfd = server = modem = tun_in = -1; 298af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 299af57ed9fSAtsushi Murai Greetings(); 300af57ed9fSAtsushi Murai GetUid(); 301af57ed9fSAtsushi Murai IpcpDefAddress(); 302a9f484e5SJordan K. Hubbard InitAlias(); 303af57ed9fSAtsushi Murai 304af57ed9fSAtsushi Murai if (SelectSystem("default", CONFFILE) < 0) { 305af57ed9fSAtsushi Murai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 306af57ed9fSAtsushi Murai } 307af57ed9fSAtsushi Murai 308af57ed9fSAtsushi Murai if (LogOpen()) 309af57ed9fSAtsushi Murai exit(EX_START); 310af57ed9fSAtsushi Murai 31153c9f6c0SAtsushi Murai switch ( LocalAuthInit() ) { 31253c9f6c0SAtsushi Murai case NOT_FOUND: 31341db6564SAtsushi Murai fprintf(stderr,LAUTH_M1); 31441db6564SAtsushi Murai fprintf(stderr,LAUTH_M2); 31541db6564SAtsushi Murai fflush (stderr); 31641db6564SAtsushi Murai /* Fall down */ 31741db6564SAtsushi Murai case VALID: 31853c9f6c0SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 31953c9f6c0SAtsushi Murai break; 32053c9f6c0SAtsushi Murai default: 32153c9f6c0SAtsushi Murai break; 32253c9f6c0SAtsushi Murai } 32353c9f6c0SAtsushi Murai 324af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 325af57ed9fSAtsushi Murai perror("open_tun"); 326af57ed9fSAtsushi Murai exit(EX_START); 327af57ed9fSAtsushi Murai } 328af57ed9fSAtsushi Murai 3296d14e2a8SJordan K. Hubbard if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND)) 330af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 331af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 332af57ed9fSAtsushi Murai printf("Interactive mode\n"); 333780700e5SAndrey A. Chernov netfd = STDIN_FILENO; 334af57ed9fSAtsushi Murai } else if (mode & MODE_AUTO) { 335680026d6SNate Williams printf("Automatic Dialer mode\n"); 336af57ed9fSAtsushi Murai if (dstsystem == NULL) { 337680026d6SNate Williams fprintf(stderr, 338680026d6SNate Williams "Destination system must be specified in auto or ddial mode.\n"); 339af57ed9fSAtsushi Murai exit(EX_START); 340af57ed9fSAtsushi Murai } 3416d14e2a8SJordan K. Hubbard } else if (mode & MODE_BACKGROUND) { 3426d14e2a8SJordan K. Hubbard printf("Background mode\n"); 3436d14e2a8SJordan K. Hubbard if (dstsystem == NULL) { 3446d14e2a8SJordan K. Hubbard fprintf(stderr, "Destination system must be specified in background mode.\n"); 3456d14e2a8SJordan K. Hubbard exit(EX_START); 3466d14e2a8SJordan K. Hubbard } 347af57ed9fSAtsushi Murai } 348af57ed9fSAtsushi Murai 34953c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 350af57ed9fSAtsushi Murai 351d7f5ee41SAndrey A. Chernov signal(SIGHUP, Hangup); 35206257ca4SAndrey A. Chernov signal(SIGTERM, CloseSession); 35306257ca4SAndrey A. Chernov signal(SIGINT, CloseSession); 35406257ca4SAndrey A. Chernov signal(SIGQUIT, CloseSession); 35553c9f6c0SAtsushi Murai #ifdef SIGSEGV 356d7f5ee41SAndrey A. Chernov signal(SIGSEGV, Hangup); 35753c9f6c0SAtsushi Murai #endif 35853c9f6c0SAtsushi Murai #ifdef SIGPIPE 359d7f5ee41SAndrey A. Chernov signal(SIGPIPE, Hangup); 36053c9f6c0SAtsushi Murai #endif 36153c9f6c0SAtsushi Murai #ifdef SIGALRM 36206257ca4SAndrey A. Chernov signal(SIGALRM, SIG_IGN); 36353c9f6c0SAtsushi Murai #endif 364c3899f8dSAtsushi Murai if(mode & MODE_INTER) 365c3899f8dSAtsushi Murai { 366c3899f8dSAtsushi Murai #ifdef SIGTSTP 367bbea88d0SAndrey A. Chernov signal(SIGTSTP, TerminalStop); 368c3899f8dSAtsushi Murai #endif 369c3899f8dSAtsushi Murai #ifdef SIGTTIN 370bbea88d0SAndrey A. Chernov signal(SIGTTIN, TerminalStop); 371c3899f8dSAtsushi Murai #endif 372c3899f8dSAtsushi Murai #ifdef SIGTTOU 373bbea88d0SAndrey A. Chernov signal(SIGTTOU, SIG_IGN); 374c3899f8dSAtsushi Murai #endif 375c3899f8dSAtsushi Murai } 376af57ed9fSAtsushi Murai 377af57ed9fSAtsushi Murai if (dstsystem) { 378af57ed9fSAtsushi Murai if (SelectSystem(dstsystem, CONFFILE) < 0) { 379af57ed9fSAtsushi Murai fprintf(stderr, "Destination system not found in conf file.\n"); 380af57ed9fSAtsushi Murai Cleanup(EX_START); 381af57ed9fSAtsushi Murai } 382af57ed9fSAtsushi Murai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 383680026d6SNate Williams fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n"); 384af57ed9fSAtsushi Murai Cleanup(EX_START); 385af57ed9fSAtsushi Murai } 386af57ed9fSAtsushi Murai } 387af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) 388af57ed9fSAtsushi Murai printf("Packet mode enabled.\n"); 389af57ed9fSAtsushi Murai 390af57ed9fSAtsushi Murai #ifdef notdef 391af57ed9fSAtsushi Murai if (mode & MODE_AUTO) { 392af57ed9fSAtsushi Murai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 393af57ed9fSAtsushi Murai } 394af57ed9fSAtsushi Murai #endif 395af57ed9fSAtsushi Murai 396af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) { 397af57ed9fSAtsushi Murai int port = SERVER_PORT + tunno; 3986d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 3996d14e2a8SJordan K. Hubbard if (pipe (BGFiledes)) { 4006d14e2a8SJordan K. Hubbard perror("pipe"); 4016d14e2a8SJordan K. Hubbard Cleanup(EX_SOCK); 4026d14e2a8SJordan K. Hubbard } 4036d14e2a8SJordan K. Hubbard } 4046d14e2a8SJordan K. Hubbard else { 405af57ed9fSAtsushi Murai /* 406af57ed9fSAtsushi Murai * Create server socket and listen at there. 407af57ed9fSAtsushi Murai */ 408af57ed9fSAtsushi Murai server = socket(PF_INET, SOCK_STREAM, 0); 409af57ed9fSAtsushi Murai if (server < 0) { 410af57ed9fSAtsushi Murai perror("socket"); 411af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 412af57ed9fSAtsushi Murai } 413af57ed9fSAtsushi Murai ifsin.sin_family = AF_INET; 414af57ed9fSAtsushi Murai ifsin.sin_addr.s_addr = INADDR_ANY; 415af57ed9fSAtsushi Murai ifsin.sin_port = htons(port); 416af57ed9fSAtsushi Murai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 417af57ed9fSAtsushi Murai perror("bind"); 418af57ed9fSAtsushi Murai if (errno == EADDRINUSE) 419af57ed9fSAtsushi Murai fprintf(stderr, "Wait for a while, then try again.\n"); 420af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 421af57ed9fSAtsushi Murai } 422af57ed9fSAtsushi Murai listen(server, 5); 4236d14e2a8SJordan K. Hubbard } 424af57ed9fSAtsushi Murai 425af57ed9fSAtsushi Murai DupLog(); 426af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 427a9c6b5dfSAtsushi Murai int fd; 428a9c6b5dfSAtsushi Murai char pid[32]; 4296d14e2a8SJordan K. Hubbard pid_t bgpid; 430a9c6b5dfSAtsushi Murai 4316d14e2a8SJordan K. Hubbard bgpid = fork (); 4326d14e2a8SJordan K. Hubbard if (bgpid == -1) { 4336d14e2a8SJordan K. Hubbard perror ("fork"); 4346d14e2a8SJordan K. Hubbard Cleanup (EX_SOCK); 4356d14e2a8SJordan K. Hubbard } 4366d14e2a8SJordan K. Hubbard if (bgpid) { 4376d14e2a8SJordan K. Hubbard char c = EX_NORMAL; 438a9c6b5dfSAtsushi Murai 4396d14e2a8SJordan K. Hubbard if (mode & MODE_BACKGROUND) { 4406d14e2a8SJordan K. Hubbard /* Wait for our child to close its pipe before we exit. */ 4416d14e2a8SJordan K. Hubbard BGPid = bgpid; 4426d14e2a8SJordan K. Hubbard read (BGFiledes[0], &c, 1); 4436d14e2a8SJordan K. Hubbard if (c == EX_NORMAL) 4446d14e2a8SJordan K. Hubbard LogPrintf (LOG_CHAT, "PPP enabled.\n"); 4456d14e2a8SJordan K. Hubbard } 4466d14e2a8SJordan K. Hubbard exit(c); 4476d14e2a8SJordan K. Hubbard } 4486d14e2a8SJordan K. Hubbard 4496d14e2a8SJordan K. Hubbard snprintf(pid_filename, sizeof (pid_filename), "%s/ppp.tun%d.pid", 4506d14e2a8SJordan K. Hubbard _PATH_VARRUN, tunno); 451a9c6b5dfSAtsushi Murai unlink(pid_filename); 45299c02d39SWarner Losh snprintf(pid, sizeof(pid), "%d\n", (int)getpid()); 453a9c6b5dfSAtsushi Murai 454a9c6b5dfSAtsushi Murai if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1) 455a9c6b5dfSAtsushi Murai { 456a9c6b5dfSAtsushi Murai write(fd, pid, strlen(pid)); 457a9c6b5dfSAtsushi Murai close(fd); 458a9c6b5dfSAtsushi Murai } 459af57ed9fSAtsushi Murai } 460780700e5SAndrey A. Chernov if (server >= 0) 4619c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port); 462af57ed9fSAtsushi Murai #ifdef DOTTYINIT 46353c9f6c0SAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 464af57ed9fSAtsushi Murai #else 465af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) { 466af57ed9fSAtsushi Murai #endif 467af57ed9fSAtsushi Murai TtyInit(); 468af57ed9fSAtsushi Murai } else { 469d91680eaSAndrey A. Chernov int fd; 470d91680eaSAndrey A. Chernov 471af57ed9fSAtsushi Murai setsid(); /* detach control tty */ 472d91680eaSAndrey A. Chernov if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 473d91680eaSAndrey A. Chernov (void)dup2(fd, STDIN_FILENO); 474d91680eaSAndrey A. Chernov (void)dup2(fd, STDOUT_FILENO); 475d91680eaSAndrey A. Chernov (void)dup2(fd, STDERR_FILENO); 476d91680eaSAndrey A. Chernov if (fd > 2) 477d91680eaSAndrey A. Chernov (void)close (fd); 478d91680eaSAndrey A. Chernov } 479af57ed9fSAtsushi Murai } 480af57ed9fSAtsushi Murai } else { 481af57ed9fSAtsushi Murai TtyInit(); 482c3899f8dSAtsushi Murai TtyCommandMode(1); 483af57ed9fSAtsushi Murai } 4849c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "PPP Started.\n"); 485af57ed9fSAtsushi Murai 486af57ed9fSAtsushi Murai 487af57ed9fSAtsushi Murai do 488af57ed9fSAtsushi Murai DoLoop(); 489af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 490af57ed9fSAtsushi Murai 491af57ed9fSAtsushi Murai Cleanup(EX_DONE); 492af57ed9fSAtsushi Murai } 493af57ed9fSAtsushi Murai 494af57ed9fSAtsushi Murai /* 4956d14e2a8SJordan K. Hubbard * Turn into packet mode, where we speak PPP. 496af57ed9fSAtsushi Murai */ 497af57ed9fSAtsushi Murai void 498af57ed9fSAtsushi Murai PacketMode() 499af57ed9fSAtsushi Murai { 500af57ed9fSAtsushi Murai if (RawModem(modem) < 0) { 501af57ed9fSAtsushi Murai fprintf(stderr, "Not connected.\r\n"); 502af57ed9fSAtsushi Murai return; 503af57ed9fSAtsushi Murai } 504af57ed9fSAtsushi Murai 505af57ed9fSAtsushi Murai AsyncInit(); 506af57ed9fSAtsushi Murai VjInit(); 507af57ed9fSAtsushi Murai LcpInit(); 508af57ed9fSAtsushi Murai IpcpInit(); 509af57ed9fSAtsushi Murai CcpInit(); 510af57ed9fSAtsushi Murai LcpUp(); 511af57ed9fSAtsushi Murai 512af57ed9fSAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 513af57ed9fSAtsushi Murai LcpOpen(OPEN_ACTIVE); 514af57ed9fSAtsushi Murai else 515af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 516af57ed9fSAtsushi Murai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 517c3899f8dSAtsushi Murai TtyCommandMode(1); 518af57ed9fSAtsushi Murai fprintf(stderr, "Packet mode.\r\n"); 519b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 520af57ed9fSAtsushi Murai } 521af57ed9fSAtsushi Murai } 522af57ed9fSAtsushi Murai 523af57ed9fSAtsushi Murai static void 524af57ed9fSAtsushi Murai ShowHelp() 525af57ed9fSAtsushi Murai { 526c3899f8dSAtsushi Murai fprintf(stderr, "The following commands are available:\r\n"); 527af57ed9fSAtsushi Murai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 5281dff3fc5SAndrey A. Chernov fprintf(stderr, " ~-\tDecrease log level\r\n"); 5291dff3fc5SAndrey A. Chernov fprintf(stderr, " ~+\tIncrease log level\r\n"); 530af57ed9fSAtsushi Murai fprintf(stderr, " ~.\tTerminate program\r\n"); 5311dff3fc5SAndrey A. Chernov fprintf(stderr, " ~?\tThis help\r\n"); 532af57ed9fSAtsushi Murai } 533af57ed9fSAtsushi Murai 534af57ed9fSAtsushi Murai static void 535af57ed9fSAtsushi Murai ReadTty() 536af57ed9fSAtsushi Murai { 537af57ed9fSAtsushi Murai int n; 538af57ed9fSAtsushi Murai char ch; 539af57ed9fSAtsushi Murai static int ttystate; 540af57ed9fSAtsushi Murai #define MAXLINESIZE 200 541af57ed9fSAtsushi Murai char linebuff[MAXLINESIZE]; 542af57ed9fSAtsushi Murai 543af57ed9fSAtsushi Murai #ifdef DEBUG 544af57ed9fSAtsushi Murai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 545af57ed9fSAtsushi Murai #endif 546af57ed9fSAtsushi Murai if (!TermMode) { 547af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff)-1); 548b0cdb3ceSJordan K. Hubbard aft_cmd = 1; 54953c9f6c0SAtsushi Murai if (n > 0) { 550af57ed9fSAtsushi Murai DecodeCommand(linebuff, n, 1); 55153c9f6c0SAtsushi Murai } else { 552af57ed9fSAtsushi Murai #ifdef DEBUG 553af57ed9fSAtsushi Murai logprintf("connection closed.\n"); 554af57ed9fSAtsushi Murai #endif 555af57ed9fSAtsushi Murai close(netfd); 556af57ed9fSAtsushi Murai netfd = -1; 557af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 558af57ed9fSAtsushi Murai } 559af57ed9fSAtsushi Murai return; 560af57ed9fSAtsushi Murai } 561af57ed9fSAtsushi Murai 562af57ed9fSAtsushi Murai /* 563af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 564af57ed9fSAtsushi Murai */ 565af57ed9fSAtsushi Murai n = read(0, &ch, 1); 566af57ed9fSAtsushi Murai #ifdef DEBUG 567af57ed9fSAtsushi Murai logprintf("got %d bytes\n", n); 568af57ed9fSAtsushi Murai #endif 569af57ed9fSAtsushi Murai 570af57ed9fSAtsushi Murai if (n > 0) { 571af57ed9fSAtsushi Murai switch (ttystate) { 572af57ed9fSAtsushi Murai case 0: 573af57ed9fSAtsushi Murai if (ch == '~') 574af57ed9fSAtsushi Murai ttystate++; 575af57ed9fSAtsushi Murai else 576af57ed9fSAtsushi Murai write(modem, &ch, n); 577af57ed9fSAtsushi Murai break; 578af57ed9fSAtsushi Murai case 1: 579af57ed9fSAtsushi Murai switch (ch) { 580af57ed9fSAtsushi Murai case '?': 581af57ed9fSAtsushi Murai ShowHelp(); 582af57ed9fSAtsushi Murai break; 583af57ed9fSAtsushi Murai case '-': 584af57ed9fSAtsushi Murai if (loglevel > 0) { 585af57ed9fSAtsushi Murai loglevel--; 586af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 587af57ed9fSAtsushi Murai } 588af57ed9fSAtsushi Murai break; 589af57ed9fSAtsushi Murai case '+': 590af57ed9fSAtsushi Murai loglevel++; 591af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 592af57ed9fSAtsushi Murai break; 593af57ed9fSAtsushi Murai #ifdef DEBUG 594af57ed9fSAtsushi Murai case 'm': 595af57ed9fSAtsushi Murai ShowMemMap(); 596af57ed9fSAtsushi Murai break; 597af57ed9fSAtsushi Murai #endif 598af57ed9fSAtsushi Murai case 'p': 599af57ed9fSAtsushi Murai /* 600af57ed9fSAtsushi Murai * XXX: Should check carrier. 601af57ed9fSAtsushi Murai */ 602af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 603af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 604af57ed9fSAtsushi Murai PacketMode(); 605af57ed9fSAtsushi Murai } 606af57ed9fSAtsushi Murai break; 607af57ed9fSAtsushi Murai #ifdef DEBUG 608af57ed9fSAtsushi Murai case 't': 609af57ed9fSAtsushi Murai ShowTimers(); 610af57ed9fSAtsushi Murai break; 611af57ed9fSAtsushi Murai #endif 612af57ed9fSAtsushi Murai case '.': 613af57ed9fSAtsushi Murai TermMode = 1; 614c3899f8dSAtsushi Murai TtyCommandMode(1); 615af57ed9fSAtsushi Murai break; 616af57ed9fSAtsushi Murai default: 617af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 618af57ed9fSAtsushi Murai fprintf(stderr, "err in write.\r\n"); 619af57ed9fSAtsushi Murai break; 620af57ed9fSAtsushi Murai } 621af57ed9fSAtsushi Murai ttystate = 0; 622af57ed9fSAtsushi Murai break; 623af57ed9fSAtsushi Murai } 624af57ed9fSAtsushi Murai } 625af57ed9fSAtsushi Murai } 626af57ed9fSAtsushi Murai 627af57ed9fSAtsushi Murai 628af57ed9fSAtsushi Murai /* 629af57ed9fSAtsushi Murai * Here, we'll try to detect HDLC frame 630af57ed9fSAtsushi Murai */ 631af57ed9fSAtsushi Murai 632af57ed9fSAtsushi Murai static char *FrameHeaders[] = { 63353c9f6c0SAtsushi Murai "\176\377\003\300\041", 63453c9f6c0SAtsushi Murai "\176\377\175\043\300\041", 63553c9f6c0SAtsushi Murai "\176\177\175\043\100\041", 63653c9f6c0SAtsushi Murai "\176\175\337\175\043\300\041", 63753c9f6c0SAtsushi Murai "\176\175\137\175\043\100\041", 638af57ed9fSAtsushi Murai NULL, 639af57ed9fSAtsushi Murai }; 640af57ed9fSAtsushi Murai 641af57ed9fSAtsushi Murai u_char * 642af57ed9fSAtsushi Murai HdlcDetect(cp, n) 643af57ed9fSAtsushi Murai u_char *cp; 644af57ed9fSAtsushi Murai int n; 645af57ed9fSAtsushi Murai { 64653c9f6c0SAtsushi Murai char *ptr, *fp, **hp; 647af57ed9fSAtsushi Murai 648af57ed9fSAtsushi Murai cp[n] = '\0'; /* be sure to null terminated */ 649af57ed9fSAtsushi Murai ptr = NULL; 650af57ed9fSAtsushi Murai for (hp = FrameHeaders; *hp; hp++) { 65153c9f6c0SAtsushi Murai fp = *hp; 65253c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 65353c9f6c0SAtsushi Murai fp++; 654ed6a16c1SPoul-Henning Kamp ptr = strstr((char *)cp, fp); 655ed6a16c1SPoul-Henning Kamp if (ptr) 656af57ed9fSAtsushi Murai break; 657af57ed9fSAtsushi Murai } 658af57ed9fSAtsushi Murai return((u_char *)ptr); 659af57ed9fSAtsushi Murai } 660af57ed9fSAtsushi Murai 661af57ed9fSAtsushi Murai static struct pppTimer RedialTimer; 662af57ed9fSAtsushi Murai 663af57ed9fSAtsushi Murai static void 664af57ed9fSAtsushi Murai RedialTimeout() 665af57ed9fSAtsushi Murai { 666af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 6679c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Redialing timer expired.\n"); 668af57ed9fSAtsushi Murai } 669af57ed9fSAtsushi Murai 670af57ed9fSAtsushi Murai static void 671af57ed9fSAtsushi Murai StartRedialTimer() 672af57ed9fSAtsushi Murai { 673af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 674a9c6b5dfSAtsushi Murai 675a9c6b5dfSAtsushi Murai if (VarRedialTimeout) { 6769c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Enter pause for redialing.\n"); 677af57ed9fSAtsushi Murai RedialTimer.state = TIMER_STOPPED; 678a9c6b5dfSAtsushi Murai 679a9c6b5dfSAtsushi Murai if (VarRedialTimeout > 0) 680a9c6b5dfSAtsushi Murai RedialTimer.load = VarRedialTimeout * SECTICKS; 681a9c6b5dfSAtsushi Murai else 682a9c6b5dfSAtsushi Murai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 683a9c6b5dfSAtsushi Murai 684af57ed9fSAtsushi Murai RedialTimer.func = RedialTimeout; 685af57ed9fSAtsushi Murai StartTimer(&RedialTimer); 686af57ed9fSAtsushi Murai } 687a9c6b5dfSAtsushi Murai } 688af57ed9fSAtsushi Murai 689af57ed9fSAtsushi Murai 690af57ed9fSAtsushi Murai static void 691af57ed9fSAtsushi Murai DoLoop() 692af57ed9fSAtsushi Murai { 693af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 694780700e5SAndrey A. Chernov int pri, i, n, wfd, nfds; 695af57ed9fSAtsushi Murai struct sockaddr_in hisaddr; 696af57ed9fSAtsushi Murai struct timeval timeout, *tp; 697af57ed9fSAtsushi Murai int ssize = sizeof(hisaddr); 698af57ed9fSAtsushi Murai u_char *cp; 699af57ed9fSAtsushi Murai u_char rbuff[MAX_MRU]; 70084b8a6ebSAtsushi Murai int dial_up; 701a9c6b5dfSAtsushi Murai int tries; 70260e218e4SAtsushi Murai int qlen; 703c3899f8dSAtsushi Murai pid_t pgroup; 704c3899f8dSAtsushi Murai 705c3899f8dSAtsushi Murai pgroup = getpgrp(); 706af57ed9fSAtsushi Murai 707af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) { 708af57ed9fSAtsushi Murai modem = OpenModem(mode); 7099c749ffbSPoul-Henning Kamp LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n"); 710b0cdb3ceSJordan K. Hubbard fflush(stderr); 711af57ed9fSAtsushi Murai PacketMode(); 712af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 713780700e5SAndrey A. Chernov if (modem < 0) 714af57ed9fSAtsushi Murai modem = OpenModem(mode); 715af57ed9fSAtsushi Murai } 716af57ed9fSAtsushi Murai 717af57ed9fSAtsushi Murai fflush(stdout); 718af57ed9fSAtsushi Murai 71984b8a6ebSAtsushi Murai timeout.tv_sec = 0; 720af57ed9fSAtsushi Murai timeout.tv_usec = 0; 721af57ed9fSAtsushi Murai 72284b8a6ebSAtsushi Murai dial_up = FALSE; /* XXXX */ 723a9c6b5dfSAtsushi Murai tries = 0; 724af57ed9fSAtsushi Murai for (;;) { 725780700e5SAndrey A. Chernov nfds = 0; 726af57ed9fSAtsushi Murai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 72784b8a6ebSAtsushi Murai 72884b8a6ebSAtsushi Murai /* 729680026d6SNate Williams * If the link is down and we're in DDIAL mode, bring it back 730680026d6SNate Williams * up. 731680026d6SNate Williams */ 732680026d6SNate Williams if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 733680026d6SNate Williams dial_up = TRUE; 734680026d6SNate Williams 735680026d6SNate Williams /* 73684b8a6ebSAtsushi Murai * If Ip packet for output is enqueued and require dial up, 73784b8a6ebSAtsushi Murai * Just do it! 73884b8a6ebSAtsushi Murai */ 73984b8a6ebSAtsushi Murai if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ 74084b8a6ebSAtsushi Murai #ifdef DEBUG 74184b8a6ebSAtsushi Murai logprintf("going to dial: modem = %d\n", modem); 74284b8a6ebSAtsushi Murai #endif 74384b8a6ebSAtsushi Murai modem = OpenModem(mode); 74484b8a6ebSAtsushi Murai if (modem < 0) { 74584b8a6ebSAtsushi Murai StartRedialTimer(); 74684b8a6ebSAtsushi Murai } else { 747a9c6b5dfSAtsushi Murai tries++; 7489c749ffbSPoul-Henning Kamp LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries); 74984b8a6ebSAtsushi Murai if (DialModem()) { 75084b8a6ebSAtsushi Murai sleep(1); /* little pause to allow peer starts */ 75184b8a6ebSAtsushi Murai ModemTimeout(); 75284b8a6ebSAtsushi Murai PacketMode(); 75384b8a6ebSAtsushi Murai dial_up = FALSE; 754a9c6b5dfSAtsushi Murai tries = 0; 75584b8a6ebSAtsushi Murai } else { 75684b8a6ebSAtsushi Murai CloseModem(); 75784b8a6ebSAtsushi Murai /* Dial failed. Keep quite during redial wait period. */ 75884b8a6ebSAtsushi Murai StartRedialTimer(); 759a9c6b5dfSAtsushi Murai 760a9c6b5dfSAtsushi Murai if (VarDialTries && tries >= VarDialTries) { 761a9c6b5dfSAtsushi Murai dial_up = FALSE; 762a9c6b5dfSAtsushi Murai tries = 0; 763a9c6b5dfSAtsushi Murai } 76484b8a6ebSAtsushi Murai } 76584b8a6ebSAtsushi Murai } 76684b8a6ebSAtsushi Murai } 76760e218e4SAtsushi Murai qlen = ModemQlen(); 76876bd0c0aSDoug Rabson 76976bd0c0aSDoug Rabson if (qlen == 0) { 77076bd0c0aSDoug Rabson IpStartOutput(); 77176bd0c0aSDoug Rabson qlen = ModemQlen(); 77276bd0c0aSDoug Rabson } 77376bd0c0aSDoug Rabson 774780700e5SAndrey A. Chernov if (modem >= 0) { 775780700e5SAndrey A. Chernov if (modem + 1 > nfds) 776780700e5SAndrey A. Chernov nfds = modem + 1; 77784b8a6ebSAtsushi Murai FD_SET(modem, &rfds); 77884b8a6ebSAtsushi Murai FD_SET(modem, &efds); 77960e218e4SAtsushi Murai if (qlen > 0) { 78084b8a6ebSAtsushi Murai FD_SET(modem, &wfds); 78184b8a6ebSAtsushi Murai } 78284b8a6ebSAtsushi Murai } 783780700e5SAndrey A. Chernov if (server >= 0) { 784780700e5SAndrey A. Chernov if (server + 1 > nfds) 785780700e5SAndrey A. Chernov nfds = server + 1; 786780700e5SAndrey A. Chernov FD_SET(server, &rfds); 787780700e5SAndrey A. Chernov } 788af57ed9fSAtsushi Murai 789af57ed9fSAtsushi Murai /* *** IMPORTANT *** 790af57ed9fSAtsushi Murai * 791af57ed9fSAtsushi Murai * CPU is serviced every TICKUNIT micro seconds. 792af57ed9fSAtsushi Murai * This value must be chosen with great care. If this values is 793af57ed9fSAtsushi Murai * too big, it results loss of characters from modem and poor responce. 794af57ed9fSAtsushi Murai * If this values is too small, ppp process eats many CPU time. 795af57ed9fSAtsushi Murai */ 79653c9f6c0SAtsushi Murai #ifndef SIGALRM 797af57ed9fSAtsushi Murai usleep(TICKUNIT); 798af57ed9fSAtsushi Murai TimerService(); 79953c9f6c0SAtsushi Murai #endif 80068d2b4d6SBruce Evans 80168d2b4d6SBruce Evans /* If there are aren't many packets queued, look for some more. */ 802780700e5SAndrey A. Chernov if (qlen < 20 && tun_in >= 0) { 803780700e5SAndrey A. Chernov if (tun_in + 1 > nfds) 804780700e5SAndrey A. Chernov nfds = tun_in + 1; 80584b8a6ebSAtsushi Murai FD_SET(tun_in, &rfds); 806780700e5SAndrey A. Chernov } 80768d2b4d6SBruce Evans 808780700e5SAndrey A. Chernov if (netfd >= 0) { 809780700e5SAndrey A. Chernov if (netfd + 1 > nfds) 810780700e5SAndrey A. Chernov nfds = netfd + 1; 811af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 812af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 813af57ed9fSAtsushi Murai } 81484b8a6ebSAtsushi Murai 81553c9f6c0SAtsushi Murai #ifndef SIGALRM 816af57ed9fSAtsushi Murai /* 81784b8a6ebSAtsushi Murai * Normally, select() will not block because modem is writable. 81884b8a6ebSAtsushi Murai * In AUTO mode, select will block until we find packet from tun 819af57ed9fSAtsushi Murai */ 820af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 821780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 82253c9f6c0SAtsushi Murai #else 82384b8a6ebSAtsushi Murai /* 82484b8a6ebSAtsushi Murai * When SIGALRM timer is running, a select function will be 82584b8a6ebSAtsushi Murai * return -1 and EINTR after a Time Service signal hundler 826a9c6b5dfSAtsushi Murai * is done. If the redial timer is not running and we are 827a9c6b5dfSAtsushi Murai * trying to dial, poll with a 0 value timer. 82884b8a6ebSAtsushi Murai */ 829a9c6b5dfSAtsushi Murai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 830780700e5SAndrey A. Chernov i = select(nfds, &rfds, &wfds, &efds, tp); 83153c9f6c0SAtsushi Murai #endif 8326b0b88d8SBrian Somers 833af57ed9fSAtsushi Murai if ( i == 0 ) { 834af57ed9fSAtsushi Murai continue; 835af57ed9fSAtsushi Murai } 83653c9f6c0SAtsushi Murai 837534fe541SBrian Somers if ( i < 0 ) { 838534fe541SBrian Somers if ( errno == EINTR ) { 839bbea88d0SAndrey A. Chernov continue; /* Got a signal - should have been dealt with */ 84084b8a6ebSAtsushi Murai } 841af57ed9fSAtsushi Murai perror("select"); 842af57ed9fSAtsushi Murai break; 843af57ed9fSAtsushi Murai } 84484b8a6ebSAtsushi Murai 845780700e5SAndrey A. Chernov if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 846af57ed9fSAtsushi Murai logprintf("Exception detected.\n"); 847af57ed9fSAtsushi Murai break; 848af57ed9fSAtsushi Murai } 849af57ed9fSAtsushi Murai 850780700e5SAndrey A. Chernov if (server >= 0 && FD_ISSET(server, &rfds)) { 851af57ed9fSAtsushi Murai #ifdef DEBUG 852af57ed9fSAtsushi Murai logprintf("connected to client.\n"); 853af57ed9fSAtsushi Murai #endif 854af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 855780700e5SAndrey A. Chernov if (netfd >= 0) { 856af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 857af57ed9fSAtsushi Murai close(wfd); 858af57ed9fSAtsushi Murai continue; 859af57ed9fSAtsushi Murai } else 860af57ed9fSAtsushi Murai netfd = wfd; 861af57ed9fSAtsushi Murai if (dup2(netfd, 1) < 0) 862af57ed9fSAtsushi Murai perror("dup2"); 863af57ed9fSAtsushi Murai mode |= MODE_INTER; 864af57ed9fSAtsushi Murai Greetings(); 86541db6564SAtsushi Murai switch ( LocalAuthInit() ) { 86641db6564SAtsushi Murai case NOT_FOUND: 86741db6564SAtsushi Murai fprintf(stdout,LAUTH_M1); 86841db6564SAtsushi Murai fprintf(stdout,LAUTH_M2); 86941db6564SAtsushi Murai fflush(stdout); 87041db6564SAtsushi Murai /* Fall down */ 87141db6564SAtsushi Murai case VALID: 87241db6564SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 87341db6564SAtsushi Murai break; 87441db6564SAtsushi Murai default: 87541db6564SAtsushi Murai break; 87641db6564SAtsushi Murai } 877af57ed9fSAtsushi Murai (void) IsInteractive(); 878af57ed9fSAtsushi Murai Prompt(0); 879af57ed9fSAtsushi Murai } 880af57ed9fSAtsushi Murai 881780700e5SAndrey A. Chernov if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 882f1884650SAtsushi Murai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 883af57ed9fSAtsushi Murai /* something to read from tty */ 884af57ed9fSAtsushi Murai ReadTty(); 885af57ed9fSAtsushi Murai } 886780700e5SAndrey A. Chernov if (modem >= 0) { 887af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 888af57ed9fSAtsushi Murai ModemStartOutput(modem); 889af57ed9fSAtsushi Murai } 890af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 89153c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 89253c9f6c0SAtsushi Murai usleep(10000); 893af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 894af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 895af57ed9fSAtsushi Murai DownConnection(); 896af57ed9fSAtsushi Murai } else 897af57ed9fSAtsushi Murai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 898af57ed9fSAtsushi Murai 899af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 900af57ed9fSAtsushi Murai /* 901af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 902af57ed9fSAtsushi Murai */ 903af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 904af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 905af57ed9fSAtsushi Murai if (cp) { 906af57ed9fSAtsushi Murai /* 907af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 908af57ed9fSAtsushi Murai */ 909af57ed9fSAtsushi Murai if (cp != rbuff) { 910af57ed9fSAtsushi Murai write(1, rbuff, cp - rbuff); 911af57ed9fSAtsushi Murai write(1, "\r\n", 2); 912af57ed9fSAtsushi Murai } 913af57ed9fSAtsushi Murai PacketMode(); 914af57ed9fSAtsushi Murai #ifdef notdef 915af57ed9fSAtsushi Murai AsyncInput(cp, n - (cp - rbuff)); 916af57ed9fSAtsushi Murai #endif 917af57ed9fSAtsushi Murai } else 918af57ed9fSAtsushi Murai write(1, rbuff, n); 919af57ed9fSAtsushi Murai } 920af57ed9fSAtsushi Murai } else { 921af57ed9fSAtsushi Murai if (n > 0) 922af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 923af57ed9fSAtsushi Murai #ifdef notdef 924af57ed9fSAtsushi Murai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 925af57ed9fSAtsushi Murai #endif 926af57ed9fSAtsushi Murai } 927af57ed9fSAtsushi Murai } 928af57ed9fSAtsushi Murai } 92984b8a6ebSAtsushi Murai 930780700e5SAndrey A. Chernov if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 931af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 932af57ed9fSAtsushi Murai if (n < 0) { 933af57ed9fSAtsushi Murai perror("read from tun"); 934af57ed9fSAtsushi Murai continue; 935af57ed9fSAtsushi Murai } 936af57ed9fSAtsushi Murai /* 937af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 938af57ed9fSAtsushi Murai * device until IPCP is opened. 939af57ed9fSAtsushi Murai */ 940af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 94184b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_DIAL); 942af57ed9fSAtsushi Murai if (pri >= 0) { 943a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 9443b92d2deSNate Williams PacketAliasOut((struct ip *)rbuff); 945a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 946a9f484e5SJordan K. Hubbard } 947af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 94884b8a6ebSAtsushi Murai dial_up = TRUE; /* XXX */ 949af57ed9fSAtsushi Murai } 950af57ed9fSAtsushi Murai continue; 951af57ed9fSAtsushi Murai } 95284b8a6ebSAtsushi Murai pri = PacketCheck(rbuff, n, FL_OUT); 953a9f484e5SJordan K. Hubbard if (pri >= 0) { 954a9f484e5SJordan K. Hubbard if (mode & MODE_ALIAS) { 9553b92d2deSNate Williams PacketAliasOut((struct ip *)rbuff); 956a9f484e5SJordan K. Hubbard n = ntohs(((struct ip *)rbuff)->ip_len); 957a9f484e5SJordan K. Hubbard } 958af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 959af57ed9fSAtsushi Murai } 960af57ed9fSAtsushi Murai } 961a9f484e5SJordan K. Hubbard } 962af57ed9fSAtsushi Murai logprintf("job done.\n"); 963af57ed9fSAtsushi Murai } 964