main.c revision 20120
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 * 2020120Snate * $Id: main.c,v 1.22 1996/10/12 16:20:32 jkh 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> 3518786Sjkh#include <unistd.h> 366059Samurai#include <sys/socket.h> 376059Samurai#include <arpa/inet.h> 386059Samurai#include "modem.h" 396059Samurai#include "os.h" 406059Samurai#include "hdlc.h" 4113389Sphk#include "ccp.h" 426059Samurai#include "lcp.h" 436059Samurai#include "ipcp.h" 446059Samurai#include "vars.h" 456735Samurai#include "auth.h" 467001Samurai#include "filter.h" 4713389Sphk#include "systems.h" 4813389Sphk#include "ip.h" 496059Samurai 506764Samurai#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 519410Sasami#define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n" 526764Samurai 536735Samurai#ifndef O_NONBLOCK 546735Samurai#ifdef O_NDELAY 556735Samurai#define O_NONBLOCK O_NDELAY 566735Samurai#endif 576735Samurai#endif 586735Samurai 596059Samuraiextern void VjInit(), AsyncInit(); 606059Samuraiextern void AsyncInput(), IpOutput(); 616059Samuraiextern int SelectSystem(); 626059Samurai 636059Samuraiextern void DecodeCommand(), Prompt(); 6418885Sjkhextern int aft_cmd; 656059Samuraiextern int IsInteractive(); 666059Samuraiextern struct in_addr ifnetmask; 676059Samuraistatic void DoLoop(void); 6810528Samuraistatic void TerminalStop(); 696059Samurai 706059Samuraistatic struct termios oldtio; /* Original tty mode */ 716059Samuraistatic struct termios comtio; /* Command level tty mode */ 7214418Sacheint TermMode; 7313379Sphkstatic int server; 746059Samuraistruct sockaddr_in ifsin; 7511336Samuraichar pid_filename[128]; 766059Samurai 776059Samuraistatic void 786059SamuraiTtyInit() 796059Samurai{ 806059Samurai struct termios newtio; 816059Samurai int stat; 826059Samurai 836059Samurai stat = fcntl(0, F_GETFL, 0); 846059Samurai stat |= O_NONBLOCK; 856059Samurai fcntl(0, F_SETFL, stat); 866059Samurai newtio = oldtio; 876059Samurai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 886059Samurai newtio.c_iflag = 0; 896059Samurai newtio.c_oflag &= ~OPOST; 906059Samurai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 916059Samurai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 926059Samurai newtio.c_cc[VMIN] = 1; 936059Samurai newtio.c_cc[VTIME] = 0; 946059Samurai newtio.c_cflag |= CS8; 956735Samurai tcsetattr(0, TCSADRAIN, &newtio); 966059Samurai comtio = newtio; 976059Samurai} 986059Samurai 996059Samurai/* 1006059Samurai * Set tty into command mode. We allow canonical input and echo processing. 1016059Samurai */ 10210528Samuraivoid 10310528SamuraiTtyCommandMode(prompt) 10410528Samuraiint prompt; 1056059Samurai{ 1066059Samurai struct termios newtio; 1076059Samurai int stat; 1086059Samurai 1096059Samurai if (!(mode & MODE_INTER)) 1106059Samurai return; 1116735Samurai tcgetattr(0, &newtio); 11210528Samurai newtio.c_lflag |= (ECHO|ISIG|ICANON); 1136059Samurai newtio.c_iflag = oldtio.c_iflag; 1146059Samurai newtio.c_oflag |= OPOST; 1156735Samurai tcsetattr(0, TCSADRAIN, &newtio); 1166059Samurai stat = fcntl(0, F_GETFL, 0); 1176059Samurai stat |= O_NONBLOCK; 1186059Samurai fcntl(0, F_SETFL, stat); 1196059Samurai TermMode = 0; 12010528Samurai if(prompt) Prompt(0); 1216059Samurai} 1226059Samurai 1236059Samurai/* 1246059Samurai * Set tty into terminal mode which is used while we invoke term command. 1256059Samurai */ 1266059Samuraivoid 1276059SamuraiTtyTermMode() 1286059Samurai{ 1296059Samurai int stat; 1306059Samurai 1316735Samurai tcsetattr(0, TCSADRAIN, &comtio); 1326059Samurai stat = fcntl(0, F_GETFL, 0); 1336059Samurai stat &= ~O_NONBLOCK; 1346059Samurai fcntl(0, F_SETFL, stat); 1356059Samurai TermMode = 1; 1366059Samurai} 1376059Samurai 1386059Samuraivoid 13910528SamuraiTtyOldMode() 1406059Samurai{ 1416059Samurai int stat; 1426059Samurai 1436059Samurai stat = fcntl(0, F_GETFL, 0); 1446059Samurai stat &= ~O_NONBLOCK; 1456059Samurai fcntl(0, F_SETFL, stat); 1466735Samurai tcsetattr(0, TCSANOW, &oldtio); 14710528Samurai} 14810528Samurai 14910528Samuraivoid 15010528SamuraiCleanup(excode) 15110528Samuraiint excode; 15210528Samurai{ 15310528Samurai 15410528Samurai OsLinkdown(); 1556059Samurai OsCloseLink(1); 1566059Samurai sleep(1); 15711336Samurai if (mode & MODE_AUTO) { 1586059Samurai DeleteIfRoutes(1); 15911336Samurai unlink(pid_filename); 16011336Samurai } 1616059Samurai OsInterfaceDown(1); 16215738Sphk LogPrintf(LOG_PHASE_BIT, "PPP Terminated.\n"); 1636059Samurai LogClose(); 1646059Samurai if (server > 0) 1656059Samurai close(server); 16610528Samurai TtyOldMode(); 1676059Samurai 1686059Samurai exit(excode); 1696059Samurai} 1706059Samurai 1716059Samuraistatic void 17214930SacheHangup(signo) 17314930Sacheint signo; 1746059Samurai{ 17517044Sache if (signo == SIGSEGV) { 17617044Sache LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo); 17717044Sache LogClose(); 17817044Sache abort(); 17917044Sache } 18015738Sphk LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo); 1816059Samurai Cleanup(EX_HANGUP); 1826059Samurai} 1836059Samurai 1846059Samuraistatic void 18514930SacheCloseSession(signo) 18614930Sacheint signo; 1876059Samurai{ 18815738Sphk LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo); 1896059Samurai LcpClose(); 1906059Samurai Cleanup(EX_TERM); 1916059Samurai} 1926059Samurai 19310528Samurai 19410528Samuraistatic void 19510528SamuraiTerminalCont() 19610528Samurai{ 19710528Samurai (void)signal(SIGCONT, SIG_DFL); 19810528Samurai (void)signal(SIGTSTP, TerminalStop); 19910528Samurai TtyCommandMode(getpgrp() == tcgetpgrp(0)); 20010528Samurai} 20110528Samurai 20210528Samuraistatic void 20310528SamuraiTerminalStop(signo) 20410528Samuraiint signo; 20510528Samurai{ 20610528Samurai (void)signal(SIGCONT, TerminalCont); 20710528Samurai TtyOldMode(); 20810528Samurai signal(SIGTSTP, SIG_DFL); 20910528Samurai kill(getpid(), signo); 21010528Samurai} 21110528Samurai 21210528Samurai 2136059Samuraivoid 2146059SamuraiUsage() 2156059Samurai{ 21620120Snate fprintf(stderr, 21720120Snate "Usage: ppp [-auto | -direct | -dedicated | -ddial ] [system]\n"); 2186059Samurai exit(EX_START); 2196059Samurai} 2206059Samurai 2216059Samuraivoid 2226059SamuraiProcessArgs(int argc, char **argv) 2236059Samurai{ 2246059Samurai int optc; 2256059Samurai char *cp; 2266059Samurai 2276059Samurai optc = 0; 2286059Samurai while (argc > 0 && **argv == '-') { 2296059Samurai cp = *argv + 1; 2306059Samurai if (strcmp(cp, "auto") == 0) 2316059Samurai mode |= MODE_AUTO; 2326059Samurai else if (strcmp(cp, "direct") == 0) 2336059Samurai mode |= MODE_DIRECT; 2346059Samurai else if (strcmp(cp, "dedicated") == 0) 2356059Samurai mode |= MODE_DEDICATED; 23620120Snate else if (strcmp(cp, "ddial") == 0) 23720120Snate mode |= MODE_DDIAL|MODE_AUTO; 2386059Samurai else 2396059Samurai Usage(); 2406059Samurai optc++; 2416059Samurai argv++; argc--; 2426059Samurai } 2436059Samurai if (argc > 1) { 2446059Samurai fprintf(stderr, "specify only one system label.\n"); 2456059Samurai exit(EX_START); 2466059Samurai } 2476059Samurai if (argc == 1) dstsystem = *argv; 2486059Samurai 2496059Samurai if (optc > 1) { 2506059Samurai fprintf(stderr, "specify only one mode.\n"); 2516059Samurai exit(EX_START); 2526059Samurai } 2536059Samurai} 2546059Samurai 2556059Samuraistatic void 2566059SamuraiGreetings() 2576059Samurai{ 2586059Samurai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 2596059Samurai fflush(stdout); 2606059Samurai} 2616059Samurai 2626059Samuraivoid 2636059Samuraimain(argc, argv) 2646059Samuraiint argc; 2656059Samuraichar **argv; 2666059Samurai{ 2676059Samurai int tunno; 2686059Samurai 2696059Samurai argc--; argv++; 2706059Samurai 2716059Samurai mode = MODE_INTER; /* default operation is interactive mode */ 2726059Samurai netfd = -1; 2736059Samurai ProcessArgs(argc, argv); 2746059Samurai Greetings(); 2756059Samurai GetUid(); 2766059Samurai IpcpDefAddress(); 2776059Samurai 2786059Samurai if (SelectSystem("default", CONFFILE) < 0) { 2796059Samurai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 2806059Samurai } 2816059Samurai 2826059Samurai if (LogOpen()) 2836059Samurai exit(EX_START); 2846059Samurai 2856735Samurai switch ( LocalAuthInit() ) { 2866735Samurai case NOT_FOUND: 2876764Samurai fprintf(stderr,LAUTH_M1); 2886764Samurai fprintf(stderr,LAUTH_M2); 2896764Samurai fflush (stderr); 2906764Samurai /* Fall down */ 2916764Samurai case VALID: 2926735Samurai VarLocalAuth = LOCAL_AUTH; 2936735Samurai break; 2946735Samurai default: 2956735Samurai break; 2966735Samurai } 2976735Samurai 2986059Samurai if (OpenTunnel(&tunno) < 0) { 2996059Samurai perror("open_tun"); 3006059Samurai exit(EX_START); 3016059Samurai } 3026059Samurai 3036059Samurai if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 3046059Samurai mode &= ~MODE_INTER; 3056059Samurai if (mode & MODE_INTER) { 3066059Samurai printf("Interactive mode\n"); 3076059Samurai netfd = 0; 3086059Samurai } else if (mode & MODE_AUTO) { 30920120Snate printf("Automatic Dialer mode\n"); 3106059Samurai if (dstsystem == NULL) { 31120120Snate fprintf(stderr, 31220120Snate "Destination system must be specified in auto or ddial mode.\n"); 3136059Samurai exit(EX_START); 3146059Samurai } 3156059Samurai } 3166059Samurai 3176735Samurai tcgetattr(0, &oldtio); /* Save original tty mode */ 3186059Samurai 3196059Samurai signal(SIGHUP, Hangup); 3206059Samurai signal(SIGTERM, CloseSession); 3216059Samurai signal(SIGINT, CloseSession); 32210528Samurai signal(SIGQUIT, CloseSession); 3236735Samurai#ifdef SIGSEGV 3246059Samurai signal(SIGSEGV, Hangup); 3256735Samurai#endif 3266735Samurai#ifdef SIGPIPE 3276735Samurai signal(SIGPIPE, Hangup); 3286735Samurai#endif 3296735Samurai#ifdef SIGALRM 3306735Samurai signal(SIGALRM, SIG_IGN); 3316735Samurai#endif 33210528Samurai if(mode & MODE_INTER) 33310528Samurai { 33410528Samurai#ifdef SIGTSTP 33510528Samurai signal(SIGTSTP, TerminalStop); 33610528Samurai#endif 33710528Samurai#ifdef SIGTTIN 33810528Samurai signal(SIGTTIN, TerminalStop); 33910528Samurai#endif 34010528Samurai#ifdef SIGTTOU 34110528Samurai signal(SIGTTOU, SIG_IGN); 34210528Samurai#endif 34310528Samurai } 3446059Samurai 3456059Samurai if (dstsystem) { 3466059Samurai if (SelectSystem(dstsystem, CONFFILE) < 0) { 3476059Samurai fprintf(stderr, "Destination system not found in conf file.\n"); 3486059Samurai Cleanup(EX_START); 3496059Samurai } 3506059Samurai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 35120120Snate fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n"); 3526059Samurai Cleanup(EX_START); 3536059Samurai } 3546059Samurai } 3556059Samurai if (mode & MODE_DIRECT) 3566059Samurai printf("Packet mode enabled.\n"); 3576059Samurai 3586059Samurai#ifdef notdef 3596059Samurai if (mode & MODE_AUTO) { 3606059Samurai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 3616059Samurai } 3626059Samurai#endif 3636059Samurai 3646059Samurai if (!(mode & MODE_INTER)) { 3656059Samurai int port = SERVER_PORT + tunno; 3666059Samurai /* 3676059Samurai * Create server socket and listen at there. 3686059Samurai */ 3696059Samurai server = socket(PF_INET, SOCK_STREAM, 0); 3706059Samurai if (server < 0) { 3716059Samurai perror("socket"); 3726059Samurai Cleanup(EX_SOCK); 3736059Samurai } 3746059Samurai ifsin.sin_family = AF_INET; 3756059Samurai ifsin.sin_addr.s_addr = INADDR_ANY; 3766059Samurai ifsin.sin_port = htons(port); 3776059Samurai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 3786059Samurai perror("bind"); 3796059Samurai if (errno == EADDRINUSE) 3806059Samurai fprintf(stderr, "Wait for a while, then try again.\n"); 3816059Samurai Cleanup(EX_SOCK); 3826059Samurai } 3836059Samurai listen(server, 5); 3846059Samurai 3856059Samurai DupLog(); 3866059Samurai if (!(mode & MODE_DIRECT)) { 38711336Samurai int fd; 38811336Samurai char pid[32]; 38911336Samurai 3906059Samurai if (fork()) 3916059Samurai exit(0); 39211336Samurai 39311336Samurai snprintf(pid_filename, sizeof (pid_filename), "%s/PPP.%s", 39411336Samurai _PATH_VARRUN, dstsystem); 39511336Samurai unlink(pid_filename); 39620120Snate sprintf(pid, "%d\n", (int)getpid()); 39711336Samurai 39811336Samurai if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1) 39911336Samurai { 40011336Samurai write(fd, pid, strlen(pid)); 40111336Samurai close(fd); 40211336Samurai } 4036059Samurai } 40415738Sphk LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port); 4056059Samurai#ifdef DOTTYINIT 4066735Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 4076059Samurai#else 4086059Samurai if (mode & MODE_DIRECT) { 4096059Samurai#endif 4106059Samurai TtyInit(); 4116059Samurai } else { 41214436Sache int fd; 41314436Sache 4146059Samurai setsid(); /* detach control tty */ 41514436Sache if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 41614436Sache (void)dup2(fd, STDIN_FILENO); 41714436Sache (void)dup2(fd, STDOUT_FILENO); 41814436Sache (void)dup2(fd, STDERR_FILENO); 41914436Sache if (fd > 2) 42014436Sache (void)close (fd); 42114436Sache } 4226059Samurai } 4236059Samurai } else { 4246059Samurai server = -1; 4256059Samurai TtyInit(); 42610528Samurai TtyCommandMode(1); 4276059Samurai } 42815738Sphk LogPrintf(LOG_PHASE_BIT, "PPP Started.\n"); 4296059Samurai 4306059Samurai 4316059Samurai do 4326059Samurai DoLoop(); 4336059Samurai while (mode & MODE_DEDICATED); 4346059Samurai 4356059Samurai Cleanup(EX_DONE); 4366059Samurai} 4376059Samurai 4386059Samurai/* 4396059Samurai * Turn into packet mode, where we speek PPP. 4406059Samurai */ 4416059Samuraivoid 4426059SamuraiPacketMode() 4436059Samurai{ 4446059Samurai if (RawModem(modem) < 0) { 4456059Samurai fprintf(stderr, "Not connected.\r\n"); 4466059Samurai return; 4476059Samurai } 4486059Samurai 4496059Samurai AsyncInit(); 4506059Samurai VjInit(); 4516059Samurai LcpInit(); 4526059Samurai IpcpInit(); 4536059Samurai CcpInit(); 4546059Samurai LcpUp(); 4556059Samurai 4566059Samurai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 4576059Samurai LcpOpen(OPEN_ACTIVE); 4586059Samurai else 4596059Samurai LcpOpen(VarOpenMode); 4606059Samurai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 46110528Samurai TtyCommandMode(1); 4626059Samurai fprintf(stderr, "Packet mode.\r\n"); 46318885Sjkh aft_cmd = 1; 4646059Samurai } 4656059Samurai} 4666059Samurai 4676059Samuraistatic void 4686059SamuraiShowHelp() 4696059Samurai{ 47010528Samurai fprintf(stderr, "The following commands are available:\r\n"); 4716059Samurai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 47214418Sache fprintf(stderr, " ~-\tDecrease log level\r\n"); 47314418Sache fprintf(stderr, " ~+\tIncrease log level\r\n"); 4746059Samurai fprintf(stderr, " ~.\tTerminate program\r\n"); 47514418Sache fprintf(stderr, " ~?\tThis help\r\n"); 4766059Samurai} 4776059Samurai 4786059Samuraistatic void 4796059SamuraiReadTty() 4806059Samurai{ 4816059Samurai int n; 4826059Samurai char ch; 4836059Samurai static int ttystate; 4846059Samurai#define MAXLINESIZE 200 4856059Samurai char linebuff[MAXLINESIZE]; 4866059Samurai 4876059Samurai#ifdef DEBUG 4886059Samurai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 4896059Samurai#endif 4906059Samurai if (!TermMode) { 4916059Samurai n = read(netfd, linebuff, sizeof(linebuff)-1); 49218885Sjkh aft_cmd = 1; 4936735Samurai if (n > 0) { 4946059Samurai DecodeCommand(linebuff, n, 1); 4956735Samurai } else { 4966059Samurai#ifdef DEBUG 4976059Samurai logprintf("connection closed.\n"); 4986059Samurai#endif 4996059Samurai close(netfd); 5006059Samurai netfd = -1; 5016059Samurai mode &= ~MODE_INTER; 5026059Samurai } 5036059Samurai return; 5046059Samurai } 5056059Samurai 5066059Samurai /* 5076059Samurai * We are in terminal mode, decode special sequences 5086059Samurai */ 5096059Samurai n = read(0, &ch, 1); 5106059Samurai#ifdef DEBUG 5116059Samurai logprintf("got %d bytes\n", n); 5126059Samurai#endif 5136059Samurai 5146059Samurai if (n > 0) { 5156059Samurai switch (ttystate) { 5166059Samurai case 0: 5176059Samurai if (ch == '~') 5186059Samurai ttystate++; 5196059Samurai else 5206059Samurai write(modem, &ch, n); 5216059Samurai break; 5226059Samurai case 1: 5236059Samurai switch (ch) { 5246059Samurai case '?': 5256059Samurai ShowHelp(); 5266059Samurai break; 5276059Samurai case '-': 5286059Samurai if (loglevel > 0) { 5296059Samurai loglevel--; 5306059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 5316059Samurai } 5326059Samurai break; 5336059Samurai case '+': 5346059Samurai loglevel++; 5356059Samurai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 5366059Samurai break; 5376059Samurai#ifdef DEBUG 5386059Samurai case 'm': 5396059Samurai ShowMemMap(); 5406059Samurai break; 5416059Samurai#endif 5426059Samurai case 'p': 5436059Samurai /* 5446059Samurai * XXX: Should check carrier. 5456059Samurai */ 5466059Samurai if (LcpFsm.state <= ST_CLOSED) { 5476059Samurai VarOpenMode = OPEN_ACTIVE; 5486059Samurai PacketMode(); 5496059Samurai } 5506059Samurai break; 5516059Samurai#ifdef DEBUG 5526059Samurai case 't': 5536059Samurai ShowTimers(); 5546059Samurai break; 5556059Samurai#endif 5566059Samurai case '.': 5576059Samurai TermMode = 1; 55810528Samurai TtyCommandMode(1); 5596059Samurai break; 5606059Samurai default: 5616059Samurai if (write(modem, &ch, n) < 0) 5626059Samurai fprintf(stderr, "err in write.\r\n"); 5636059Samurai break; 5646059Samurai } 5656059Samurai ttystate = 0; 5666059Samurai break; 5676059Samurai } 5686059Samurai } 5696059Samurai} 5706059Samurai 5716059Samurai 5726059Samurai/* 5736059Samurai * Here, we'll try to detect HDLC frame 5746059Samurai */ 5756059Samurai 5766059Samuraistatic char *FrameHeaders[] = { 5776735Samurai "\176\377\003\300\041", 5786735Samurai "\176\377\175\043\300\041", 5796735Samurai "\176\177\175\043\100\041", 5806735Samurai "\176\175\337\175\043\300\041", 5816735Samurai "\176\175\137\175\043\100\041", 5826059Samurai NULL, 5836059Samurai}; 5846059Samurai 5856059Samuraiu_char * 5866059SamuraiHdlcDetect(cp, n) 5876059Samuraiu_char *cp; 5886059Samuraiint n; 5896059Samurai{ 5906735Samurai char *ptr, *fp, **hp; 5916059Samurai 5926059Samurai cp[n] = '\0'; /* be sure to null terminated */ 5936059Samurai ptr = NULL; 5946059Samurai for (hp = FrameHeaders; *hp; hp++) { 5956735Samurai fp = *hp; 5966735Samurai if (DEV_IS_SYNC) 5976735Samurai fp++; 59813389Sphk ptr = strstr((char *)cp, fp); 59913389Sphk if (ptr) 6006059Samurai break; 6016059Samurai } 6026059Samurai return((u_char *)ptr); 6036059Samurai} 6046059Samurai 6056059Samuraistatic struct pppTimer RedialTimer; 6066059Samurai 6076059Samuraistatic void 6086059SamuraiRedialTimeout() 6096059Samurai{ 6106059Samurai StopTimer(&RedialTimer); 61115738Sphk LogPrintf(LOG_PHASE_BIT, "Redialing timer expired.\n"); 6126059Samurai} 6136059Samurai 6146059Samuraistatic void 6156059SamuraiStartRedialTimer() 6166059Samurai{ 6176059Samurai StopTimer(&RedialTimer); 61811336Samurai 61911336Samurai if (VarRedialTimeout) { 62015738Sphk LogPrintf(LOG_PHASE_BIT, "Enter pause for redialing.\n"); 62111336Samurai RedialTimer.state = TIMER_STOPPED; 62211336Samurai 62311336Samurai if (VarRedialTimeout > 0) 62411336Samurai RedialTimer.load = VarRedialTimeout * SECTICKS; 62511336Samurai else 62611336Samurai RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 62711336Samurai 62811336Samurai RedialTimer.func = RedialTimeout; 62911336Samurai StartTimer(&RedialTimer); 63011336Samurai } 6316059Samurai} 6326059Samurai 6336059Samurai 6346059Samuraistatic void 6356059SamuraiDoLoop() 6366059Samurai{ 6376059Samurai fd_set rfds, wfds, efds; 6386059Samurai int pri, i, n, wfd; 6396059Samurai struct sockaddr_in hisaddr; 6406059Samurai struct timeval timeout, *tp; 6416059Samurai int ssize = sizeof(hisaddr); 6426059Samurai u_char *cp; 6436059Samurai u_char rbuff[MAX_MRU]; 6447001Samurai int dial_up; 64511336Samurai int tries; 6469448Samurai int qlen; 64710528Samurai pid_t pgroup; 6486059Samurai 64910528Samurai pgroup = getpgrp(); 65010528Samurai 6516059Samurai if (mode & MODE_DIRECT) { 6526059Samurai modem = OpenModem(mode); 65315738Sphk LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n"); 65418885Sjkh fflush(stderr); 6556059Samurai PacketMode(); 6566059Samurai } else if (mode & MODE_DEDICATED) { 6576059Samurai if (!modem) 6586059Samurai modem = OpenModem(mode); 6596059Samurai } 6606059Samurai 6616059Samurai fflush(stdout); 6626059Samurai 6637001Samurai timeout.tv_sec = 0; 6646059Samurai timeout.tv_usec = 0; 6656059Samurai 6667001Samurai dial_up = FALSE; /* XXXX */ 66711336Samurai tries = 0; 6686059Samurai for (;;) { 6696059Samurai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 6707001Samurai 67120120Snate /* 67220120Snate * If the link is down and we're in DDIAL mode, bring it back 67320120Snate * up. 67420120Snate */ 67520120Snate if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 67620120Snate dial_up = TRUE; 67720120Snate 6787001Samurai /* 6797001Samurai * If Ip packet for output is enqueued and require dial up, 6807001Samurai * Just do it! 6817001Samurai */ 6827001Samurai if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ 6837001Samurai#ifdef DEBUG 6847001Samurai logprintf("going to dial: modem = %d\n", modem); 6857001Samurai#endif 68611336Samurai modem = OpenModem(mode); 68711336Samurai if (modem < 0) { 68811336Samurai modem = 0; /* Set intial value for next OpenModem */ 68911336Samurai StartRedialTimer(); 69011336Samurai } else { 69111336Samurai tries++; 69215738Sphk LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries); 69311336Samurai if (DialModem()) { 69411336Samurai sleep(1); /* little pause to allow peer starts */ 69511336Samurai ModemTimeout(); 69611336Samurai PacketMode(); 69711336Samurai dial_up = FALSE; 69811336Samurai tries = 0; 69911336Samurai } else { 70011336Samurai CloseModem(); 70111336Samurai /* Dial failed. Keep quite during redial wait period. */ 70211336Samurai StartRedialTimer(); 70311336Samurai 70411336Samurai if (VarDialTries && tries >= VarDialTries) { 70511336Samurai dial_up = FALSE; 70611336Samurai tries = 0; 70711336Samurai } 70811336Samurai } 70911336Samurai } 7107001Samurai } 7119448Samurai qlen = ModemQlen(); 71213733Sdfr 71313733Sdfr if (qlen == 0) { 71413733Sdfr IpStartOutput(); 71513733Sdfr qlen = ModemQlen(); 71613733Sdfr } 71713733Sdfr 7187001Samurai if (modem) { 7197001Samurai FD_SET(modem, &rfds); 7207001Samurai FD_SET(modem, &efds); 7219448Samurai if (qlen > 0) { 7227001Samurai FD_SET(modem, &wfds); 7237001Samurai } 7247001Samurai } 7256059Samurai if (server > 0) FD_SET(server, &rfds); 7266059Samurai 7276059Samurai /* *** IMPORTANT *** 7286059Samurai * 7296059Samurai * CPU is serviced every TICKUNIT micro seconds. 7306059Samurai * This value must be chosen with great care. If this values is 7316059Samurai * too big, it results loss of characters from modem and poor responce. 7326059Samurai * If this values is too small, ppp process eats many CPU time. 7336059Samurai */ 7346735Samurai#ifndef SIGALRM 7356059Samurai usleep(TICKUNIT); 7366059Samurai TimerService(); 7376735Samurai#endif 73810877Sbde 73910877Sbde /* If there are aren't many packets queued, look for some more. */ 74010877Sbde if (qlen < 20) 74110877Sbde FD_SET(tun_in, &rfds); 74210877Sbde 7436059Samurai if (netfd > -1) { 7446059Samurai FD_SET(netfd, &rfds); 7456059Samurai FD_SET(netfd, &efds); 7466059Samurai } 7477001Samurai 7486735Samurai#ifndef SIGALRM 7496059Samurai /* 7507001Samurai * Normally, select() will not block because modem is writable. 7517001Samurai * In AUTO mode, select will block until we find packet from tun 7526059Samurai */ 7536059Samurai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 7546059Samurai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 7556735Samurai#else 7568857Srgrimes /* 7577001Samurai * When SIGALRM timer is running, a select function will be 7588857Srgrimes * return -1 and EINTR after a Time Service signal hundler 75911336Samurai * is done. If the redial timer is not running and we are 76011336Samurai * trying to dial, poll with a 0 value timer. 7617001Samurai */ 76211336Samurai tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 76311336Samurai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 7646735Samurai#endif 7657001Samurai if ( i == 0 ) { 7667001Samurai continue; 7676059Samurai } 7686735Samurai 7697001Samurai if ( i < 0 ) { 7707001Samurai if ( errno == EINTR ) { 77111336Samurai continue; /* Got SIGALRM, Do check a queue for dialing */ 7727001Samurai } 7737001Samurai perror("select"); 7747001Samurai break; 7758857Srgrimes } 7767001Samurai 7776059Samurai if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) { 7786059Samurai logprintf("Exception detected.\n"); 7796059Samurai break; 7806059Samurai } 7816059Samurai 7826059Samurai if (server > 0 && FD_ISSET(server, &rfds)) { 7836059Samurai#ifdef DEBUG 7846059Samurai logprintf("connected to client.\n"); 7856059Samurai#endif 7866059Samurai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 7876059Samurai if (netfd > 0) { 7886059Samurai write(wfd, "already in use.\n", 16); 7896059Samurai close(wfd); 7906059Samurai continue; 7916059Samurai } else 7926059Samurai netfd = wfd; 7936059Samurai if (dup2(netfd, 1) < 0) 7946059Samurai perror("dup2"); 7956059Samurai mode |= MODE_INTER; 7966059Samurai Greetings(); 7976764Samurai switch ( LocalAuthInit() ) { 7986764Samurai case NOT_FOUND: 7996764Samurai fprintf(stdout,LAUTH_M1); 8006764Samurai fprintf(stdout,LAUTH_M2); 8016764Samurai fflush(stdout); 8026764Samurai /* Fall down */ 8036764Samurai case VALID: 8046764Samurai VarLocalAuth = LOCAL_AUTH; 8056764Samurai break; 8066764Samurai default: 8076764Samurai break; 8086764Samurai } 8096059Samurai (void) IsInteractive(); 8106059Samurai Prompt(0); 8116059Samurai } 8126059Samurai 81310528Samurai if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds) && 81410858Samurai ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 8156059Samurai /* something to read from tty */ 8166059Samurai ReadTty(); 8176059Samurai } 8186059Samurai if (modem) { 8196059Samurai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 8206059Samurai ModemStartOutput(modem); 8216059Samurai } 8226059Samurai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 8236735Samurai if (LcpFsm.state <= ST_CLOSED) 8246735Samurai usleep(10000); 8256059Samurai n = read(modem, rbuff, sizeof(rbuff)); 8266059Samurai if ((mode & MODE_DIRECT) && n <= 0) { 8276059Samurai DownConnection(); 8286059Samurai } else 8296059Samurai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 8306059Samurai 8316059Samurai if (LcpFsm.state <= ST_CLOSED) { 8326059Samurai /* 8336059Samurai * In dedicated mode, we just discard input until LCP is started. 8346059Samurai */ 8356059Samurai if (!(mode & MODE_DEDICATED)) { 8366059Samurai cp = HdlcDetect(rbuff, n); 8376059Samurai if (cp) { 8386059Samurai /* 8396059Samurai * LCP packet is detected. Turn ourselves into packet mode. 8406059Samurai */ 8416059Samurai if (cp != rbuff) { 8426059Samurai write(1, rbuff, cp - rbuff); 8436059Samurai write(1, "\r\n", 2); 8446059Samurai } 8456059Samurai PacketMode(); 8466059Samurai#ifdef notdef 8476059Samurai AsyncInput(cp, n - (cp - rbuff)); 8486059Samurai#endif 8496059Samurai } else 8506059Samurai write(1, rbuff, n); 8516059Samurai } 8526059Samurai } else { 8536059Samurai if (n > 0) 8546059Samurai AsyncInput(rbuff, n); 8556059Samurai#ifdef notdef 8566059Samurai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 8576059Samurai#endif 8586059Samurai } 8596059Samurai } 8606059Samurai } 8617001Samurai 8626059Samurai if (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 8636059Samurai n = read(tun_in, rbuff, sizeof(rbuff)); 8646059Samurai if (n < 0) { 8656059Samurai perror("read from tun"); 8666059Samurai continue; 8676059Samurai } 8686059Samurai /* 8696059Samurai * Process on-demand dialup. Output packets are queued within tunnel 8706059Samurai * device until IPCP is opened. 8716059Samurai */ 8726059Samurai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 8737001Samurai pri = PacketCheck(rbuff, n, FL_DIAL); 8746059Samurai if (pri >= 0) { 8756059Samurai IpEnqueue(pri, rbuff, n); 8767001Samurai dial_up = TRUE; /* XXX */ 8776059Samurai } 8786059Samurai continue; 8796059Samurai } 8807001Samurai pri = PacketCheck(rbuff, n, FL_OUT); 8816059Samurai if (pri >= 0) 8826059Samurai IpEnqueue(pri, rbuff, n); 8836059Samurai } 8846059Samurai } 8856059Samurai logprintf("job done.\n"); 8866059Samurai} 887