main.c revision 6764
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 * 206764Samurai * $Id: main.c,v 1.2 1995/02/26 12:17:41 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" 436059Samurai 446764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 456764Samurai#define LAUTH_M2 "Warning: All manipulation is allowed by anyone in a world\n" 466764Samurai 476735Samurai#ifndef O_NONBLOCK 486735Samurai#ifdef O_NDELAY 496735Samurai#define O_NONBLOCK O_NDELAY 506735Samurai#endif 516735Samurai#endif 526735Samurai 536059Samuraiextern void VjInit(), AsyncInit(); 546059Samuraiextern void AsyncInput(), IpOutput(); 556059Samuraiextern int SelectSystem(); 566059Samurai 576059Samuraiextern void DecodeCommand(), Prompt(); 586059Samuraiextern int IsInteractive(); 596059Samuraiextern struct in_addr ifnetmask; 606059Samuraistatic void DoLoop(void); 616059Samurai 626059Samuraistatic struct termios oldtio; /* Original tty mode */ 636059Samuraistatic struct termios comtio; /* Command level tty mode */ 646059Samuraistatic int TermMode; 656059Samuraistatic int server, update; 666059Samuraistruct sockaddr_in ifsin; 676059Samurai 686059Samuraistatic void 696059SamuraiTtyInit() 706059Samurai{ 716059Samurai struct termios newtio; 726059Samurai int stat; 736059Samurai 746059Samurai stat = fcntl(0, F_GETFL, 0); 756059Samurai stat |= O_NONBLOCK; 766059Samurai fcntl(0, F_SETFL, stat); 776059Samurai newtio = oldtio; 786059Samurai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 796059Samurai newtio.c_iflag = 0; 806059Samurai newtio.c_oflag &= ~OPOST; 816059Samurai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 826059Samurai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 836059Samurai newtio.c_cc[VMIN] = 1; 846059Samurai newtio.c_cc[VTIME] = 0; 856059Samurai newtio.c_cflag |= CS8; 866735Samurai tcsetattr(0, TCSADRAIN, &newtio); 876059Samurai comtio = newtio; 886059Samurai} 896059Samurai 906059Samurai/* 916059Samurai * Set tty into command mode. We allow canonical input and echo processing. 926059Samurai */ 936059Samuraistatic void 946059SamuraiTtyCommandMode() 956059Samurai{ 966059Samurai struct termios newtio; 976059Samurai int stat; 986059Samurai 996059Samurai if (!(mode & MODE_INTER)) 1006059Samurai return; 1016735Samurai tcgetattr(0, &newtio); 1026059Samurai newtio.c_lflag |= (ECHO|ICANON); 1036059Samurai newtio.c_iflag = oldtio.c_iflag; 1046059Samurai newtio.c_oflag |= OPOST; 1056735Samurai tcsetattr(0, TCSADRAIN, &newtio); 1066059Samurai stat = fcntl(0, F_GETFL, 0); 1076059Samurai stat |= O_NONBLOCK; 1086059Samurai fcntl(0, F_SETFL, stat); 1096059Samurai TermMode = 0; 1106059Samurai Prompt(0); 1116059Samurai} 1126059Samurai 1136059Samurai/* 1146059Samurai * Set tty into terminal mode which is used while we invoke term command. 1156059Samurai */ 1166059Samuraivoid 1176059SamuraiTtyTermMode() 1186059Samurai{ 1196059Samurai int stat; 1206059Samurai 1216735Samurai tcsetattr(0, TCSADRAIN, &comtio); 1226059Samurai stat = fcntl(0, F_GETFL, 0); 1236059Samurai stat &= ~O_NONBLOCK; 1246059Samurai fcntl(0, F_SETFL, stat); 1256059Samurai TermMode = 1; 1266059Samurai} 1276059Samurai 1286059Samuraivoid 1296059SamuraiCleanup(excode) 1306059Samuraiint excode; 1316059Samurai{ 1326059Samurai int stat; 1336059Samurai 1346059Samurai OsLinkdown(); 1356735Samurai#ifdef notdef 1366059Samurai stat = fcntl(0, F_GETFL, 0); 1376059Samurai stat &= ~O_NONBLOCK; 1386059Samurai fcntl(0, F_SETFL, stat); 1396735Samurai tcsetattr(0, TCSANOW, &oldtio); 1406735Samurai#endif 1416059Samurai OsCloseLink(1); 1426059Samurai sleep(1); 1436059Samurai if (mode & MODE_AUTO) 1446059Samurai DeleteIfRoutes(1); 1456059Samurai OsInterfaceDown(1); 1466059Samurai LogPrintf(LOG_PHASE, "PPP Terminated.\n"); 1476059Samurai LogClose(); 1486059Samurai if (server > 0) 1496059Samurai close(server); 1506735Samurai#ifndef notdef 1516735Samurai stat = fcntl(0, F_GETFL, 0); 1526735Samurai stat &= ~O_NONBLOCK; 1536735Samurai fcntl(0, F_SETFL, stat); 1546735Samurai tcsetattr(0, TCSANOW, &oldtio); 1556735Samurai#endif 1566059Samurai 1576059Samurai exit(excode); 1586059Samurai} 1596059Samurai 1606059Samuraistatic void 1616059SamuraiHangup() 1626059Samurai{ 1636059Samurai LogPrintf(LOG_PHASE, "SIGHUP\n"); 1646059Samurai signal(SIGHUP, Hangup); 1656059Samurai Cleanup(EX_HANGUP); 1666059Samurai} 1676059Samurai 1686059Samuraistatic void 1696059SamuraiCloseSession() 1706059Samurai{ 1716059Samurai LogPrintf(LOG_PHASE, "SIGTERM\n"); 1726059Samurai LcpClose(); 1736059Samurai Cleanup(EX_TERM); 1746059Samurai} 1756059Samurai 1766059Samuraivoid 1776059SamuraiUsage() 1786059Samurai{ 1796059Samurai fprintf(stderr, "Usage: ppp [-auto | -direct -dedicated] [system]\n"); 1806059Samurai exit(EX_START); 1816059Samurai} 1826059Samurai 1836059Samuraivoid 1846059SamuraiProcessArgs(int argc, char **argv) 1856059Samurai{ 1866059Samurai int optc; 1876059Samurai char *cp; 1886059Samurai 1896059Samurai optc = 0; 1906059Samurai while (argc > 0 && **argv == '-') { 1916059Samurai cp = *argv + 1; 1926059Samurai if (strcmp(cp, "auto") == 0) 1936059Samurai mode |= MODE_AUTO; 1946059Samurai else if (strcmp(cp, "direct") == 0) 1956059Samurai mode |= MODE_DIRECT; 1966059Samurai else if (strcmp(cp, "dedicated") == 0) 1976059Samurai mode |= MODE_DEDICATED; 1986059Samurai else 1996059Samurai Usage(); 2006059Samurai optc++; 2016059Samurai argv++; argc--; 2026059Samurai } 2036059Samurai if (argc > 1) { 2046059Samurai fprintf(stderr, "specify only one system label.\n"); 2056059Samurai exit(EX_START); 2066059Samurai } 2076059Samurai if (argc == 1) dstsystem = *argv; 2086059Samurai 2096059Samurai if (optc > 1) { 2106059Samurai fprintf(stderr, "specify only one mode.\n"); 2116059Samurai exit(EX_START); 2126059Samurai } 2136059Samurai} 2146059Samurai 2156059Samuraistatic void 2166059SamuraiGreetings() 2176059Samurai{ 2186059Samurai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 2196059Samurai fflush(stdout); 2206059Samurai} 2216059Samurai 2226059Samuraivoid 2236059Samuraimain(argc, argv) 2246059Samuraiint argc; 2256059Samuraichar **argv; 2266059Samurai{ 2276059Samurai int tunno; 2286059Samurai int on = 1; 2296059Samurai 2306059Samurai argc--; argv++; 2316059Samurai 2326059Samurai mode = MODE_INTER; /* default operation is interactive mode */ 2336059Samurai netfd = -1; 2346059Samurai ProcessArgs(argc, argv); 2356059Samurai Greetings(); 2366059Samurai GetUid(); 2376059Samurai IpcpDefAddress(); 2386059Samurai 2396059Samurai if (SelectSystem("default", CONFFILE) < 0) { 2406059Samurai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 2416059Samurai } 2426059Samurai 2436059Samurai if (LogOpen()) 2446059Samurai exit(EX_START); 2456059Samurai 2466735Samurai switch ( LocalAuthInit() ) { 2476735Samurai case NOT_FOUND: 2486764Samurai fprintf(stderr,LAUTH_M1); 2496764Samurai fprintf(stderr,LAUTH_M2); 2506764Samurai fflush (stderr); 2516764Samurai /* Fall down */ 2526764Samurai case VALID: 2536735Samurai VarLocalAuth = LOCAL_AUTH; 2546735Samurai break; 2556735Samurai default: 2566735Samurai break; 2576735Samurai } 2586735Samurai 2596059Samurai if (OpenTunnel(&tunno) < 0) { 2606059Samurai perror("open_tun"); 2616059Samurai exit(EX_START); 2626059Samurai } 2636059Samurai 2646059Samurai if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 2656059Samurai mode &= ~MODE_INTER; 2666059Samurai if (mode & MODE_INTER) { 2676059Samurai printf("Interactive mode\n"); 2686059Samurai netfd = 0; 2696059Samurai } else if (mode & MODE_AUTO) { 2706059Samurai printf("Automatic mode\n"); 2716059Samurai if (dstsystem == NULL) { 2726059Samurai fprintf(stderr, "Destination system must be specified in auto mode.\n"); 2736059Samurai exit(EX_START); 2746059Samurai } 2756059Samurai } 2766059Samurai 2776735Samurai tcgetattr(0, &oldtio); /* Save original tty mode */ 2786059Samurai 2796059Samurai signal(SIGHUP, Hangup); 2806059Samurai signal(SIGTERM, CloseSession); 2816059Samurai signal(SIGINT, CloseSession); 2826735Samurai#ifdef SIGSEGV 2836059Samurai signal(SIGSEGV, Hangup); 2846735Samurai#endif 2856735Samurai#ifdef SIGPIPE 2866735Samurai signal(SIGPIPE, Hangup); 2876735Samurai#endif 2886735Samurai#ifdef SIGALRM 2896735Samurai signal(SIGALRM, SIG_IGN); 2906735Samurai#endif 2916059Samurai 2926059Samurai if (dstsystem) { 2936059Samurai if (SelectSystem(dstsystem, CONFFILE) < 0) { 2946059Samurai fprintf(stderr, "Destination system not found in conf file.\n"); 2956059Samurai Cleanup(EX_START); 2966059Samurai } 2976059Samurai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 2986059Samurai fprintf(stderr, "Must specify dstaddr with auto mode.\n"); 2996059Samurai Cleanup(EX_START); 3006059Samurai } 3016059Samurai } 3026059Samurai if (mode & MODE_DIRECT) 3036059Samurai printf("Packet mode enabled.\n"); 3046059Samurai 3056059Samurai#ifdef notdef 3066059Samurai if (mode & MODE_AUTO) { 3076059Samurai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 3086059Samurai } 3096059Samurai#endif 3106059Samurai 3116059Samurai if (!(mode & MODE_INTER)) { 3126059Samurai int port = SERVER_PORT + tunno; 3136059Samurai /* 3146059Samurai * Create server socket and listen at there. 3156059Samurai */ 3166059Samurai server = socket(PF_INET, SOCK_STREAM, 0); 3176059Samurai if (server < 0) { 3186059Samurai perror("socket"); 3196059Samurai Cleanup(EX_SOCK); 3206059Samurai } 3216059Samurai ifsin.sin_family = AF_INET; 3226059Samurai ifsin.sin_addr.s_addr = INADDR_ANY; 3236059Samurai ifsin.sin_port = htons(port); 3246059Samurai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 3256059Samurai perror("bind"); 3266059Samurai if (errno == EADDRINUSE) 3276059Samurai fprintf(stderr, "Wait for a while, then try again.\n"); 3286059Samurai Cleanup(EX_SOCK); 3296059Samurai } 3306059Samurai listen(server, 5); 3316059Samurai 3326059Samurai DupLog(); 3336059Samurai if (!(mode & MODE_DIRECT)) { 3346059Samurai if (fork()) 3356059Samurai exit(0); 3366059Samurai } 3376059Samurai LogPrintf(LOG_PHASE, "Listening at %d.\n", port); 3386059Samurai#ifdef DOTTYINIT 3396735Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 3406059Samurai#else 3416059Samurai if (mode & MODE_DIRECT) { 3426059Samurai#endif 3436059Samurai TtyInit(); 3446059Samurai } else { 3456059Samurai setsid(); /* detach control tty */ 3466059Samurai } 3476059Samurai } else { 3486059Samurai server = -1; 3496059Samurai TtyInit(); 3506059Samurai TtyCommandMode(); 3516059Samurai } 3526059Samurai LogPrintf(LOG_PHASE, "PPP Started.\n"); 3536059Samurai 3546059Samurai 3556059Samurai do 3566059Samurai DoLoop(); 3576059Samurai while (mode & MODE_DEDICATED); 3586059Samurai 3596059Samurai Cleanup(EX_DONE); 3606059Samurai} 3616059Samurai 3626059Samurai/* 3636059Samurai * Turn into packet mode, where we speek PPP. 3646059Samurai */ 3656059Samuraivoid 3666059SamuraiPacketMode() 3676059Samurai{ 3686059Samurai if (RawModem(modem) < 0) { 3696059Samurai fprintf(stderr, "Not connected.\r\n"); 3706059Samurai return; 3716059Samurai } 3726059Samurai 3736059Samurai AsyncInit(); 3746059Samurai VjInit(); 3756059Samurai LcpInit(); 3766059Samurai IpcpInit(); 3776059Samurai CcpInit(); 3786059Samurai LcpUp(); 3796059Samurai 3806059Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 3816059Samurai LcpOpen(OPEN_ACTIVE); 3826059Samurai else 3836059Samurai LcpOpen(VarOpenMode); 3846059Samurai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 3856059Samurai TtyCommandMode(); 3866059Samurai fprintf(stderr, "Packet mode.\r\n"); 3876059Samurai } 3886059Samurai} 3896059Samurai 3906059Samuraistatic void 3916059SamuraiShowHelp() 3926059Samurai{ 3936059Samurai fprintf(stderr, "Following commands are available\r\n"); 3946059Samurai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 3956059Samurai fprintf(stderr, " ~.\tTerminate program\r\n"); 3966059Samurai} 3976059Samurai 3986059Samuraistatic void 3996059SamuraiReadTty() 4006059Samurai{ 4016059Samurai int n; 4026059Samurai char ch; 4036059Samurai static int ttystate; 4046059Samurai#define MAXLINESIZE 200 4056059Samurai char linebuff[MAXLINESIZE]; 4066059Samurai 4076059Samurai#ifdef DEBUG 4086059Samurai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 4096059Samurai#endif 4106059Samurai if (!TermMode) { 4116059Samurai n = read(netfd, linebuff, sizeof(linebuff)-1); 4126735Samurai if (n > 0) { 4136059Samurai DecodeCommand(linebuff, n, 1); 4146735Samurai } else { 4156059Samurai#ifdef DEBUG 4166059Samurai logprintf("connection closed.\n"); 4176059Samurai#endif 4186059Samurai close(netfd); 4196059Samurai netfd = -1; 4206059Samurai mode &= ~MODE_INTER; 4216059Samurai } 4226059Samurai return; 4236059Samurai } 4246059Samurai 4256059Samurai /* 4266059Samurai * We are in terminal mode, decode special sequences 4276059Samurai */ 4286059Samurai n = read(0, &ch, 1); 4296059Samurai#ifdef DEBUG 4306059Samurai logprintf("got %d bytes\n", n); 4316059Samurai#endif 4326059Samurai 4336059Samurai if (n > 0) { 4346059Samurai switch (ttystate) { 4356059Samurai case 0: 4366059Samurai if (ch == '~') 4376059Samurai ttystate++; 4386059Samurai else 4396059Samurai write(modem, &ch, n); 4406059Samurai break; 4416059Samurai case 1: 4426059Samurai switch (ch) { 4436059Samurai case '?': 4446059Samurai ShowHelp(); 4456059Samurai break; 4466059Samurai case '-': 4476059Samurai if (loglevel > 0) { 4486059Samurai loglevel--; 4496059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 4506059Samurai } 4516059Samurai break; 4526059Samurai case '+': 4536059Samurai loglevel++; 4546059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 4556059Samurai break; 4566059Samurai#ifdef DEBUG 4576059Samurai case 'm': 4586059Samurai ShowMemMap(); 4596059Samurai break; 4606059Samurai#endif 4616059Samurai case 'p': 4626059Samurai /* 4636059Samurai * XXX: Should check carrier. 4646059Samurai */ 4656059Samurai if (LcpFsm.state <= ST_CLOSED) { 4666059Samurai VarOpenMode = OPEN_ACTIVE; 4676059Samurai PacketMode(); 4686059Samurai } 4696059Samurai break; 4706059Samurai#ifdef DEBUG 4716059Samurai case 't': 4726059Samurai ShowTimers(); 4736059Samurai break; 4746059Samurai#endif 4756059Samurai case '.': 4766059Samurai TermMode = 1; 4776059Samurai TtyCommandMode(); 4786059Samurai break; 4796059Samurai default: 4806059Samurai if (write(modem, &ch, n) < 0) 4816059Samurai fprintf(stderr, "err in write.\r\n"); 4826059Samurai break; 4836059Samurai } 4846059Samurai ttystate = 0; 4856059Samurai break; 4866059Samurai } 4876059Samurai } 4886059Samurai} 4896059Samurai 4906059Samurai 4916059Samurai/* 4926059Samurai * Here, we'll try to detect HDLC frame 4936059Samurai */ 4946059Samurai 4956059Samuraistatic char *FrameHeaders[] = { 4966735Samurai "\176\377\003\300\041", 4976735Samurai "\176\377\175\043\300\041", 4986735Samurai "\176\177\175\043\100\041", 4996735Samurai "\176\175\337\175\043\300\041", 5006735Samurai "\176\175\137\175\043\100\041", 5016059Samurai NULL, 5026059Samurai}; 5036059Samurai 5046059Samuraiu_char * 5056059SamuraiHdlcDetect(cp, n) 5066059Samuraiu_char *cp; 5076059Samuraiint n; 5086059Samurai{ 5096735Samurai char *ptr, *fp, **hp; 5106059Samurai 5116059Samurai cp[n] = '\0'; /* be sure to null terminated */ 5126059Samurai ptr = NULL; 5136059Samurai for (hp = FrameHeaders; *hp; hp++) { 5146735Samurai fp = *hp; 5156735Samurai if (DEV_IS_SYNC) 5166735Samurai fp++; 5176735Samurai if (ptr = strstr((char *)cp, fp)) 5186059Samurai break; 5196059Samurai } 5206059Samurai return((u_char *)ptr); 5216059Samurai} 5226059Samurai 5236059Samuraistatic struct pppTimer RedialTimer; 5246059Samurai 5256059Samuraistatic void 5266059SamuraiRedialTimeout() 5276059Samurai{ 5286059Samurai StopTimer(&RedialTimer); 5296059Samurai LogPrintf(LOG_PHASE, "Redialing timer expired.\n"); 5306059Samurai} 5316059Samurai 5326059Samuraistatic void 5336059SamuraiStartRedialTimer() 5346059Samurai{ 5356059Samurai LogPrintf(LOG_PHASE, "Enter pause for redialing.\n"); 5366059Samurai StopTimer(&RedialTimer); 5376059Samurai RedialTimer.state = TIMER_STOPPED; 5386059Samurai RedialTimer.load = REDIAL_PERIOD * SECTICKS; 5396059Samurai RedialTimer.func = RedialTimeout; 5406059Samurai StartTimer(&RedialTimer); 5416059Samurai} 5426059Samurai 5436059Samurai 5446059Samuraistatic void 5456059SamuraiDoLoop() 5466059Samurai{ 5476059Samurai fd_set rfds, wfds, efds; 5486059Samurai int pri, i, n, wfd; 5496059Samurai struct sockaddr_in hisaddr; 5506059Samurai struct timeval timeout, *tp; 5516059Samurai int ssize = sizeof(hisaddr); 5526059Samurai u_char *cp; 5536059Samurai u_char rbuff[MAX_MRU]; 5546735Samurai struct itimerval itimer; 5556059Samurai 5566059Samurai if (mode & MODE_DIRECT) { 5576059Samurai modem = OpenModem(mode); 5586059Samurai fprintf(stderr, "Packet mode enabled\n"); 5596059Samurai PacketMode(); 5606059Samurai } else if (mode & MODE_DEDICATED) { 5616059Samurai if (!modem) 5626059Samurai modem = OpenModem(mode); 5636059Samurai } 5646059Samurai 5656059Samurai fflush(stdout); 5666059Samurai 5676059Samurai timeout.tv_sec = 0;; 5686735Samurai#ifdef SIGALRM 5696735Samurai signal(SIGALRM, (void (*)(int))TimerService); 5706735Samurai itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0; 5716735Samurai itimer.it_interval.tv_usec = itimer.it_value.tv_usec = TICKUNIT; 5726735Samurai setitimer(ITIMER_REAL, &itimer, NULL); 5736735Samurai#else 5746059Samurai timeout.tv_usec = 0; 5756735Samurai#endif 5766059Samurai 5776059Samurai for (;;) { 5786059Samurai IpStartOutput(); 5796059Samurai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 5806059Samurai FD_SET(tun_in, &rfds); 5816059Samurai if (server > 0) FD_SET(server, &rfds); 5826059Samurai 5836059Samurai /* *** IMPORTANT *** 5846059Samurai * 5856059Samurai * CPU is serviced every TICKUNIT micro seconds. 5866059Samurai * This value must be chosen with great care. If this values is 5876059Samurai * too big, it results loss of characters from modem and poor responce. 5886059Samurai * If this values is too small, ppp process eats many CPU time. 5896059Samurai */ 5906735Samurai#ifndef SIGALRM 5916059Samurai usleep(TICKUNIT); 5926059Samurai TimerService(); 5936735Samurai#endif 5946059Samurai 5956059Samurai if (modem) { 5966059Samurai FD_SET(modem, &rfds); 5976059Samurai FD_SET(modem, &efds); 5986735Samurai if (ModemQlen() > 0) { 5996735Samurai FD_SET(modem, &wfds); 6006735Samurai } 6016059Samurai } 6026059Samurai if (netfd > -1) { 6036059Samurai FD_SET(netfd, &rfds); 6046059Samurai FD_SET(netfd, &efds); 6056059Samurai } 6066735Samurai#ifndef SIGALRM 6076059Samurai /* 6086059Samurai * Normally, slect() will not block because modem is writable. 6096059Samurai * In AUTO mode, select will block until we find packet from tun. 6106059Samurai * However, we have to run ourselves while we are in redial wait state. 6116059Samurai */ 6126059Samurai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 6136059Samurai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 6146735Samurai#else 6156735Samurai i = select(tun_in+10, &rfds, &wfds, &efds, NULL); 6166735Samurai#endif 6176059Samurai if (i == 0) { 6186059Samurai continue; 6196059Samurai } 6206735Samurai 6216059Samurai if (i < 0) { 6226735Samurai if (errno == EINTR) 6236735Samurai continue; 6246059Samurai perror("select"); 6256059Samurai break; 6266059Samurai } 6276059Samurai if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) { 6286059Samurai logprintf("Exception detected.\n"); 6296059Samurai break; 6306059Samurai } 6316059Samurai 6326059Samurai if (server > 0 && FD_ISSET(server, &rfds)) { 6336059Samurai#ifdef DEBUG 6346059Samurai logprintf("connected to client.\n"); 6356059Samurai#endif 6366059Samurai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 6376059Samurai if (netfd > 0) { 6386059Samurai write(wfd, "already in use.\n", 16); 6396059Samurai close(wfd); 6406059Samurai continue; 6416059Samurai } else 6426059Samurai netfd = wfd; 6436059Samurai if (dup2(netfd, 1) < 0) 6446059Samurai perror("dup2"); 6456059Samurai mode |= MODE_INTER; 6466059Samurai Greetings(); 6476764Samurai switch ( LocalAuthInit() ) { 6486764Samurai case NOT_FOUND: 6496764Samurai fprintf(stdout,LAUTH_M1); 6506764Samurai fprintf(stdout,LAUTH_M2); 6516764Samurai fflush(stdout); 6526764Samurai /* Fall down */ 6536764Samurai case VALID: 6546764Samurai VarLocalAuth = LOCAL_AUTH; 6556764Samurai break; 6566764Samurai default: 6576764Samurai break; 6586764Samurai } 6596059Samurai (void) IsInteractive(); 6606059Samurai Prompt(0); 6616059Samurai } 6626059Samurai 6636059Samurai if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds)) { 6646059Samurai /* something to read from tty */ 6656059Samurai ReadTty(); 6666059Samurai } 6676059Samurai if (modem) { 6686059Samurai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 6696059Samurai ModemStartOutput(modem); 6706059Samurai } 6716059Samurai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 6726735Samurai if (LcpFsm.state <= ST_CLOSED) 6736735Samurai usleep(10000); 6746059Samurai n = read(modem, rbuff, sizeof(rbuff)); 6756059Samurai if ((mode & MODE_DIRECT) && n <= 0) { 6766059Samurai DownConnection(); 6776059Samurai } else 6786059Samurai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 6796059Samurai 6806059Samurai if (LcpFsm.state <= ST_CLOSED) { 6816059Samurai /* 6826059Samurai * In dedicated mode, we just discard input until LCP is started. 6836059Samurai */ 6846059Samurai if (!(mode & MODE_DEDICATED)) { 6856059Samurai cp = HdlcDetect(rbuff, n); 6866059Samurai if (cp) { 6876059Samurai /* 6886059Samurai * LCP packet is detected. Turn ourselves into packet mode. 6896059Samurai */ 6906059Samurai if (cp != rbuff) { 6916059Samurai write(1, rbuff, cp - rbuff); 6926059Samurai write(1, "\r\n", 2); 6936059Samurai } 6946059Samurai PacketMode(); 6956059Samurai#ifdef notdef 6966059Samurai AsyncInput(cp, n - (cp - rbuff)); 6976059Samurai#endif 6986059Samurai } else 6996059Samurai write(1, rbuff, n); 7006059Samurai } 7016059Samurai } else { 7026059Samurai if (n > 0) 7036059Samurai AsyncInput(rbuff, n); 7046059Samurai#ifdef notdef 7056059Samurai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 7066059Samurai#endif 7076059Samurai } 7086059Samurai } 7096059Samurai } 7106059Samurai if (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 7116059Samurai /* 7126059Samurai * If there are many packets queued, wait until they are drained. 7136059Samurai */ 7146059Samurai if (ModemQlen() > 5) 7156059Samurai continue; 7166059Samurai 7176059Samurai n = read(tun_in, rbuff, sizeof(rbuff)); 7186059Samurai if (n < 0) { 7196059Samurai perror("read from tun"); 7206059Samurai continue; 7216059Samurai } 7226059Samurai /* 7236059Samurai * Process on-demand dialup. Output packets are queued within tunnel 7246059Samurai * device until IPCP is opened. 7256059Samurai */ 7266059Samurai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 7276059Samurai pri = PacketCheck(rbuff, n, 2); 7286059Samurai if (pri >= 0) { 7296059Samurai if (RedialTimer.state == TIMER_RUNNING) { 7306059Samurai /* 7316059Samurai * We are in redial wait state. Ignore packet. 7326059Samurai */ 7336059Samurai continue; 7346059Samurai } 7356059Samurai modem = OpenModem(mode); 7366059Samurai#ifdef DEBUG 7376059Samurai logprintf("going to dial: modem = %d\n", modem); 7386059Samurai#endif 7396059Samurai if (modem < 0) { 7406059Samurai printf("failed to open modem.\n"); 7416059Samurai Cleanup(EX_MODEM); 7426059Samurai } 7436059Samurai 7446059Samurai if (DialModem()) { 7456059Samurai sleep(1); /* little pause to allow peer starts */ 7466735Samurai ModemTimeout(); 7476059Samurai PacketMode(); 7486059Samurai } else { 7496059Samurai CloseModem(); 7506059Samurai /* Dial failed. Keep quite during redial wait period. */ 7516059Samurai /* XXX: We shoud implement re-dial */ 7526059Samurai StartRedialTimer(); 7536059Samurai continue; 7546059Samurai } 7556059Samurai IpEnqueue(pri, rbuff, n); 7566059Samurai } 7576059Samurai continue; 7586059Samurai } 7596059Samurai pri = PacketCheck(rbuff, n, 1); 7606059Samurai if (pri >= 0) 7616059Samurai IpEnqueue(pri, rbuff, n); 7626059Samurai } 7636059Samurai } 7646735Samurai#ifdef SIGALRM 7656735Samurai itimer.it_value.tv_usec = itimer.it_value.tv_sec = 0; 7666735Samurai setitimer(ITIMER_REAL, &itimer, NULL); 7676735Samurai signal(SIGALRM, SIG_DFL); 7686735Samurai#endif 7696059Samurai logprintf("job done.\n"); 7706059Samurai} 771