main.c revision 13389
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 * 2013389Sphk * $Id: main.c,v 1.12 1996/01/10 21:27:53 phk Exp $ 218857Srgrimes * 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> 2811336Samurai#include <paths.h> 296059Samurai#include <sys/time.h> 306059Samurai#include <termios.h> 316059Samurai#include <signal.h> 326059Samurai#include <sys/wait.h> 336059Samurai#include <errno.h> 346059Samurai#include <netdb.h> 356059Samurai#include <sys/socket.h> 366059Samurai#include <arpa/inet.h> 376059Samurai#include "modem.h" 386059Samurai#include "os.h" 396059Samurai#include "hdlc.h" 4013389Sphk#include "ccp.h" 416059Samurai#include "lcp.h" 426059Samurai#include "ipcp.h" 436059Samurai#include "vars.h" 446735Samurai#include "auth.h" 457001Samurai#include "filter.h" 4613389Sphk#include "systems.h" 4713389Sphk#include "ip.h" 486059Samurai 496764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 509410Sasami#define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n" 516764Samurai 526735Samurai#ifndef O_NONBLOCK 536735Samurai#ifdef O_NDELAY 546735Samurai#define O_NONBLOCK O_NDELAY 556735Samurai#endif 566735Samurai#endif 576735Samurai 586059Samuraiextern void VjInit(), AsyncInit(); 596059Samuraiextern void AsyncInput(), IpOutput(); 606059Samuraiextern int SelectSystem(); 616059Samurai 626059Samuraiextern void DecodeCommand(), Prompt(); 636059Samuraiextern int IsInteractive(); 646059Samuraiextern struct in_addr ifnetmask; 656059Samuraistatic void DoLoop(void); 6610528Samuraistatic void TerminalStop(); 676059Samurai 686059Samuraistatic struct termios oldtio; /* Original tty mode */ 696059Samuraistatic struct termios comtio; /* Command level tty mode */ 706059Samuraistatic int TermMode; 7113379Sphkstatic int server; 726059Samuraistruct sockaddr_in ifsin; 7311336Samuraichar pid_filename[128]; 746059Samurai 756059Samuraistatic void 766059SamuraiTtyInit() 776059Samurai{ 786059Samurai struct termios newtio; 796059Samurai int stat; 806059Samurai 816059Samurai stat = fcntl(0, F_GETFL, 0); 826059Samurai stat |= O_NONBLOCK; 836059Samurai fcntl(0, F_SETFL, stat); 846059Samurai newtio = oldtio; 856059Samurai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 866059Samurai newtio.c_iflag = 0; 876059Samurai newtio.c_oflag &= ~OPOST; 886059Samurai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 896059Samurai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 906059Samurai newtio.c_cc[VMIN] = 1; 916059Samurai newtio.c_cc[VTIME] = 0; 926059Samurai newtio.c_cflag |= CS8; 936735Samurai tcsetattr(0, TCSADRAIN, &newtio); 946059Samurai comtio = newtio; 956059Samurai} 966059Samurai 976059Samurai/* 986059Samurai * Set tty into command mode. We allow canonical input and echo processing. 996059Samurai */ 10010528Samuraivoid 10110528SamuraiTtyCommandMode(prompt) 10210528Samuraiint prompt; 1036059Samurai{ 1046059Samurai struct termios newtio; 1056059Samurai int stat; 1066059Samurai 1076059Samurai if (!(mode & MODE_INTER)) 1086059Samurai return; 1096735Samurai tcgetattr(0, &newtio); 11010528Samurai newtio.c_lflag |= (ECHO|ISIG|ICANON); 1116059Samurai newtio.c_iflag = oldtio.c_iflag; 1126059Samurai newtio.c_oflag |= OPOST; 1136735Samurai tcsetattr(0, TCSADRAIN, &newtio); 1146059Samurai stat = fcntl(0, F_GETFL, 0); 1156059Samurai stat |= O_NONBLOCK; 1166059Samurai fcntl(0, F_SETFL, stat); 1176059Samurai TermMode = 0; 11810528Samurai if(prompt) Prompt(0); 1196059Samurai} 1206059Samurai 1216059Samurai/* 1226059Samurai * Set tty into terminal mode which is used while we invoke term command. 1236059Samurai */ 1246059Samuraivoid 1256059SamuraiTtyTermMode() 1266059Samurai{ 1276059Samurai int stat; 1286059Samurai 1296735Samurai tcsetattr(0, TCSADRAIN, &comtio); 1306059Samurai stat = fcntl(0, F_GETFL, 0); 1316059Samurai stat &= ~O_NONBLOCK; 1326059Samurai fcntl(0, F_SETFL, stat); 1336059Samurai TermMode = 1; 1346059Samurai} 1356059Samurai 1366059Samuraivoid 13710528SamuraiTtyOldMode() 1386059Samurai{ 1396059Samurai int stat; 1406059Samurai 1416059Samurai stat = fcntl(0, F_GETFL, 0); 1426059Samurai stat &= ~O_NONBLOCK; 1436059Samurai fcntl(0, F_SETFL, stat); 1446735Samurai tcsetattr(0, TCSANOW, &oldtio); 14510528Samurai} 14610528Samurai 14710528Samuraivoid 14810528SamuraiCleanup(excode) 14910528Samuraiint excode; 15010528Samurai{ 15110528Samurai 15210528Samurai OsLinkdown(); 1536059Samurai OsCloseLink(1); 1546059Samurai sleep(1); 15511336Samurai if (mode & MODE_AUTO) { 1566059Samurai DeleteIfRoutes(1); 15711336Samurai unlink(pid_filename); 15811336Samurai } 1596059Samurai OsInterfaceDown(1); 1606059Samurai LogPrintf(LOG_PHASE, "PPP Terminated.\n"); 1616059Samurai LogClose(); 1626059Samurai if (server > 0) 1636059Samurai close(server); 16410528Samurai TtyOldMode(); 1656059Samurai 1666059Samurai exit(excode); 1676059Samurai} 1686059Samurai 1696059Samuraistatic void 1706059SamuraiHangup() 1716059Samurai{ 1726059Samurai LogPrintf(LOG_PHASE, "SIGHUP\n"); 1736059Samurai Cleanup(EX_HANGUP); 1746059Samurai} 1756059Samurai 1766059Samuraistatic void 1776059SamuraiCloseSession() 1786059Samurai{ 1796059Samurai LogPrintf(LOG_PHASE, "SIGTERM\n"); 1806059Samurai LcpClose(); 1816059Samurai Cleanup(EX_TERM); 1826059Samurai} 1836059Samurai 18410528Samurai 18510528Samuraistatic void 18610528SamuraiTerminalCont() 18710528Samurai{ 18810528Samurai (void)signal(SIGCONT, SIG_DFL); 18910528Samurai (void)signal(SIGTSTP, TerminalStop); 19010528Samurai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 19110528Samurai} 19210528Samurai 19310528Samuraistatic void 19410528SamuraiTerminalStop(signo) 19510528Samuraiint signo; 19610528Samurai{ 19710528Samurai (void)signal(SIGCONT, TerminalCont); 19810528Samurai TtyOldMode(); 19910528Samurai signal(SIGTSTP, SIG_DFL); 20010528Samurai kill(getpid(), signo); 20110528Samurai} 20210528Samurai 20310528Samurai 2046059Samuraivoid 2056059SamuraiUsage() 2066059Samurai{ 20710528Samurai fprintf(stderr, "Usage: ppp [-auto | -direct | -dedicated] [system]\n"); 2086059Samurai exit(EX_START); 2096059Samurai} 2106059Samurai 2116059Samuraivoid 2126059SamuraiProcessArgs(int argc, char **argv) 2136059Samurai{ 2146059Samurai int optc; 2156059Samurai char *cp; 2166059Samurai 2176059Samurai optc = 0; 2186059Samurai while (argc > 0 && **argv == '-') { 2196059Samurai cp = *argv + 1; 2206059Samurai if (strcmp(cp, "auto") == 0) 2216059Samurai mode |= MODE_AUTO; 2226059Samurai else if (strcmp(cp, "direct") == 0) 2236059Samurai mode |= MODE_DIRECT; 2246059Samurai else if (strcmp(cp, "dedicated") == 0) 2256059Samurai mode |= MODE_DEDICATED; 2266059Samurai else 2276059Samurai Usage(); 2286059Samurai optc++; 2296059Samurai argv++; argc--; 2306059Samurai } 2316059Samurai if (argc > 1) { 2326059Samurai fprintf(stderr, "specify only one system label.\n"); 2336059Samurai exit(EX_START); 2346059Samurai } 2356059Samurai if (argc == 1) dstsystem = *argv; 2366059Samurai 2376059Samurai if (optc > 1) { 2386059Samurai fprintf(stderr, "specify only one mode.\n"); 2396059Samurai exit(EX_START); 2406059Samurai } 2416059Samurai} 2426059Samurai 2436059Samuraistatic void 2446059SamuraiGreetings() 2456059Samurai{ 2466059Samurai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 2476059Samurai fflush(stdout); 2486059Samurai} 2496059Samurai 2506059Samuraivoid 2516059Samuraimain(argc, argv) 2526059Samuraiint argc; 2536059Samuraichar **argv; 2546059Samurai{ 2556059Samurai int tunno; 2566059Samurai 2576059Samurai argc--; argv++; 2586059Samurai 2596059Samurai mode = MODE_INTER; /* default operation is interactive mode */ 2606059Samurai netfd = -1; 2616059Samurai ProcessArgs(argc, argv); 2626059Samurai Greetings(); 2636059Samurai GetUid(); 2646059Samurai IpcpDefAddress(); 2656059Samurai 2666059Samurai if (SelectSystem("default", CONFFILE) < 0) { 2676059Samurai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 2686059Samurai } 2696059Samurai 2706059Samurai if (LogOpen()) 2716059Samurai exit(EX_START); 2726059Samurai 2736735Samurai switch ( LocalAuthInit() ) { 2746735Samurai case NOT_FOUND: 2756764Samurai fprintf(stderr,LAUTH_M1); 2766764Samurai fprintf(stderr,LAUTH_M2); 2776764Samurai fflush (stderr); 2786764Samurai /* Fall down */ 2796764Samurai case VALID: 2806735Samurai VarLocalAuth = LOCAL_AUTH; 2816735Samurai break; 2826735Samurai default: 2836735Samurai break; 2846735Samurai } 2856735Samurai 2866059Samurai if (OpenTunnel(&tunno) < 0) { 2876059Samurai perror("open_tun"); 2886059Samurai exit(EX_START); 2896059Samurai } 2906059Samurai 2916059Samurai if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 2926059Samurai mode &= ~MODE_INTER; 2936059Samurai if (mode & MODE_INTER) { 2946059Samurai printf("Interactive mode\n"); 2956059Samurai netfd = 0; 2966059Samurai } else if (mode & MODE_AUTO) { 2976059Samurai printf("Automatic mode\n"); 2986059Samurai if (dstsystem == NULL) { 2996059Samurai fprintf(stderr, "Destination system must be specified in auto mode.\n"); 3006059Samurai exit(EX_START); 3016059Samurai } 3026059Samurai } 3036059Samurai 3046735Samurai tcgetattr(0, &oldtio); /* Save original tty mode */ 3056059Samurai 3066059Samurai signal(SIGHUP, Hangup); 3076059Samurai signal(SIGTERM, CloseSession); 3086059Samurai signal(SIGINT, CloseSession); 30910528Samurai signal(SIGQUIT, CloseSession); 3106735Samurai#ifdef SIGSEGV 3116059Samurai signal(SIGSEGV, Hangup); 3126735Samurai#endif 3136735Samurai#ifdef SIGPIPE 3146735Samurai signal(SIGPIPE, Hangup); 3156735Samurai#endif 3166735Samurai#ifdef SIGALRM 3176735Samurai signal(SIGALRM, SIG_IGN); 3186735Samurai#endif 31910528Samurai if(mode & MODE_INTER) 32010528Samurai { 32110528Samurai#ifdef SIGTSTP 32210528Samurai signal(SIGTSTP, TerminalStop); 32310528Samurai#endif 32410528Samurai#ifdef SIGTTIN 32510528Samurai signal(SIGTTIN, TerminalStop); 32610528Samurai#endif 32710528Samurai#ifdef SIGTTOU 32810528Samurai signal(SIGTTOU, SIG_IGN); 32910528Samurai#endif 33010528Samurai } 3316059Samurai 3326059Samurai if (dstsystem) { 3336059Samurai if (SelectSystem(dstsystem, CONFFILE) < 0) { 3346059Samurai fprintf(stderr, "Destination system not found in conf file.\n"); 3356059Samurai Cleanup(EX_START); 3366059Samurai } 3376059Samurai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 3386059Samurai fprintf(stderr, "Must specify dstaddr with auto mode.\n"); 3396059Samurai Cleanup(EX_START); 3406059Samurai } 3416059Samurai } 3426059Samurai if (mode & MODE_DIRECT) 3436059Samurai printf("Packet mode enabled.\n"); 3446059Samurai 3456059Samurai#ifdef notdef 3466059Samurai if (mode & MODE_AUTO) { 3476059Samurai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 3486059Samurai } 3496059Samurai#endif 3506059Samurai 3516059Samurai if (!(mode & MODE_INTER)) { 3526059Samurai int port = SERVER_PORT + tunno; 3536059Samurai /* 3546059Samurai * Create server socket and listen at there. 3556059Samurai */ 3566059Samurai server = socket(PF_INET, SOCK_STREAM, 0); 3576059Samurai if (server < 0) { 3586059Samurai perror("socket"); 3596059Samurai Cleanup(EX_SOCK); 3606059Samurai } 3616059Samurai ifsin.sin_family = AF_INET; 3626059Samurai ifsin.sin_addr.s_addr = INADDR_ANY; 3636059Samurai ifsin.sin_port = htons(port); 3646059Samurai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 3656059Samurai perror("bind"); 3666059Samurai if (errno == EADDRINUSE) 3676059Samurai fprintf(stderr, "Wait for a while, then try again.\n"); 3686059Samurai Cleanup(EX_SOCK); 3696059Samurai } 3706059Samurai listen(server, 5); 3716059Samurai 3726059Samurai DupLog(); 3736059Samurai if (!(mode & MODE_DIRECT)) { 37411336Samurai int fd; 37511336Samurai char pid[32]; 37611336Samurai 3776059Samurai if (fork()) 3786059Samurai exit(0); 37911336Samurai 38011336Samurai snprintf(pid_filename, sizeof (pid_filename), "%s/PPP.%s", 38111336Samurai _PATH_VARRUN, dstsystem); 38211336Samurai unlink(pid_filename); 38313389Sphk sprintf(pid, "%lu\n", getpid()); 38411336Samurai 38511336Samurai if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1) 38611336Samurai { 38711336Samurai write(fd, pid, strlen(pid)); 38811336Samurai close(fd); 38911336Samurai } 3906059Samurai } 3916059Samurai LogPrintf(LOG_PHASE, "Listening at %d.\n", port); 3926059Samurai#ifdef DOTTYINIT 3936735Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 3946059Samurai#else 3956059Samurai if (mode & MODE_DIRECT) { 3966059Samurai#endif 3976059Samurai TtyInit(); 3986059Samurai } else { 3996059Samurai setsid(); /* detach control tty */ 4006059Samurai } 4016059Samurai } else { 4026059Samurai server = -1; 4036059Samurai TtyInit(); 40410528Samurai TtyCommandMode(1); 4056059Samurai } 4066059Samurai LogPrintf(LOG_PHASE, "PPP Started.\n"); 4076059Samurai 4086059Samurai 4096059Samurai do 4106059Samurai DoLoop(); 4116059Samurai while (mode & MODE_DEDICATED); 4126059Samurai 4136059Samurai Cleanup(EX_DONE); 4146059Samurai} 4156059Samurai 4166059Samurai/* 4176059Samurai * Turn into packet mode, where we speek PPP. 4186059Samurai */ 4196059Samuraivoid 4206059SamuraiPacketMode() 4216059Samurai{ 4226059Samurai if (RawModem(modem) < 0) { 4236059Samurai fprintf(stderr, "Not connected.\r\n"); 4246059Samurai return; 4256059Samurai } 4266059Samurai 4276059Samurai AsyncInit(); 4286059Samurai VjInit(); 4296059Samurai LcpInit(); 4306059Samurai IpcpInit(); 4316059Samurai CcpInit(); 4326059Samurai LcpUp(); 4336059Samurai 4346059Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 4356059Samurai LcpOpen(OPEN_ACTIVE); 4366059Samurai else 4376059Samurai LcpOpen(VarOpenMode); 4386059Samurai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 43910528Samurai TtyCommandMode(1); 4406059Samurai fprintf(stderr, "Packet mode.\r\n"); 4416059Samurai } 4426059Samurai} 4436059Samurai 4446059Samuraistatic void 4456059SamuraiShowHelp() 4466059Samurai{ 44710528Samurai fprintf(stderr, "The following commands are available:\r\n"); 4486059Samurai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 4496059Samurai fprintf(stderr, " ~.\tTerminate program\r\n"); 4506059Samurai} 4516059Samurai 4526059Samuraistatic void 4536059SamuraiReadTty() 4546059Samurai{ 4556059Samurai int n; 4566059Samurai char ch; 4576059Samurai static int ttystate; 4586059Samurai#define MAXLINESIZE 200 4596059Samurai char linebuff[MAXLINESIZE]; 4606059Samurai 4616059Samurai#ifdef DEBUG 4626059Samurai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 4636059Samurai#endif 4646059Samurai if (!TermMode) { 4656059Samurai n = read(netfd, linebuff, sizeof(linebuff)-1); 4666735Samurai if (n > 0) { 4676059Samurai DecodeCommand(linebuff, n, 1); 4686735Samurai } else { 4696059Samurai#ifdef DEBUG 4706059Samurai logprintf("connection closed.\n"); 4716059Samurai#endif 4726059Samurai close(netfd); 4736059Samurai netfd = -1; 4746059Samurai mode &= ~MODE_INTER; 4756059Samurai } 4766059Samurai return; 4776059Samurai } 4786059Samurai 4796059Samurai /* 4806059Samurai * We are in terminal mode, decode special sequences 4816059Samurai */ 4826059Samurai n = read(0, &ch, 1); 4836059Samurai#ifdef DEBUG 4846059Samurai logprintf("got %d bytes\n", n); 4856059Samurai#endif 4866059Samurai 4876059Samurai if (n > 0) { 4886059Samurai switch (ttystate) { 4896059Samurai case 0: 4906059Samurai if (ch == '~') 4916059Samurai ttystate++; 4926059Samurai else 4936059Samurai write(modem, &ch, n); 4946059Samurai break; 4956059Samurai case 1: 4966059Samurai switch (ch) { 4976059Samurai case '?': 4986059Samurai ShowHelp(); 4996059Samurai break; 5006059Samurai case '-': 5016059Samurai if (loglevel > 0) { 5026059Samurai loglevel--; 5036059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 5046059Samurai } 5056059Samurai break; 5066059Samurai case '+': 5076059Samurai loglevel++; 5086059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 5096059Samurai break; 5106059Samurai#ifdef DEBUG 5116059Samurai case 'm': 5126059Samurai ShowMemMap(); 5136059Samurai break; 5146059Samurai#endif 5156059Samurai case 'p': 5166059Samurai /* 5176059Samurai * XXX: Should check carrier. 5186059Samurai */ 5196059Samurai if (LcpFsm.state <= ST_CLOSED) { 5206059Samurai VarOpenMode = OPEN_ACTIVE; 5216059Samurai PacketMode(); 5226059Samurai } 5236059Samurai break; 5246059Samurai#ifdef DEBUG 5256059Samurai case 't': 5266059Samurai ShowTimers(); 5276059Samurai break; 5286059Samurai#endif 5296059Samurai case '.': 5306059Samurai TermMode = 1; 53110528Samurai TtyCommandMode(1); 5326059Samurai break; 5336059Samurai default: 5346059Samurai if (write(modem, &ch, n) < 0) 5356059Samurai fprintf(stderr, "err in write.\r\n"); 5366059Samurai break; 5376059Samurai } 5386059Samurai ttystate = 0; 5396059Samurai break; 5406059Samurai } 5416059Samurai } 5426059Samurai} 5436059Samurai 5446059Samurai 5456059Samurai/* 5466059Samurai * Here, we'll try to detect HDLC frame 5476059Samurai */ 5486059Samurai 5496059Samuraistatic char *FrameHeaders[] = { 5506735Samurai "\176\377\003\300\041", 5516735Samurai "\176\377\175\043\300\041", 5526735Samurai "\176\177\175\043\100\041", 5536735Samurai "\176\175\337\175\043\300\041", 5546735Samurai "\176\175\137\175\043\100\041", 5556059Samurai NULL, 5566059Samurai}; 5576059Samurai 5586059Samuraiu_char * 5596059SamuraiHdlcDetect(cp, n) 5606059Samuraiu_char *cp; 5616059Samuraiint n; 5626059Samurai{ 5636735Samurai char *ptr, *fp, **hp; 5646059Samurai 5656059Samurai cp[n] = '\0'; /* be sure to null terminated */ 5666059Samurai ptr = NULL; 5676059Samurai for (hp = FrameHeaders; *hp; hp++) { 5686735Samurai fp = *hp; 5696735Samurai if (DEV_IS_SYNC) 5706735Samurai fp++; 57113389Sphk ptr = strstr((char *)cp, fp); 57213389Sphk if (ptr) 5736059Samurai break; 5746059Samurai } 5756059Samurai return((u_char *)ptr); 5766059Samurai} 5776059Samurai 5786059Samuraistatic struct pppTimer RedialTimer; 5796059Samurai 5806059Samuraistatic void 5816059SamuraiRedialTimeout() 5826059Samurai{ 5836059Samurai StopTimer(&RedialTimer); 5846059Samurai LogPrintf(LOG_PHASE, "Redialing timer expired.\n"); 5856059Samurai} 5866059Samurai 5876059Samuraistatic void 5886059SamuraiStartRedialTimer() 5896059Samurai{ 5906059Samurai StopTimer(&RedialTimer); 59111336Samurai 59211336Samurai if (VarRedialTimeout) { 59311336Samurai LogPrintf(LOG_PHASE, "Enter pause for redialing.\n"); 59411336Samurai RedialTimer.state = TIMER_STOPPED; 59511336Samurai 59611336Samurai if (VarRedialTimeout > 0) 59711336Samurai RedialTimer.load = VarRedialTimeout * SECTICKS; 59811336Samurai else 59911336Samurai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 60011336Samurai 60111336Samurai RedialTimer.func = RedialTimeout; 60211336Samurai StartTimer(&RedialTimer); 60311336Samurai } 6046059Samurai} 6056059Samurai 6066059Samurai 6076059Samuraistatic void 6086059SamuraiDoLoop() 6096059Samurai{ 6106059Samurai fd_set rfds, wfds, efds; 6116059Samurai int pri, i, n, wfd; 6126059Samurai struct sockaddr_in hisaddr; 6136059Samurai struct timeval timeout, *tp; 6146059Samurai int ssize = sizeof(hisaddr); 6156059Samurai u_char *cp; 6166059Samurai u_char rbuff[MAX_MRU]; 6177001Samurai int dial_up; 61811336Samurai int tries; 6199448Samurai int qlen; 62010528Samurai pid_t pgroup; 6216059Samurai 62210528Samurai pgroup = getpgrp(); 62310528Samurai 6246059Samurai if (mode & MODE_DIRECT) { 6256059Samurai modem = OpenModem(mode); 6269448Samurai LogPrintf(LOG_PHASE, "Packet mode enabled\n"); 6276059Samurai PacketMode(); 6286059Samurai } else if (mode & MODE_DEDICATED) { 6296059Samurai if (!modem) 6306059Samurai modem = OpenModem(mode); 6316059Samurai } 6326059Samurai 6336059Samurai fflush(stdout); 6346059Samurai 6357001Samurai timeout.tv_sec = 0; 6366059Samurai timeout.tv_usec = 0; 6376059Samurai 6387001Samurai dial_up = FALSE; /* XXXX */ 63911336Samurai tries = 0; 6406059Samurai for (;;) { 6418857Srgrimes if ( modem ) 6427001Samurai IpStartOutput(); 6436059Samurai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 6447001Samurai 6457001Samurai /* 6467001Samurai * If Ip packet for output is enqueued and require dial up, 6477001Samurai * Just do it! 6487001Samurai */ 6497001Samurai if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ 6507001Samurai#ifdef DEBUG 6517001Samurai logprintf("going to dial: modem = %d\n", modem); 6527001Samurai#endif 65311336Samurai modem = OpenModem(mode); 65411336Samurai if (modem < 0) { 65511336Samurai modem = 0; /* Set intial value for next OpenModem */ 65611336Samurai StartRedialTimer(); 65711336Samurai } else { 65811336Samurai tries++; 65911336Samurai LogPrintf(LOG_CHAT, "Dial attempt %u\n", tries); 66011336Samurai if (DialModem()) { 66111336Samurai sleep(1); /* little pause to allow peer starts */ 66211336Samurai ModemTimeout(); 66311336Samurai PacketMode(); 66411336Samurai dial_up = FALSE; 66511336Samurai tries = 0; 66611336Samurai } else { 66711336Samurai CloseModem(); 66811336Samurai /* Dial failed. Keep quite during redial wait period. */ 66911336Samurai StartRedialTimer(); 67011336Samurai 67111336Samurai if (VarDialTries && tries >= VarDialTries) { 67211336Samurai dial_up = FALSE; 67311336Samurai tries = 0; 67411336Samurai } 67511336Samurai } 67611336Samurai } 6777001Samurai } 6789448Samurai qlen = ModemQlen(); 6797001Samurai if (modem) { 6807001Samurai FD_SET(modem, &rfds); 6817001Samurai FD_SET(modem, &efds); 6829448Samurai if (qlen > 0) { 6837001Samurai FD_SET(modem, &wfds); 6847001Samurai } 6857001Samurai } 6866059Samurai if (server > 0) FD_SET(server, &rfds); 6876059Samurai 6886059Samurai /* *** IMPORTANT *** 6896059Samurai * 6906059Samurai * CPU is serviced every TICKUNIT micro seconds. 6916059Samurai * This value must be chosen with great care. If this values is 6926059Samurai * too big, it results loss of characters from modem and poor responce. 6936059Samurai * If this values is too small, ppp process eats many CPU time. 6946059Samurai */ 6956735Samurai#ifndef SIGALRM 6966059Samurai usleep(TICKUNIT); 6976059Samurai TimerService(); 6986735Samurai#endif 69910877Sbde 70010877Sbde /* If there are aren't many packets queued, look for some more. */ 70110877Sbde if (qlen < 20) 70210877Sbde FD_SET(tun_in, &rfds); 70310877Sbde 7046059Samurai if (netfd > -1) { 7056059Samurai FD_SET(netfd, &rfds); 7066059Samurai FD_SET(netfd, &efds); 7076059Samurai } 7087001Samurai 7096735Samurai#ifndef SIGALRM 7106059Samurai /* 7117001Samurai * Normally, select() will not block because modem is writable. 7127001Samurai * In AUTO mode, select will block until we find packet from tun 7136059Samurai */ 7146059Samurai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 7156059Samurai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 7166735Samurai#else 7178857Srgrimes /* 7187001Samurai * When SIGALRM timer is running, a select function will be 7198857Srgrimes * return -1 and EINTR after a Time Service signal hundler 72011336Samurai * is done. If the redial timer is not running and we are 72111336Samurai * trying to dial, poll with a 0 value timer. 7227001Samurai */ 72311336Samurai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 72411336Samurai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 7256735Samurai#endif 7267001Samurai if ( i == 0 ) { 7277001Samurai continue; 7286059Samurai } 7296735Samurai 7307001Samurai if ( i < 0 ) { 7317001Samurai if ( errno == EINTR ) { 73211336Samurai continue; /* Got SIGALRM, Do check a queue for dialing */ 7337001Samurai } 7347001Samurai perror("select"); 7357001Samurai break; 7368857Srgrimes } 7377001Samurai 7386059Samurai if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) { 7396059Samurai logprintf("Exception detected.\n"); 7406059Samurai break; 7416059Samurai } 7426059Samurai 7436059Samurai if (server > 0 && FD_ISSET(server, &rfds)) { 7446059Samurai#ifdef DEBUG 7456059Samurai logprintf("connected to client.\n"); 7466059Samurai#endif 7476059Samurai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 7486059Samurai if (netfd > 0) { 7496059Samurai write(wfd, "already in use.\n", 16); 7506059Samurai close(wfd); 7516059Samurai continue; 7526059Samurai } else 7536059Samurai netfd = wfd; 7546059Samurai if (dup2(netfd, 1) < 0) 7556059Samurai perror("dup2"); 7566059Samurai mode |= MODE_INTER; 7576059Samurai Greetings(); 7586764Samurai switch ( LocalAuthInit() ) { 7596764Samurai case NOT_FOUND: 7606764Samurai fprintf(stdout,LAUTH_M1); 7616764Samurai fprintf(stdout,LAUTH_M2); 7626764Samurai fflush(stdout); 7636764Samurai /* Fall down */ 7646764Samurai case VALID: 7656764Samurai VarLocalAuth = LOCAL_AUTH; 7666764Samurai break; 7676764Samurai default: 7686764Samurai break; 7696764Samurai } 7706059Samurai (void) IsInteractive(); 7716059Samurai Prompt(0); 7726059Samurai } 7736059Samurai 77410528Samurai if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds) && 77510858Samurai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 7766059Samurai /* something to read from tty */ 7776059Samurai ReadTty(); 7786059Samurai } 7796059Samurai if (modem) { 7806059Samurai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 7816059Samurai ModemStartOutput(modem); 7826059Samurai } 7836059Samurai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 7846735Samurai if (LcpFsm.state <= ST_CLOSED) 7856735Samurai usleep(10000); 7866059Samurai n = read(modem, rbuff, sizeof(rbuff)); 7876059Samurai if ((mode & MODE_DIRECT) && n <= 0) { 7886059Samurai DownConnection(); 7896059Samurai } else 7906059Samurai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 7916059Samurai 7926059Samurai if (LcpFsm.state <= ST_CLOSED) { 7936059Samurai /* 7946059Samurai * In dedicated mode, we just discard input until LCP is started. 7956059Samurai */ 7966059Samurai if (!(mode & MODE_DEDICATED)) { 7976059Samurai cp = HdlcDetect(rbuff, n); 7986059Samurai if (cp) { 7996059Samurai /* 8006059Samurai * LCP packet is detected. Turn ourselves into packet mode. 8016059Samurai */ 8026059Samurai if (cp != rbuff) { 8036059Samurai write(1, rbuff, cp - rbuff); 8046059Samurai write(1, "\r\n", 2); 8056059Samurai } 8066059Samurai PacketMode(); 8076059Samurai#ifdef notdef 8086059Samurai AsyncInput(cp, n - (cp - rbuff)); 8096059Samurai#endif 8106059Samurai } else 8116059Samurai write(1, rbuff, n); 8126059Samurai } 8136059Samurai } else { 8146059Samurai if (n > 0) 8156059Samurai AsyncInput(rbuff, n); 8166059Samurai#ifdef notdef 8176059Samurai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 8186059Samurai#endif 8196059Samurai } 8206059Samurai } 8216059Samurai } 8227001Samurai 8236059Samurai if (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 8246059Samurai n = read(tun_in, rbuff, sizeof(rbuff)); 8256059Samurai if (n < 0) { 8266059Samurai perror("read from tun"); 8276059Samurai continue; 8286059Samurai } 8296059Samurai /* 8306059Samurai * Process on-demand dialup. Output packets are queued within tunnel 8316059Samurai * device until IPCP is opened. 8326059Samurai */ 8336059Samurai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 8347001Samurai pri = PacketCheck(rbuff, n, FL_DIAL); 8356059Samurai if (pri >= 0) { 8366059Samurai IpEnqueue(pri, rbuff, n); 8377001Samurai dial_up = TRUE; /* XXX */ 8386059Samurai } 8396059Samurai continue; 8406059Samurai } 8417001Samurai pri = PacketCheck(rbuff, n, FL_OUT); 8426059Samurai if (pri >= 0) 8436059Samurai IpEnqueue(pri, rbuff, n); 8446059Samurai } 8456059Samurai } 8466059Samurai logprintf("job done.\n"); 8476059Samurai} 848