main.c revision 7001
16059Samurai/* 26059Samurai * User Process PPP 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 207001Samurai * $Id: main.c,v 1.3 1995/02/27 10:57:50 amurai Exp $ 216735Samurai * 226059Samurai * TODO: 236059Samurai * o Add commands for traffic summary, version display, etc. 246059Samurai * o Add signal handler for misc controls. 256059Samurai */ 266059Samurai#include "fsm.h" 276059Samurai#include <fcntl.h> 286059Samurai#include <sys/time.h> 296059Samurai#include <termios.h> 306059Samurai#include <signal.h> 316059Samurai#include <sys/wait.h> 326059Samurai#include <errno.h> 336059Samurai#include <netdb.h> 346059Samurai#include <sys/socket.h> 356059Samurai#include <arpa/inet.h> 366059Samurai#include "modem.h" 376059Samurai#include "os.h" 386059Samurai#include "hdlc.h" 396059Samurai#include "lcp.h" 406059Samurai#include "ipcp.h" 416059Samurai#include "vars.h" 426735Samurai#include "auth.h" 437001Samurai#include "filter.h" 446059Samurai 456764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 466764Samurai#define LAUTH_M2 "Warning: All manipulation is allowed by anyone in a world\n" 476764Samurai 486735Samurai#ifndef O_NONBLOCK 496735Samurai#ifdef O_NDELAY 506735Samurai#define O_NONBLOCK O_NDELAY 516735Samurai#endif 526735Samurai#endif 536735Samurai 546059Samuraiextern void VjInit(), AsyncInit(); 556059Samuraiextern void AsyncInput(), IpOutput(); 566059Samuraiextern int SelectSystem(); 576059Samurai 586059Samuraiextern void DecodeCommand(), Prompt(); 596059Samuraiextern int IsInteractive(); 606059Samuraiextern struct in_addr ifnetmask; 616059Samuraistatic void DoLoop(void); 626059Samurai 636059Samuraistatic struct termios oldtio; /* Original tty mode */ 646059Samuraistatic struct termios comtio; /* Command level tty mode */ 656059Samuraistatic int TermMode; 666059Samuraistatic int server, update; 676059Samuraistruct sockaddr_in ifsin; 686059Samurai 696059Samuraistatic void 706059SamuraiTtyInit() 716059Samurai{ 726059Samurai struct termios newtio; 736059Samurai int stat; 746059Samurai 756059Samurai stat = fcntl(0, F_GETFL, 0); 766059Samurai stat |= O_NONBLOCK; 776059Samurai fcntl(0, F_SETFL, stat); 786059Samurai newtio = oldtio; 796059Samurai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 806059Samurai newtio.c_iflag = 0; 816059Samurai newtio.c_oflag &= ~OPOST; 826059Samurai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 836059Samurai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 846059Samurai newtio.c_cc[VMIN] = 1; 856059Samurai newtio.c_cc[VTIME] = 0; 866059Samurai newtio.c_cflag |= CS8; 876735Samurai tcsetattr(0, TCSADRAIN, &newtio); 886059Samurai comtio = newtio; 896059Samurai} 906059Samurai 916059Samurai/* 926059Samurai * Set tty into command mode. We allow canonical input and echo processing. 936059Samurai */ 946059Samuraistatic void 956059SamuraiTtyCommandMode() 966059Samurai{ 976059Samurai struct termios newtio; 986059Samurai int stat; 996059Samurai 1006059Samurai if (!(mode & MODE_INTER)) 1016059Samurai return; 1026735Samurai tcgetattr(0, &newtio); 1036059Samurai newtio.c_lflag |= (ECHO|ICANON); 1046059Samurai newtio.c_iflag = oldtio.c_iflag; 1056059Samurai newtio.c_oflag |= OPOST; 1066735Samurai tcsetattr(0, TCSADRAIN, &newtio); 1076059Samurai stat = fcntl(0, F_GETFL, 0); 1086059Samurai stat |= O_NONBLOCK; 1096059Samurai fcntl(0, F_SETFL, stat); 1106059Samurai TermMode = 0; 1116059Samurai Prompt(0); 1126059Samurai} 1136059Samurai 1146059Samurai/* 1156059Samurai * Set tty into terminal mode which is used while we invoke term command. 1166059Samurai */ 1176059Samuraivoid 1186059SamuraiTtyTermMode() 1196059Samurai{ 1206059Samurai int stat; 1216059Samurai 1226735Samurai tcsetattr(0, TCSADRAIN, &comtio); 1236059Samurai stat = fcntl(0, F_GETFL, 0); 1246059Samurai stat &= ~O_NONBLOCK; 1256059Samurai fcntl(0, F_SETFL, stat); 1266059Samurai TermMode = 1; 1276059Samurai} 1286059Samurai 1296059Samuraivoid 1306059SamuraiCleanup(excode) 1316059Samuraiint excode; 1326059Samurai{ 1336059Samurai int stat; 1346059Samurai 1356059Samurai OsLinkdown(); 1366735Samurai#ifdef notdef 1376059Samurai stat = fcntl(0, F_GETFL, 0); 1386059Samurai stat &= ~O_NONBLOCK; 1396059Samurai fcntl(0, F_SETFL, stat); 1406735Samurai tcsetattr(0, TCSANOW, &oldtio); 1416735Samurai#endif 1426059Samurai OsCloseLink(1); 1436059Samurai sleep(1); 1446059Samurai if (mode & MODE_AUTO) 1456059Samurai DeleteIfRoutes(1); 1466059Samurai OsInterfaceDown(1); 1476059Samurai LogPrintf(LOG_PHASE, "PPP Terminated.\n"); 1486059Samurai LogClose(); 1496059Samurai if (server > 0) 1506059Samurai close(server); 1516735Samurai#ifndef notdef 1526735Samurai stat = fcntl(0, F_GETFL, 0); 1536735Samurai stat &= ~O_NONBLOCK; 1546735Samurai fcntl(0, F_SETFL, stat); 1556735Samurai tcsetattr(0, TCSANOW, &oldtio); 1566735Samurai#endif 1576059Samurai 1586059Samurai exit(excode); 1596059Samurai} 1606059Samurai 1616059Samuraistatic void 1626059SamuraiHangup() 1636059Samurai{ 1646059Samurai LogPrintf(LOG_PHASE, "SIGHUP\n"); 1656059Samurai signal(SIGHUP, Hangup); 1666059Samurai Cleanup(EX_HANGUP); 1676059Samurai} 1686059Samurai 1696059Samuraistatic void 1706059SamuraiCloseSession() 1716059Samurai{ 1726059Samurai LogPrintf(LOG_PHASE, "SIGTERM\n"); 1736059Samurai LcpClose(); 1746059Samurai Cleanup(EX_TERM); 1756059Samurai} 1766059Samurai 1776059Samuraivoid 1786059SamuraiUsage() 1796059Samurai{ 1806059Samurai fprintf(stderr, "Usage: ppp [-auto | -direct -dedicated] [system]\n"); 1816059Samurai exit(EX_START); 1826059Samurai} 1836059Samurai 1846059Samuraivoid 1856059SamuraiProcessArgs(int argc, char **argv) 1866059Samurai{ 1876059Samurai int optc; 1886059Samurai char *cp; 1896059Samurai 1906059Samurai optc = 0; 1916059Samurai while (argc > 0 && **argv == '-') { 1926059Samurai cp = *argv + 1; 1936059Samurai if (strcmp(cp, "auto") == 0) 1946059Samurai mode |= MODE_AUTO; 1956059Samurai else if (strcmp(cp, "direct") == 0) 1966059Samurai mode |= MODE_DIRECT; 1976059Samurai else if (strcmp(cp, "dedicated") == 0) 1986059Samurai mode |= MODE_DEDICATED; 1996059Samurai else 2006059Samurai Usage(); 2016059Samurai optc++; 2026059Samurai argv++; argc--; 2036059Samurai } 2046059Samurai if (argc > 1) { 2056059Samurai fprintf(stderr, "specify only one system label.\n"); 2066059Samurai exit(EX_START); 2076059Samurai } 2086059Samurai if (argc == 1) dstsystem = *argv; 2096059Samurai 2106059Samurai if (optc > 1) { 2116059Samurai fprintf(stderr, "specify only one mode.\n"); 2126059Samurai exit(EX_START); 2136059Samurai } 2146059Samurai} 2156059Samurai 2166059Samuraistatic void 2176059SamuraiGreetings() 2186059Samurai{ 2196059Samurai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 2206059Samurai fflush(stdout); 2216059Samurai} 2226059Samurai 2236059Samuraivoid 2246059Samuraimain(argc, argv) 2256059Samuraiint argc; 2266059Samuraichar **argv; 2276059Samurai{ 2286059Samurai int tunno; 2296059Samurai int on = 1; 2306059Samurai 2316059Samurai argc--; argv++; 2326059Samurai 2336059Samurai mode = MODE_INTER; /* default operation is interactive mode */ 2346059Samurai netfd = -1; 2356059Samurai ProcessArgs(argc, argv); 2366059Samurai Greetings(); 2376059Samurai GetUid(); 2386059Samurai IpcpDefAddress(); 2396059Samurai 2406059Samurai if (SelectSystem("default", CONFFILE) < 0) { 2416059Samurai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 2426059Samurai } 2436059Samurai 2446059Samurai if (LogOpen()) 2456059Samurai exit(EX_START); 2466059Samurai 2476735Samurai switch ( LocalAuthInit() ) { 2486735Samurai case NOT_FOUND: 2496764Samurai fprintf(stderr,LAUTH_M1); 2506764Samurai fprintf(stderr,LAUTH_M2); 2516764Samurai fflush (stderr); 2526764Samurai /* Fall down */ 2536764Samurai case VALID: 2546735Samurai VarLocalAuth = LOCAL_AUTH; 2556735Samurai break; 2566735Samurai default: 2576735Samurai break; 2586735Samurai } 2596735Samurai 2606059Samurai if (OpenTunnel(&tunno) < 0) { 2616059Samurai perror("open_tun"); 2626059Samurai exit(EX_START); 2636059Samurai } 2646059Samurai 2656059Samurai if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 2666059Samurai mode &= ~MODE_INTER; 2676059Samurai if (mode & MODE_INTER) { 2686059Samurai printf("Interactive mode\n"); 2696059Samurai netfd = 0; 2706059Samurai } else if (mode & MODE_AUTO) { 2716059Samurai printf("Automatic mode\n"); 2726059Samurai if (dstsystem == NULL) { 2736059Samurai fprintf(stderr, "Destination system must be specified in auto mode.\n"); 2746059Samurai exit(EX_START); 2756059Samurai } 2766059Samurai } 2776059Samurai 2786735Samurai tcgetattr(0, &oldtio); /* Save original tty mode */ 2796059Samurai 2806059Samurai signal(SIGHUP, Hangup); 2816059Samurai signal(SIGTERM, CloseSession); 2826059Samurai signal(SIGINT, CloseSession); 2836735Samurai#ifdef SIGSEGV 2846059Samurai signal(SIGSEGV, Hangup); 2856735Samurai#endif 2866735Samurai#ifdef SIGPIPE 2876735Samurai signal(SIGPIPE, Hangup); 2886735Samurai#endif 2896735Samurai#ifdef SIGALRM 2906735Samurai signal(SIGALRM, SIG_IGN); 2916735Samurai#endif 2926059Samurai 2936059Samurai if (dstsystem) { 2946059Samurai if (SelectSystem(dstsystem, CONFFILE) < 0) { 2956059Samurai fprintf(stderr, "Destination system not found in conf file.\n"); 2966059Samurai Cleanup(EX_START); 2976059Samurai } 2986059Samurai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 2996059Samurai fprintf(stderr, "Must specify dstaddr with auto mode.\n"); 3006059Samurai Cleanup(EX_START); 3016059Samurai } 3026059Samurai } 3036059Samurai if (mode & MODE_DIRECT) 3046059Samurai printf("Packet mode enabled.\n"); 3056059Samurai 3066059Samurai#ifdef notdef 3076059Samurai if (mode & MODE_AUTO) { 3086059Samurai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 3096059Samurai } 3106059Samurai#endif 3116059Samurai 3126059Samurai if (!(mode & MODE_INTER)) { 3136059Samurai int port = SERVER_PORT + tunno; 3146059Samurai /* 3156059Samurai * Create server socket and listen at there. 3166059Samurai */ 3176059Samurai server = socket(PF_INET, SOCK_STREAM, 0); 3186059Samurai if (server < 0) { 3196059Samurai perror("socket"); 3206059Samurai Cleanup(EX_SOCK); 3216059Samurai } 3226059Samurai ifsin.sin_family = AF_INET; 3236059Samurai ifsin.sin_addr.s_addr = INADDR_ANY; 3246059Samurai ifsin.sin_port = htons(port); 3256059Samurai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 3266059Samurai perror("bind"); 3276059Samurai if (errno == EADDRINUSE) 3286059Samurai fprintf(stderr, "Wait for a while, then try again.\n"); 3296059Samurai Cleanup(EX_SOCK); 3306059Samurai } 3316059Samurai listen(server, 5); 3326059Samurai 3336059Samurai DupLog(); 3346059Samurai if (!(mode & MODE_DIRECT)) { 3356059Samurai if (fork()) 3366059Samurai exit(0); 3376059Samurai } 3386059Samurai LogPrintf(LOG_PHASE, "Listening at %d.\n", port); 3396059Samurai#ifdef DOTTYINIT 3406735Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 3416059Samurai#else 3426059Samurai if (mode & MODE_DIRECT) { 3436059Samurai#endif 3446059Samurai TtyInit(); 3456059Samurai } else { 3466059Samurai setsid(); /* detach control tty */ 3476059Samurai } 3486059Samurai } else { 3496059Samurai server = -1; 3506059Samurai TtyInit(); 3516059Samurai TtyCommandMode(); 3526059Samurai } 3536059Samurai LogPrintf(LOG_PHASE, "PPP Started.\n"); 3546059Samurai 3556059Samurai 3566059Samurai do 3576059Samurai DoLoop(); 3586059Samurai while (mode & MODE_DEDICATED); 3596059Samurai 3606059Samurai Cleanup(EX_DONE); 3616059Samurai} 3626059Samurai 3636059Samurai/* 3646059Samurai * Turn into packet mode, where we speek PPP. 3656059Samurai */ 3666059Samuraivoid 3676059SamuraiPacketMode() 3686059Samurai{ 3696059Samurai if (RawModem(modem) < 0) { 3706059Samurai fprintf(stderr, "Not connected.\r\n"); 3716059Samurai return; 3726059Samurai } 3736059Samurai 3746059Samurai AsyncInit(); 3756059Samurai VjInit(); 3766059Samurai LcpInit(); 3776059Samurai IpcpInit(); 3786059Samurai CcpInit(); 3796059Samurai LcpUp(); 3806059Samurai 3816059Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 3826059Samurai LcpOpen(OPEN_ACTIVE); 3836059Samurai else 3846059Samurai LcpOpen(VarOpenMode); 3856059Samurai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 3866059Samurai TtyCommandMode(); 3876059Samurai fprintf(stderr, "Packet mode.\r\n"); 3886059Samurai } 3896059Samurai} 3906059Samurai 3916059Samuraistatic void 3926059SamuraiShowHelp() 3936059Samurai{ 3946059Samurai fprintf(stderr, "Following commands are available\r\n"); 3956059Samurai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 3966059Samurai fprintf(stderr, " ~.\tTerminate program\r\n"); 3976059Samurai} 3986059Samurai 3996059Samuraistatic void 4006059SamuraiReadTty() 4016059Samurai{ 4026059Samurai int n; 4036059Samurai char ch; 4046059Samurai static int ttystate; 4056059Samurai#define MAXLINESIZE 200 4066059Samurai char linebuff[MAXLINESIZE]; 4076059Samurai 4086059Samurai#ifdef DEBUG 4096059Samurai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 4106059Samurai#endif 4116059Samurai if (!TermMode) { 4126059Samurai n = read(netfd, linebuff, sizeof(linebuff)-1); 4136735Samurai if (n > 0) { 4146059Samurai DecodeCommand(linebuff, n, 1); 4156735Samurai } else { 4166059Samurai#ifdef DEBUG 4176059Samurai logprintf("connection closed.\n"); 4186059Samurai#endif 4196059Samurai close(netfd); 4206059Samurai netfd = -1; 4216059Samurai mode &= ~MODE_INTER; 4226059Samurai } 4236059Samurai return; 4246059Samurai } 4256059Samurai 4266059Samurai /* 4276059Samurai * We are in terminal mode, decode special sequences 4286059Samurai */ 4296059Samurai n = read(0, &ch, 1); 4306059Samurai#ifdef DEBUG 4316059Samurai logprintf("got %d bytes\n", n); 4326059Samurai#endif 4336059Samurai 4346059Samurai if (n > 0) { 4356059Samurai switch (ttystate) { 4366059Samurai case 0: 4376059Samurai if (ch == '~') 4386059Samurai ttystate++; 4396059Samurai else 4406059Samurai write(modem, &ch, n); 4416059Samurai break; 4426059Samurai case 1: 4436059Samurai switch (ch) { 4446059Samurai case '?': 4456059Samurai ShowHelp(); 4466059Samurai break; 4476059Samurai case '-': 4486059Samurai if (loglevel > 0) { 4496059Samurai loglevel--; 4506059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 4516059Samurai } 4526059Samurai break; 4536059Samurai case '+': 4546059Samurai loglevel++; 4556059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 4566059Samurai break; 4576059Samurai#ifdef DEBUG 4586059Samurai case 'm': 4596059Samurai ShowMemMap(); 4606059Samurai break; 4616059Samurai#endif 4626059Samurai case 'p': 4636059Samurai /* 4646059Samurai * XXX: Should check carrier. 4656059Samurai */ 4666059Samurai if (LcpFsm.state <= ST_CLOSED) { 4676059Samurai VarOpenMode = OPEN_ACTIVE; 4686059Samurai PacketMode(); 4696059Samurai } 4706059Samurai break; 4716059Samurai#ifdef DEBUG 4726059Samurai case 't': 4736059Samurai ShowTimers(); 4746059Samurai break; 4756059Samurai#endif 4766059Samurai case '.': 4776059Samurai TermMode = 1; 4786059Samurai TtyCommandMode(); 4796059Samurai break; 4806059Samurai default: 4816059Samurai if (write(modem, &ch, n) < 0) 4826059Samurai fprintf(stderr, "err in write.\r\n"); 4836059Samurai break; 4846059Samurai } 4856059Samurai ttystate = 0; 4866059Samurai break; 4876059Samurai } 4886059Samurai } 4896059Samurai} 4906059Samurai 4916059Samurai 4926059Samurai/* 4936059Samurai * Here, we'll try to detect HDLC frame 4946059Samurai */ 4956059Samurai 4966059Samuraistatic char *FrameHeaders[] = { 4976735Samurai "\176\377\003\300\041", 4986735Samurai "\176\377\175\043\300\041", 4996735Samurai "\176\177\175\043\100\041", 5006735Samurai "\176\175\337\175\043\300\041", 5016735Samurai "\176\175\137\175\043\100\041", 5026059Samurai NULL, 5036059Samurai}; 5046059Samurai 5056059Samuraiu_char * 5066059SamuraiHdlcDetect(cp, n) 5076059Samuraiu_char *cp; 5086059Samuraiint n; 5096059Samurai{ 5106735Samurai char *ptr, *fp, **hp; 5116059Samurai 5126059Samurai cp[n] = '\0'; /* be sure to null terminated */ 5136059Samurai ptr = NULL; 5146059Samurai for (hp = FrameHeaders; *hp; hp++) { 5156735Samurai fp = *hp; 5166735Samurai if (DEV_IS_SYNC) 5176735Samurai fp++; 5186735Samurai if (ptr = strstr((char *)cp, fp)) 5196059Samurai break; 5206059Samurai } 5216059Samurai return((u_char *)ptr); 5226059Samurai} 5236059Samurai 5246059Samuraistatic struct pppTimer RedialTimer; 5256059Samurai 5266059Samuraistatic void 5276059SamuraiRedialTimeout() 5286059Samurai{ 5296059Samurai StopTimer(&RedialTimer); 5306059Samurai LogPrintf(LOG_PHASE, "Redialing timer expired.\n"); 5316059Samurai} 5326059Samurai 5336059Samuraistatic void 5346059SamuraiStartRedialTimer() 5356059Samurai{ 5366059Samurai LogPrintf(LOG_PHASE, "Enter pause for redialing.\n"); 5376059Samurai StopTimer(&RedialTimer); 5386059Samurai RedialTimer.state = TIMER_STOPPED; 5396059Samurai RedialTimer.load = REDIAL_PERIOD * SECTICKS; 5406059Samurai RedialTimer.func = RedialTimeout; 5416059Samurai StartTimer(&RedialTimer); 5426059Samurai} 5436059Samurai 5446059Samurai 5456059Samuraistatic void 5466059SamuraiDoLoop() 5476059Samurai{ 5486059Samurai fd_set rfds, wfds, efds; 5496059Samurai int pri, i, n, wfd; 5506059Samurai struct sockaddr_in hisaddr; 5516059Samurai struct timeval timeout, *tp; 5526059Samurai int ssize = sizeof(hisaddr); 5536059Samurai u_char *cp; 5546059Samurai u_char rbuff[MAX_MRU]; 5557001Samurai int dial_up; 5566059Samurai 5576059Samurai if (mode & MODE_DIRECT) { 5586059Samurai modem = OpenModem(mode); 5596059Samurai fprintf(stderr, "Packet mode enabled\n"); 5606059Samurai PacketMode(); 5616059Samurai } else if (mode & MODE_DEDICATED) { 5626059Samurai if (!modem) 5636059Samurai modem = OpenModem(mode); 5646059Samurai } 5656059Samurai 5666059Samurai fflush(stdout); 5676059Samurai 5686735Samurai#ifdef SIGALRM 5697001Samurai timeout.tv_sec = 0; 5706735Samurai#else 5716059Samurai timeout.tv_usec = 0; 5726735Samurai#endif 5736059Samurai 5747001Samurai dial_up = FALSE; /* XXXX */ 5756059Samurai for (;;) { 5767001Samurai if ( modem ) 5777001Samurai IpStartOutput(); 5786059Samurai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 5797001Samurai 5807001Samurai /* 5817001Samurai * If Ip packet for output is enqueued and require dial up, 5827001Samurai * Just do it! 5837001Samurai */ 5847001Samurai if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ 5857001Samurai#ifdef DEBUG 5867001Samurai logprintf("going to dial: modem = %d\n", modem); 5877001Samurai#endif 5887001Samurai modem = OpenModem(mode); 5897001Samurai if (modem < 0) { 5907001Samurai modem = 0; /* Set intial value for next OpenModem */ 5917001Samurai StartRedialTimer(); 5927001Samurai } else { 5937001Samurai if (DialModem()) { 5947001Samurai sleep(1); /* little pause to allow peer starts */ 5957001Samurai ModemTimeout(); 5967001Samurai PacketMode(); 5977001Samurai dial_up = FALSE; 5987001Samurai } else { 5997001Samurai CloseModem(); 6007001Samurai /* Dial failed. Keep quite during redial wait period. */ 6017001Samurai StartRedialTimer(); 6027001Samurai } 6037001Samurai } 6047001Samurai } 6057001Samurai if (modem) { 6067001Samurai FD_SET(modem, &rfds); 6077001Samurai FD_SET(modem, &efds); 6087001Samurai if (ModemQlen() > 0) { 6097001Samurai FD_SET(modem, &wfds); 6107001Samurai } 6117001Samurai } 6126059Samurai if (server > 0) FD_SET(server, &rfds); 6136059Samurai 6146059Samurai /* *** IMPORTANT *** 6156059Samurai * 6166059Samurai * CPU is serviced every TICKUNIT micro seconds. 6176059Samurai * This value must be chosen with great care. If this values is 6186059Samurai * too big, it results loss of characters from modem and poor responce. 6196059Samurai * If this values is too small, ppp process eats many CPU time. 6206059Samurai */ 6216735Samurai#ifndef SIGALRM 6226059Samurai usleep(TICKUNIT); 6236059Samurai TimerService(); 6246735Samurai#endif 6256059Samurai 6267001Samurai FD_SET(tun_in, &rfds); 6276059Samurai if (netfd > -1) { 6286059Samurai FD_SET(netfd, &rfds); 6296059Samurai FD_SET(netfd, &efds); 6306059Samurai } 6317001Samurai 6327001Samurai 6336735Samurai#ifndef SIGALRM 6346059Samurai /* 6357001Samurai * Normally, select() will not block because modem is writable. 6367001Samurai * In AUTO mode, select will block until we find packet from tun 6376059Samurai */ 6386059Samurai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 6396059Samurai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 6406735Samurai#else 6417001Samurai /* 6427001Samurai * When SIGALRM timer is running, a select function will be 6437001Samurai * return -1 and EINTR after a Time Service signal hundler 6447001Samurai * is done. 6457001Samurai */ 6466735Samurai i = select(tun_in+10, &rfds, &wfds, &efds, NULL); 6476735Samurai#endif 6487001Samurai if ( i == 0 ) { 6497001Samurai continue; 6506059Samurai } 6516735Samurai 6527001Samurai if ( i < 0 ) { 6537001Samurai if ( errno == EINTR ) { 6547001Samurai continue; /* Got SIGALRM, Do check a queue for dailing */ 6557001Samurai } 6567001Samurai perror("select"); 6577001Samurai break; 6587001Samurai } 6597001Samurai 6606059Samurai if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) { 6616059Samurai logprintf("Exception detected.\n"); 6626059Samurai break; 6636059Samurai } 6646059Samurai 6656059Samurai if (server > 0 && FD_ISSET(server, &rfds)) { 6666059Samurai#ifdef DEBUG 6676059Samurai logprintf("connected to client.\n"); 6686059Samurai#endif 6696059Samurai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 6706059Samurai if (netfd > 0) { 6716059Samurai write(wfd, "already in use.\n", 16); 6726059Samurai close(wfd); 6736059Samurai continue; 6746059Samurai } else 6756059Samurai netfd = wfd; 6766059Samurai if (dup2(netfd, 1) < 0) 6776059Samurai perror("dup2"); 6786059Samurai mode |= MODE_INTER; 6796059Samurai Greetings(); 6806764Samurai switch ( LocalAuthInit() ) { 6816764Samurai case NOT_FOUND: 6826764Samurai fprintf(stdout,LAUTH_M1); 6836764Samurai fprintf(stdout,LAUTH_M2); 6846764Samurai fflush(stdout); 6856764Samurai /* Fall down */ 6866764Samurai case VALID: 6876764Samurai VarLocalAuth = LOCAL_AUTH; 6886764Samurai break; 6896764Samurai default: 6906764Samurai break; 6916764Samurai } 6926059Samurai (void) IsInteractive(); 6936059Samurai Prompt(0); 6946059Samurai } 6956059Samurai 6966059Samurai if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds)) { 6976059Samurai /* something to read from tty */ 6986059Samurai ReadTty(); 6996059Samurai } 7006059Samurai if (modem) { 7016059Samurai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 7026059Samurai ModemStartOutput(modem); 7036059Samurai } 7046059Samurai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 7056735Samurai if (LcpFsm.state <= ST_CLOSED) 7066735Samurai usleep(10000); 7076059Samurai n = read(modem, rbuff, sizeof(rbuff)); 7086059Samurai if ((mode & MODE_DIRECT) && n <= 0) { 7096059Samurai DownConnection(); 7106059Samurai } else 7116059Samurai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 7126059Samurai 7136059Samurai if (LcpFsm.state <= ST_CLOSED) { 7146059Samurai /* 7156059Samurai * In dedicated mode, we just discard input until LCP is started. 7166059Samurai */ 7176059Samurai if (!(mode & MODE_DEDICATED)) { 7186059Samurai cp = HdlcDetect(rbuff, n); 7196059Samurai if (cp) { 7206059Samurai /* 7216059Samurai * LCP packet is detected. Turn ourselves into packet mode. 7226059Samurai */ 7236059Samurai if (cp != rbuff) { 7246059Samurai write(1, rbuff, cp - rbuff); 7256059Samurai write(1, "\r\n", 2); 7266059Samurai } 7276059Samurai PacketMode(); 7286059Samurai#ifdef notdef 7296059Samurai AsyncInput(cp, n - (cp - rbuff)); 7306059Samurai#endif 7316059Samurai } else 7326059Samurai write(1, rbuff, n); 7336059Samurai } 7346059Samurai } else { 7356059Samurai if (n > 0) 7366059Samurai AsyncInput(rbuff, n); 7376059Samurai#ifdef notdef 7386059Samurai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 7396059Samurai#endif 7406059Samurai } 7416059Samurai } 7426059Samurai } 7437001Samurai 7446059Samurai if (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 7456059Samurai /* 7466059Samurai * If there are many packets queued, wait until they are drained. 7476059Samurai */ 7486059Samurai if (ModemQlen() > 5) 7496059Samurai continue; 7507001Samurai 7516059Samurai n = read(tun_in, rbuff, sizeof(rbuff)); 7526059Samurai if (n < 0) { 7536059Samurai perror("read from tun"); 7546059Samurai continue; 7556059Samurai } 7566059Samurai /* 7576059Samurai * Process on-demand dialup. Output packets are queued within tunnel 7586059Samurai * device until IPCP is opened. 7596059Samurai */ 7606059Samurai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 7617001Samurai pri = PacketCheck(rbuff, n, FL_DIAL); 7626059Samurai if (pri >= 0) { 7636059Samurai IpEnqueue(pri, rbuff, n); 7647001Samurai dial_up = TRUE; /* XXX */ 7656059Samurai } 7666059Samurai continue; 7676059Samurai } 7687001Samurai pri = PacketCheck(rbuff, n, FL_OUT); 7696059Samurai if (pri >= 0) 7706059Samurai IpEnqueue(pri, rbuff, n); 7716059Samurai } 7726059Samurai } 7736059Samurai logprintf("job done.\n"); 7746059Samurai} 775