1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * User Process PPP 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 20af57ed9fSAtsushi Murai * $Id:$ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai * o Add commands for traffic summary, version display, etc. 24af57ed9fSAtsushi Murai * o Add signal handler for misc controls. 25af57ed9fSAtsushi Murai */ 26af57ed9fSAtsushi Murai #include "fsm.h" 27af57ed9fSAtsushi Murai #include <fcntl.h> 28af57ed9fSAtsushi Murai #include <sys/time.h> 29af57ed9fSAtsushi Murai #include <termios.h> 30af57ed9fSAtsushi Murai #include <signal.h> 31af57ed9fSAtsushi Murai #include <sys/wait.h> 32af57ed9fSAtsushi Murai #include <errno.h> 33af57ed9fSAtsushi Murai #include <netdb.h> 34af57ed9fSAtsushi Murai #include <sys/socket.h> 35af57ed9fSAtsushi Murai #include <arpa/inet.h> 36af57ed9fSAtsushi Murai #include "modem.h" 37af57ed9fSAtsushi Murai #include "os.h" 38af57ed9fSAtsushi Murai #include "hdlc.h" 39af57ed9fSAtsushi Murai #include "lcp.h" 40af57ed9fSAtsushi Murai #include "ipcp.h" 41af57ed9fSAtsushi Murai #include "vars.h" 4253c9f6c0SAtsushi Murai #include "auth.h" 4353c9f6c0SAtsushi Murai 4453c9f6c0SAtsushi Murai #ifndef O_NONBLOCK 4553c9f6c0SAtsushi Murai #ifdef O_NDELAY 4653c9f6c0SAtsushi Murai #define O_NONBLOCK O_NDELAY 4753c9f6c0SAtsushi Murai #endif 4853c9f6c0SAtsushi Murai #endif 49af57ed9fSAtsushi Murai 50af57ed9fSAtsushi Murai extern void VjInit(), AsyncInit(); 51af57ed9fSAtsushi Murai extern void AsyncInput(), IpOutput(); 52af57ed9fSAtsushi Murai extern int SelectSystem(); 53af57ed9fSAtsushi Murai 54af57ed9fSAtsushi Murai extern void DecodeCommand(), Prompt(); 55af57ed9fSAtsushi Murai extern int IsInteractive(); 56af57ed9fSAtsushi Murai extern struct in_addr ifnetmask; 57af57ed9fSAtsushi Murai static void DoLoop(void); 58af57ed9fSAtsushi Murai 59af57ed9fSAtsushi Murai static struct termios oldtio; /* Original tty mode */ 60af57ed9fSAtsushi Murai static struct termios comtio; /* Command level tty mode */ 61af57ed9fSAtsushi Murai static int TermMode; 62af57ed9fSAtsushi Murai static int server, update; 63af57ed9fSAtsushi Murai struct sockaddr_in ifsin; 64af57ed9fSAtsushi Murai 65af57ed9fSAtsushi Murai static void 66af57ed9fSAtsushi Murai TtyInit() 67af57ed9fSAtsushi Murai { 68af57ed9fSAtsushi Murai struct termios newtio; 69af57ed9fSAtsushi Murai int stat; 70af57ed9fSAtsushi Murai 71af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 72af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 73af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 74af57ed9fSAtsushi Murai newtio = oldtio; 75af57ed9fSAtsushi Murai newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 76af57ed9fSAtsushi Murai newtio.c_iflag = 0; 77af57ed9fSAtsushi Murai newtio.c_oflag &= ~OPOST; 78af57ed9fSAtsushi Murai newtio.c_cc[VEOF] = _POSIX_VDISABLE; 79af57ed9fSAtsushi Murai newtio.c_cc[VINTR] = _POSIX_VDISABLE; 80af57ed9fSAtsushi Murai newtio.c_cc[VMIN] = 1; 81af57ed9fSAtsushi Murai newtio.c_cc[VTIME] = 0; 82af57ed9fSAtsushi Murai newtio.c_cflag |= CS8; 8353c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 84af57ed9fSAtsushi Murai comtio = newtio; 85af57ed9fSAtsushi Murai } 86af57ed9fSAtsushi Murai 87af57ed9fSAtsushi Murai /* 88af57ed9fSAtsushi Murai * Set tty into command mode. We allow canonical input and echo processing. 89af57ed9fSAtsushi Murai */ 90af57ed9fSAtsushi Murai static void 91af57ed9fSAtsushi Murai TtyCommandMode() 92af57ed9fSAtsushi Murai { 93af57ed9fSAtsushi Murai struct termios newtio; 94af57ed9fSAtsushi Murai int stat; 95af57ed9fSAtsushi Murai 96af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) 97af57ed9fSAtsushi Murai return; 9853c9f6c0SAtsushi Murai tcgetattr(0, &newtio); 99af57ed9fSAtsushi Murai newtio.c_lflag |= (ECHO|ICANON); 100af57ed9fSAtsushi Murai newtio.c_iflag = oldtio.c_iflag; 101af57ed9fSAtsushi Murai newtio.c_oflag |= OPOST; 10253c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &newtio); 103af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 104af57ed9fSAtsushi Murai stat |= O_NONBLOCK; 105af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 106af57ed9fSAtsushi Murai TermMode = 0; 107af57ed9fSAtsushi Murai Prompt(0); 108af57ed9fSAtsushi Murai } 109af57ed9fSAtsushi Murai 110af57ed9fSAtsushi Murai /* 111af57ed9fSAtsushi Murai * Set tty into terminal mode which is used while we invoke term command. 112af57ed9fSAtsushi Murai */ 113af57ed9fSAtsushi Murai void 114af57ed9fSAtsushi Murai TtyTermMode() 115af57ed9fSAtsushi Murai { 116af57ed9fSAtsushi Murai int stat; 117af57ed9fSAtsushi Murai 11853c9f6c0SAtsushi Murai tcsetattr(0, TCSADRAIN, &comtio); 119af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 120af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 121af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 122af57ed9fSAtsushi Murai TermMode = 1; 123af57ed9fSAtsushi Murai } 124af57ed9fSAtsushi Murai 125af57ed9fSAtsushi Murai void 126af57ed9fSAtsushi Murai Cleanup(excode) 127af57ed9fSAtsushi Murai int excode; 128af57ed9fSAtsushi Murai { 129af57ed9fSAtsushi Murai int stat; 130af57ed9fSAtsushi Murai 131af57ed9fSAtsushi Murai OsLinkdown(); 13253c9f6c0SAtsushi Murai #ifdef notdef 133af57ed9fSAtsushi Murai stat = fcntl(0, F_GETFL, 0); 134af57ed9fSAtsushi Murai stat &= ~O_NONBLOCK; 135af57ed9fSAtsushi Murai fcntl(0, F_SETFL, stat); 13653c9f6c0SAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 13753c9f6c0SAtsushi Murai #endif 138af57ed9fSAtsushi Murai OsCloseLink(1); 139af57ed9fSAtsushi Murai sleep(1); 140af57ed9fSAtsushi Murai if (mode & MODE_AUTO) 141af57ed9fSAtsushi Murai DeleteIfRoutes(1); 142af57ed9fSAtsushi Murai OsInterfaceDown(1); 143af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "PPP Terminated.\n"); 144af57ed9fSAtsushi Murai LogClose(); 145af57ed9fSAtsushi Murai if (server > 0) 146af57ed9fSAtsushi Murai close(server); 14753c9f6c0SAtsushi Murai #ifndef notdef 14853c9f6c0SAtsushi Murai stat = fcntl(0, F_GETFL, 0); 14953c9f6c0SAtsushi Murai stat &= ~O_NONBLOCK; 15053c9f6c0SAtsushi Murai fcntl(0, F_SETFL, stat); 15153c9f6c0SAtsushi Murai tcsetattr(0, TCSANOW, &oldtio); 15253c9f6c0SAtsushi Murai #endif 153af57ed9fSAtsushi Murai 154af57ed9fSAtsushi Murai exit(excode); 155af57ed9fSAtsushi Murai } 156af57ed9fSAtsushi Murai 157af57ed9fSAtsushi Murai static void 158af57ed9fSAtsushi Murai Hangup() 159af57ed9fSAtsushi Murai { 160af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "SIGHUP\n"); 161af57ed9fSAtsushi Murai signal(SIGHUP, Hangup); 162af57ed9fSAtsushi Murai Cleanup(EX_HANGUP); 163af57ed9fSAtsushi Murai } 164af57ed9fSAtsushi Murai 165af57ed9fSAtsushi Murai static void 166af57ed9fSAtsushi Murai CloseSession() 167af57ed9fSAtsushi Murai { 168af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "SIGTERM\n"); 169af57ed9fSAtsushi Murai LcpClose(); 170af57ed9fSAtsushi Murai Cleanup(EX_TERM); 171af57ed9fSAtsushi Murai } 172af57ed9fSAtsushi Murai 173af57ed9fSAtsushi Murai void 174af57ed9fSAtsushi Murai Usage() 175af57ed9fSAtsushi Murai { 176af57ed9fSAtsushi Murai fprintf(stderr, "Usage: ppp [-auto | -direct -dedicated] [system]\n"); 177af57ed9fSAtsushi Murai exit(EX_START); 178af57ed9fSAtsushi Murai } 179af57ed9fSAtsushi Murai 180af57ed9fSAtsushi Murai void 181af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv) 182af57ed9fSAtsushi Murai { 183af57ed9fSAtsushi Murai int optc; 184af57ed9fSAtsushi Murai char *cp; 185af57ed9fSAtsushi Murai 186af57ed9fSAtsushi Murai optc = 0; 187af57ed9fSAtsushi Murai while (argc > 0 && **argv == '-') { 188af57ed9fSAtsushi Murai cp = *argv + 1; 189af57ed9fSAtsushi Murai if (strcmp(cp, "auto") == 0) 190af57ed9fSAtsushi Murai mode |= MODE_AUTO; 191af57ed9fSAtsushi Murai else if (strcmp(cp, "direct") == 0) 192af57ed9fSAtsushi Murai mode |= MODE_DIRECT; 193af57ed9fSAtsushi Murai else if (strcmp(cp, "dedicated") == 0) 194af57ed9fSAtsushi Murai mode |= MODE_DEDICATED; 195af57ed9fSAtsushi Murai else 196af57ed9fSAtsushi Murai Usage(); 197af57ed9fSAtsushi Murai optc++; 198af57ed9fSAtsushi Murai argv++; argc--; 199af57ed9fSAtsushi Murai } 200af57ed9fSAtsushi Murai if (argc > 1) { 201af57ed9fSAtsushi Murai fprintf(stderr, "specify only one system label.\n"); 202af57ed9fSAtsushi Murai exit(EX_START); 203af57ed9fSAtsushi Murai } 204af57ed9fSAtsushi Murai if (argc == 1) dstsystem = *argv; 205af57ed9fSAtsushi Murai 206af57ed9fSAtsushi Murai if (optc > 1) { 207af57ed9fSAtsushi Murai fprintf(stderr, "specify only one mode.\n"); 208af57ed9fSAtsushi Murai exit(EX_START); 209af57ed9fSAtsushi Murai } 210af57ed9fSAtsushi Murai } 211af57ed9fSAtsushi Murai 212af57ed9fSAtsushi Murai static void 213af57ed9fSAtsushi Murai Greetings() 214af57ed9fSAtsushi Murai { 215af57ed9fSAtsushi Murai printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 216af57ed9fSAtsushi Murai fflush(stdout); 217af57ed9fSAtsushi Murai } 218af57ed9fSAtsushi Murai 219af57ed9fSAtsushi Murai void 220af57ed9fSAtsushi Murai main(argc, argv) 221af57ed9fSAtsushi Murai int argc; 222af57ed9fSAtsushi Murai char **argv; 223af57ed9fSAtsushi Murai { 224af57ed9fSAtsushi Murai int tunno; 225af57ed9fSAtsushi Murai int on = 1; 226af57ed9fSAtsushi Murai 227af57ed9fSAtsushi Murai argc--; argv++; 228af57ed9fSAtsushi Murai 229af57ed9fSAtsushi Murai mode = MODE_INTER; /* default operation is interactive mode */ 230af57ed9fSAtsushi Murai netfd = -1; 231af57ed9fSAtsushi Murai ProcessArgs(argc, argv); 232af57ed9fSAtsushi Murai Greetings(); 233af57ed9fSAtsushi Murai GetUid(); 234af57ed9fSAtsushi Murai IpcpDefAddress(); 235af57ed9fSAtsushi Murai 236af57ed9fSAtsushi Murai if (SelectSystem("default", CONFFILE) < 0) { 237af57ed9fSAtsushi Murai fprintf(stderr, "Warning: No default entry is given in config file.\n"); 238af57ed9fSAtsushi Murai } 239af57ed9fSAtsushi Murai 240af57ed9fSAtsushi Murai if (LogOpen()) 241af57ed9fSAtsushi Murai exit(EX_START); 242af57ed9fSAtsushi Murai 24353c9f6c0SAtsushi Murai switch ( LocalAuthInit() ) { 24453c9f6c0SAtsushi Murai case NOT_FOUND: 24553c9f6c0SAtsushi Murai fprintf(stderr, "Warning: No password entry in secret file\n"); 24653c9f6c0SAtsushi Murai fprintf(stderr, "Warning: Anyone is allowd manipulating!!!\n"); 24753c9f6c0SAtsushi Murai VarLocalAuth = LOCAL_AUTH; 24853c9f6c0SAtsushi Murai break; 24953c9f6c0SAtsushi Murai default: 25053c9f6c0SAtsushi Murai break; 25153c9f6c0SAtsushi Murai } 25253c9f6c0SAtsushi Murai 253af57ed9fSAtsushi Murai if (OpenTunnel(&tunno) < 0) { 254af57ed9fSAtsushi Murai perror("open_tun"); 255af57ed9fSAtsushi Murai exit(EX_START); 256af57ed9fSAtsushi Murai } 257af57ed9fSAtsushi Murai 258af57ed9fSAtsushi Murai if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 259af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 260af57ed9fSAtsushi Murai if (mode & MODE_INTER) { 261af57ed9fSAtsushi Murai printf("Interactive mode\n"); 262af57ed9fSAtsushi Murai netfd = 0; 263af57ed9fSAtsushi Murai } else if (mode & MODE_AUTO) { 264af57ed9fSAtsushi Murai printf("Automatic mode\n"); 265af57ed9fSAtsushi Murai if (dstsystem == NULL) { 266af57ed9fSAtsushi Murai fprintf(stderr, "Destination system must be specified in auto mode.\n"); 267af57ed9fSAtsushi Murai exit(EX_START); 268af57ed9fSAtsushi Murai } 269af57ed9fSAtsushi Murai } 270af57ed9fSAtsushi Murai 27153c9f6c0SAtsushi Murai tcgetattr(0, &oldtio); /* Save original tty mode */ 272af57ed9fSAtsushi Murai 273af57ed9fSAtsushi Murai signal(SIGHUP, Hangup); 274af57ed9fSAtsushi Murai signal(SIGTERM, CloseSession); 275af57ed9fSAtsushi Murai signal(SIGINT, CloseSession); 27653c9f6c0SAtsushi Murai #ifdef SIGSEGV 277af57ed9fSAtsushi Murai signal(SIGSEGV, Hangup); 27853c9f6c0SAtsushi Murai #endif 27953c9f6c0SAtsushi Murai #ifdef SIGPIPE 28053c9f6c0SAtsushi Murai signal(SIGPIPE, Hangup); 28153c9f6c0SAtsushi Murai #endif 28253c9f6c0SAtsushi Murai #ifdef SIGALRM 28353c9f6c0SAtsushi Murai signal(SIGALRM, SIG_IGN); 28453c9f6c0SAtsushi Murai #endif 285af57ed9fSAtsushi Murai 286af57ed9fSAtsushi Murai if (dstsystem) { 287af57ed9fSAtsushi Murai if (SelectSystem(dstsystem, CONFFILE) < 0) { 288af57ed9fSAtsushi Murai fprintf(stderr, "Destination system not found in conf file.\n"); 289af57ed9fSAtsushi Murai Cleanup(EX_START); 290af57ed9fSAtsushi Murai } 291af57ed9fSAtsushi Murai if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 292af57ed9fSAtsushi Murai fprintf(stderr, "Must specify dstaddr with auto mode.\n"); 293af57ed9fSAtsushi Murai Cleanup(EX_START); 294af57ed9fSAtsushi Murai } 295af57ed9fSAtsushi Murai } 296af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) 297af57ed9fSAtsushi Murai printf("Packet mode enabled.\n"); 298af57ed9fSAtsushi Murai 299af57ed9fSAtsushi Murai #ifdef notdef 300af57ed9fSAtsushi Murai if (mode & MODE_AUTO) { 301af57ed9fSAtsushi Murai OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 302af57ed9fSAtsushi Murai } 303af57ed9fSAtsushi Murai #endif 304af57ed9fSAtsushi Murai 305af57ed9fSAtsushi Murai if (!(mode & MODE_INTER)) { 306af57ed9fSAtsushi Murai int port = SERVER_PORT + tunno; 307af57ed9fSAtsushi Murai /* 308af57ed9fSAtsushi Murai * Create server socket and listen at there. 309af57ed9fSAtsushi Murai */ 310af57ed9fSAtsushi Murai server = socket(PF_INET, SOCK_STREAM, 0); 311af57ed9fSAtsushi Murai if (server < 0) { 312af57ed9fSAtsushi Murai perror("socket"); 313af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 314af57ed9fSAtsushi Murai } 315af57ed9fSAtsushi Murai ifsin.sin_family = AF_INET; 316af57ed9fSAtsushi Murai ifsin.sin_addr.s_addr = INADDR_ANY; 317af57ed9fSAtsushi Murai ifsin.sin_port = htons(port); 318af57ed9fSAtsushi Murai if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 319af57ed9fSAtsushi Murai perror("bind"); 320af57ed9fSAtsushi Murai if (errno == EADDRINUSE) 321af57ed9fSAtsushi Murai fprintf(stderr, "Wait for a while, then try again.\n"); 322af57ed9fSAtsushi Murai Cleanup(EX_SOCK); 323af57ed9fSAtsushi Murai } 324af57ed9fSAtsushi Murai listen(server, 5); 325af57ed9fSAtsushi Murai 326af57ed9fSAtsushi Murai DupLog(); 327af57ed9fSAtsushi Murai if (!(mode & MODE_DIRECT)) { 328af57ed9fSAtsushi Murai if (fork()) 329af57ed9fSAtsushi Murai exit(0); 330af57ed9fSAtsushi Murai } 331af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "Listening at %d.\n", port); 332af57ed9fSAtsushi Murai #ifdef DOTTYINIT 33353c9f6c0SAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 334af57ed9fSAtsushi Murai #else 335af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) { 336af57ed9fSAtsushi Murai #endif 337af57ed9fSAtsushi Murai TtyInit(); 338af57ed9fSAtsushi Murai } else { 339af57ed9fSAtsushi Murai setsid(); /* detach control tty */ 340af57ed9fSAtsushi Murai } 341af57ed9fSAtsushi Murai } else { 342af57ed9fSAtsushi Murai server = -1; 343af57ed9fSAtsushi Murai TtyInit(); 344af57ed9fSAtsushi Murai TtyCommandMode(); 345af57ed9fSAtsushi Murai } 346af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "PPP Started.\n"); 347af57ed9fSAtsushi Murai 348af57ed9fSAtsushi Murai 349af57ed9fSAtsushi Murai do 350af57ed9fSAtsushi Murai DoLoop(); 351af57ed9fSAtsushi Murai while (mode & MODE_DEDICATED); 352af57ed9fSAtsushi Murai 353af57ed9fSAtsushi Murai Cleanup(EX_DONE); 354af57ed9fSAtsushi Murai } 355af57ed9fSAtsushi Murai 356af57ed9fSAtsushi Murai /* 357af57ed9fSAtsushi Murai * Turn into packet mode, where we speek PPP. 358af57ed9fSAtsushi Murai */ 359af57ed9fSAtsushi Murai void 360af57ed9fSAtsushi Murai PacketMode() 361af57ed9fSAtsushi Murai { 362af57ed9fSAtsushi Murai if (RawModem(modem) < 0) { 363af57ed9fSAtsushi Murai fprintf(stderr, "Not connected.\r\n"); 364af57ed9fSAtsushi Murai return; 365af57ed9fSAtsushi Murai } 366af57ed9fSAtsushi Murai 367af57ed9fSAtsushi Murai AsyncInit(); 368af57ed9fSAtsushi Murai VjInit(); 369af57ed9fSAtsushi Murai LcpInit(); 370af57ed9fSAtsushi Murai IpcpInit(); 371af57ed9fSAtsushi Murai CcpInit(); 372af57ed9fSAtsushi Murai LcpUp(); 373af57ed9fSAtsushi Murai 374af57ed9fSAtsushi Murai if (mode & (MODE_DIRECT|MODE_DEDICATED)) 375af57ed9fSAtsushi Murai LcpOpen(OPEN_ACTIVE); 376af57ed9fSAtsushi Murai else 377af57ed9fSAtsushi Murai LcpOpen(VarOpenMode); 378af57ed9fSAtsushi Murai if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 379af57ed9fSAtsushi Murai TtyCommandMode(); 380af57ed9fSAtsushi Murai fprintf(stderr, "Packet mode.\r\n"); 381af57ed9fSAtsushi Murai } 382af57ed9fSAtsushi Murai } 383af57ed9fSAtsushi Murai 384af57ed9fSAtsushi Murai static void 385af57ed9fSAtsushi Murai ShowHelp() 386af57ed9fSAtsushi Murai { 387af57ed9fSAtsushi Murai fprintf(stderr, "Following commands are available\r\n"); 388af57ed9fSAtsushi Murai fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 389af57ed9fSAtsushi Murai fprintf(stderr, " ~.\tTerminate program\r\n"); 390af57ed9fSAtsushi Murai } 391af57ed9fSAtsushi Murai 392af57ed9fSAtsushi Murai static void 393af57ed9fSAtsushi Murai ReadTty() 394af57ed9fSAtsushi Murai { 395af57ed9fSAtsushi Murai int n; 396af57ed9fSAtsushi Murai char ch; 397af57ed9fSAtsushi Murai static int ttystate; 398af57ed9fSAtsushi Murai #define MAXLINESIZE 200 399af57ed9fSAtsushi Murai char linebuff[MAXLINESIZE]; 400af57ed9fSAtsushi Murai 401af57ed9fSAtsushi Murai #ifdef DEBUG 402af57ed9fSAtsushi Murai logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 403af57ed9fSAtsushi Murai #endif 404af57ed9fSAtsushi Murai if (!TermMode) { 405af57ed9fSAtsushi Murai n = read(netfd, linebuff, sizeof(linebuff)-1); 40653c9f6c0SAtsushi Murai if (n > 0) { 407af57ed9fSAtsushi Murai DecodeCommand(linebuff, n, 1); 40853c9f6c0SAtsushi Murai } else { 409af57ed9fSAtsushi Murai #ifdef DEBUG 410af57ed9fSAtsushi Murai logprintf("connection closed.\n"); 411af57ed9fSAtsushi Murai #endif 41253c9f6c0SAtsushi Murai VarLocalAuth = LOCAL_NO_AUTH; 413af57ed9fSAtsushi Murai close(netfd); 414af57ed9fSAtsushi Murai netfd = -1; 415af57ed9fSAtsushi Murai mode &= ~MODE_INTER; 416af57ed9fSAtsushi Murai } 417af57ed9fSAtsushi Murai return; 418af57ed9fSAtsushi Murai } 419af57ed9fSAtsushi Murai 420af57ed9fSAtsushi Murai /* 421af57ed9fSAtsushi Murai * We are in terminal mode, decode special sequences 422af57ed9fSAtsushi Murai */ 423af57ed9fSAtsushi Murai n = read(0, &ch, 1); 424af57ed9fSAtsushi Murai #ifdef DEBUG 425af57ed9fSAtsushi Murai logprintf("got %d bytes\n", n); 426af57ed9fSAtsushi Murai #endif 427af57ed9fSAtsushi Murai 428af57ed9fSAtsushi Murai if (n > 0) { 429af57ed9fSAtsushi Murai switch (ttystate) { 430af57ed9fSAtsushi Murai case 0: 431af57ed9fSAtsushi Murai if (ch == '~') 432af57ed9fSAtsushi Murai ttystate++; 433af57ed9fSAtsushi Murai else 434af57ed9fSAtsushi Murai write(modem, &ch, n); 435af57ed9fSAtsushi Murai break; 436af57ed9fSAtsushi Murai case 1: 437af57ed9fSAtsushi Murai switch (ch) { 438af57ed9fSAtsushi Murai case '?': 439af57ed9fSAtsushi Murai ShowHelp(); 440af57ed9fSAtsushi Murai break; 441af57ed9fSAtsushi Murai case '-': 442af57ed9fSAtsushi Murai if (loglevel > 0) { 443af57ed9fSAtsushi Murai loglevel--; 444af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 445af57ed9fSAtsushi Murai } 446af57ed9fSAtsushi Murai break; 447af57ed9fSAtsushi Murai case '+': 448af57ed9fSAtsushi Murai loglevel++; 449af57ed9fSAtsushi Murai fprintf(stderr, "New loglevel is %d\r\n", loglevel); 450af57ed9fSAtsushi Murai break; 451af57ed9fSAtsushi Murai #ifdef DEBUG 452af57ed9fSAtsushi Murai case 'm': 453af57ed9fSAtsushi Murai ShowMemMap(); 454af57ed9fSAtsushi Murai break; 455af57ed9fSAtsushi Murai #endif 456af57ed9fSAtsushi Murai case 'p': 457af57ed9fSAtsushi Murai /* 458af57ed9fSAtsushi Murai * XXX: Should check carrier. 459af57ed9fSAtsushi Murai */ 460af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 461af57ed9fSAtsushi Murai VarOpenMode = OPEN_ACTIVE; 462af57ed9fSAtsushi Murai PacketMode(); 463af57ed9fSAtsushi Murai } 464af57ed9fSAtsushi Murai break; 465af57ed9fSAtsushi Murai #ifdef DEBUG 466af57ed9fSAtsushi Murai case 't': 467af57ed9fSAtsushi Murai ShowTimers(); 468af57ed9fSAtsushi Murai break; 469af57ed9fSAtsushi Murai #endif 470af57ed9fSAtsushi Murai case '.': 471af57ed9fSAtsushi Murai TermMode = 1; 472af57ed9fSAtsushi Murai TtyCommandMode(); 473af57ed9fSAtsushi Murai break; 474af57ed9fSAtsushi Murai default: 475af57ed9fSAtsushi Murai if (write(modem, &ch, n) < 0) 476af57ed9fSAtsushi Murai fprintf(stderr, "err in write.\r\n"); 477af57ed9fSAtsushi Murai break; 478af57ed9fSAtsushi Murai } 479af57ed9fSAtsushi Murai ttystate = 0; 480af57ed9fSAtsushi Murai break; 481af57ed9fSAtsushi Murai } 482af57ed9fSAtsushi Murai } 483af57ed9fSAtsushi Murai } 484af57ed9fSAtsushi Murai 485af57ed9fSAtsushi Murai 486af57ed9fSAtsushi Murai /* 487af57ed9fSAtsushi Murai * Here, we'll try to detect HDLC frame 488af57ed9fSAtsushi Murai */ 489af57ed9fSAtsushi Murai 490af57ed9fSAtsushi Murai static char *FrameHeaders[] = { 49153c9f6c0SAtsushi Murai "\176\377\003\300\041", 49253c9f6c0SAtsushi Murai "\176\377\175\043\300\041", 49353c9f6c0SAtsushi Murai "\176\177\175\043\100\041", 49453c9f6c0SAtsushi Murai "\176\175\337\175\043\300\041", 49553c9f6c0SAtsushi Murai "\176\175\137\175\043\100\041", 496af57ed9fSAtsushi Murai NULL, 497af57ed9fSAtsushi Murai }; 498af57ed9fSAtsushi Murai 499af57ed9fSAtsushi Murai u_char * 500af57ed9fSAtsushi Murai HdlcDetect(cp, n) 501af57ed9fSAtsushi Murai u_char *cp; 502af57ed9fSAtsushi Murai int n; 503af57ed9fSAtsushi Murai { 50453c9f6c0SAtsushi Murai char *ptr, *fp, **hp; 505af57ed9fSAtsushi Murai 506af57ed9fSAtsushi Murai cp[n] = '\0'; /* be sure to null terminated */ 507af57ed9fSAtsushi Murai ptr = NULL; 508af57ed9fSAtsushi Murai for (hp = FrameHeaders; *hp; hp++) { 50953c9f6c0SAtsushi Murai fp = *hp; 51053c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 51153c9f6c0SAtsushi Murai fp++; 51253c9f6c0SAtsushi Murai if (ptr = strstr((char *)cp, fp)) 513af57ed9fSAtsushi Murai break; 514af57ed9fSAtsushi Murai } 515af57ed9fSAtsushi Murai return((u_char *)ptr); 516af57ed9fSAtsushi Murai } 517af57ed9fSAtsushi Murai 518af57ed9fSAtsushi Murai static struct pppTimer RedialTimer; 519af57ed9fSAtsushi Murai 520af57ed9fSAtsushi Murai static void 521af57ed9fSAtsushi Murai RedialTimeout() 522af57ed9fSAtsushi Murai { 523af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 524af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "Redialing timer expired.\n"); 525af57ed9fSAtsushi Murai } 526af57ed9fSAtsushi Murai 527af57ed9fSAtsushi Murai static void 528af57ed9fSAtsushi Murai StartRedialTimer() 529af57ed9fSAtsushi Murai { 530af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "Enter pause for redialing.\n"); 531af57ed9fSAtsushi Murai StopTimer(&RedialTimer); 532af57ed9fSAtsushi Murai RedialTimer.state = TIMER_STOPPED; 533af57ed9fSAtsushi Murai RedialTimer.load = REDIAL_PERIOD * SECTICKS; 534af57ed9fSAtsushi Murai RedialTimer.func = RedialTimeout; 535af57ed9fSAtsushi Murai StartTimer(&RedialTimer); 536af57ed9fSAtsushi Murai } 537af57ed9fSAtsushi Murai 538af57ed9fSAtsushi Murai 539af57ed9fSAtsushi Murai static void 540af57ed9fSAtsushi Murai DoLoop() 541af57ed9fSAtsushi Murai { 542af57ed9fSAtsushi Murai fd_set rfds, wfds, efds; 543af57ed9fSAtsushi Murai int pri, i, n, wfd; 544af57ed9fSAtsushi Murai struct sockaddr_in hisaddr; 545af57ed9fSAtsushi Murai struct timeval timeout, *tp; 546af57ed9fSAtsushi Murai int ssize = sizeof(hisaddr); 547af57ed9fSAtsushi Murai u_char *cp; 548af57ed9fSAtsushi Murai u_char rbuff[MAX_MRU]; 54953c9f6c0SAtsushi Murai struct itimerval itimer; 550af57ed9fSAtsushi Murai 551af57ed9fSAtsushi Murai if (mode & MODE_DIRECT) { 552af57ed9fSAtsushi Murai modem = OpenModem(mode); 553af57ed9fSAtsushi Murai fprintf(stderr, "Packet mode enabled\n"); 554af57ed9fSAtsushi Murai PacketMode(); 555af57ed9fSAtsushi Murai } else if (mode & MODE_DEDICATED) { 556af57ed9fSAtsushi Murai if (!modem) 557af57ed9fSAtsushi Murai modem = OpenModem(mode); 558af57ed9fSAtsushi Murai } 559af57ed9fSAtsushi Murai 560af57ed9fSAtsushi Murai fflush(stdout); 561af57ed9fSAtsushi Murai 562af57ed9fSAtsushi Murai timeout.tv_sec = 0;; 56353c9f6c0SAtsushi Murai #ifdef SIGALRM 56453c9f6c0SAtsushi Murai signal(SIGALRM, (void (*)(int))TimerService); 56553c9f6c0SAtsushi Murai itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0; 56653c9f6c0SAtsushi Murai itimer.it_interval.tv_usec = itimer.it_value.tv_usec = TICKUNIT; 56753c9f6c0SAtsushi Murai setitimer(ITIMER_REAL, &itimer, NULL); 56853c9f6c0SAtsushi Murai #else 569af57ed9fSAtsushi Murai timeout.tv_usec = 0; 57053c9f6c0SAtsushi Murai #endif 571af57ed9fSAtsushi Murai 572af57ed9fSAtsushi Murai for (;;) { 573af57ed9fSAtsushi Murai IpStartOutput(); 574af57ed9fSAtsushi Murai FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 575af57ed9fSAtsushi Murai FD_SET(tun_in, &rfds); 576af57ed9fSAtsushi Murai if (server > 0) FD_SET(server, &rfds); 577af57ed9fSAtsushi Murai 578af57ed9fSAtsushi Murai /* *** IMPORTANT *** 579af57ed9fSAtsushi Murai * 580af57ed9fSAtsushi Murai * CPU is serviced every TICKUNIT micro seconds. 581af57ed9fSAtsushi Murai * This value must be chosen with great care. If this values is 582af57ed9fSAtsushi Murai * too big, it results loss of characters from modem and poor responce. 583af57ed9fSAtsushi Murai * If this values is too small, ppp process eats many CPU time. 584af57ed9fSAtsushi Murai */ 58553c9f6c0SAtsushi Murai #ifndef SIGALRM 586af57ed9fSAtsushi Murai usleep(TICKUNIT); 587af57ed9fSAtsushi Murai TimerService(); 58853c9f6c0SAtsushi Murai #endif 589af57ed9fSAtsushi Murai 590af57ed9fSAtsushi Murai if (modem) { 591af57ed9fSAtsushi Murai FD_SET(modem, &rfds); 592af57ed9fSAtsushi Murai FD_SET(modem, &efds); 59353c9f6c0SAtsushi Murai if (ModemQlen() > 0) { 594af57ed9fSAtsushi Murai FD_SET(modem, &wfds); 595af57ed9fSAtsushi Murai } 59653c9f6c0SAtsushi Murai } 597af57ed9fSAtsushi Murai if (netfd > -1) { 598af57ed9fSAtsushi Murai FD_SET(netfd, &rfds); 599af57ed9fSAtsushi Murai FD_SET(netfd, &efds); 600af57ed9fSAtsushi Murai } 60153c9f6c0SAtsushi Murai #ifndef SIGALRM 602af57ed9fSAtsushi Murai /* 603af57ed9fSAtsushi Murai * Normally, slect() will not block because modem is writable. 604af57ed9fSAtsushi Murai * In AUTO mode, select will block until we find packet from tun. 605af57ed9fSAtsushi Murai * However, we have to run ourselves while we are in redial wait state. 606af57ed9fSAtsushi Murai */ 607af57ed9fSAtsushi Murai tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 608af57ed9fSAtsushi Murai i = select(tun_in+10, &rfds, &wfds, &efds, tp); 60953c9f6c0SAtsushi Murai #else 61053c9f6c0SAtsushi Murai i = select(tun_in+10, &rfds, &wfds, &efds, NULL); 61153c9f6c0SAtsushi Murai #endif 612af57ed9fSAtsushi Murai if (i == 0) { 613af57ed9fSAtsushi Murai continue; 614af57ed9fSAtsushi Murai } 61553c9f6c0SAtsushi Murai 616af57ed9fSAtsushi Murai if (i < 0) { 61753c9f6c0SAtsushi Murai if (errno == EINTR) 61853c9f6c0SAtsushi Murai continue; 619af57ed9fSAtsushi Murai perror("select"); 620af57ed9fSAtsushi Murai break; 621af57ed9fSAtsushi Murai } 622af57ed9fSAtsushi Murai if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) { 623af57ed9fSAtsushi Murai logprintf("Exception detected.\n"); 624af57ed9fSAtsushi Murai break; 625af57ed9fSAtsushi Murai } 626af57ed9fSAtsushi Murai 627af57ed9fSAtsushi Murai if (server > 0 && FD_ISSET(server, &rfds)) { 628af57ed9fSAtsushi Murai #ifdef DEBUG 629af57ed9fSAtsushi Murai logprintf("connected to client.\n"); 630af57ed9fSAtsushi Murai #endif 631af57ed9fSAtsushi Murai wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 632af57ed9fSAtsushi Murai if (netfd > 0) { 633af57ed9fSAtsushi Murai write(wfd, "already in use.\n", 16); 634af57ed9fSAtsushi Murai close(wfd); 635af57ed9fSAtsushi Murai continue; 636af57ed9fSAtsushi Murai } else 637af57ed9fSAtsushi Murai netfd = wfd; 638af57ed9fSAtsushi Murai if (dup2(netfd, 1) < 0) 639af57ed9fSAtsushi Murai perror("dup2"); 640af57ed9fSAtsushi Murai mode |= MODE_INTER; 641af57ed9fSAtsushi Murai Greetings(); 642af57ed9fSAtsushi Murai (void) IsInteractive(); 643af57ed9fSAtsushi Murai Prompt(0); 644af57ed9fSAtsushi Murai } 645af57ed9fSAtsushi Murai 646af57ed9fSAtsushi Murai if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds)) { 647af57ed9fSAtsushi Murai /* something to read from tty */ 648af57ed9fSAtsushi Murai ReadTty(); 649af57ed9fSAtsushi Murai } 650af57ed9fSAtsushi Murai if (modem) { 651af57ed9fSAtsushi Murai if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 652af57ed9fSAtsushi Murai ModemStartOutput(modem); 653af57ed9fSAtsushi Murai } 654af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 65553c9f6c0SAtsushi Murai if (LcpFsm.state <= ST_CLOSED) 65653c9f6c0SAtsushi Murai usleep(10000); 657af57ed9fSAtsushi Murai n = read(modem, rbuff, sizeof(rbuff)); 658af57ed9fSAtsushi Murai if ((mode & MODE_DIRECT) && n <= 0) { 659af57ed9fSAtsushi Murai DownConnection(); 660af57ed9fSAtsushi Murai } else 661af57ed9fSAtsushi Murai LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 662af57ed9fSAtsushi Murai 663af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED) { 664af57ed9fSAtsushi Murai /* 665af57ed9fSAtsushi Murai * In dedicated mode, we just discard input until LCP is started. 666af57ed9fSAtsushi Murai */ 667af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 668af57ed9fSAtsushi Murai cp = HdlcDetect(rbuff, n); 669af57ed9fSAtsushi Murai if (cp) { 670af57ed9fSAtsushi Murai /* 671af57ed9fSAtsushi Murai * LCP packet is detected. Turn ourselves into packet mode. 672af57ed9fSAtsushi Murai */ 673af57ed9fSAtsushi Murai if (cp != rbuff) { 674af57ed9fSAtsushi Murai write(1, rbuff, cp - rbuff); 675af57ed9fSAtsushi Murai write(1, "\r\n", 2); 676af57ed9fSAtsushi Murai } 677af57ed9fSAtsushi Murai PacketMode(); 678af57ed9fSAtsushi Murai #ifdef notdef 679af57ed9fSAtsushi Murai AsyncInput(cp, n - (cp - rbuff)); 680af57ed9fSAtsushi Murai #endif 681af57ed9fSAtsushi Murai } else 682af57ed9fSAtsushi Murai write(1, rbuff, n); 683af57ed9fSAtsushi Murai } 684af57ed9fSAtsushi Murai } else { 685af57ed9fSAtsushi Murai if (n > 0) 686af57ed9fSAtsushi Murai AsyncInput(rbuff, n); 687af57ed9fSAtsushi Murai #ifdef notdef 688af57ed9fSAtsushi Murai continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 689af57ed9fSAtsushi Murai #endif 690af57ed9fSAtsushi Murai } 691af57ed9fSAtsushi Murai } 692af57ed9fSAtsushi Murai } 693af57ed9fSAtsushi Murai if (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 694af57ed9fSAtsushi Murai /* 695af57ed9fSAtsushi Murai * If there are many packets queued, wait until they are drained. 696af57ed9fSAtsushi Murai */ 697af57ed9fSAtsushi Murai if (ModemQlen() > 5) 698af57ed9fSAtsushi Murai continue; 699af57ed9fSAtsushi Murai 700af57ed9fSAtsushi Murai n = read(tun_in, rbuff, sizeof(rbuff)); 701af57ed9fSAtsushi Murai if (n < 0) { 702af57ed9fSAtsushi Murai perror("read from tun"); 703af57ed9fSAtsushi Murai continue; 704af57ed9fSAtsushi Murai } 705af57ed9fSAtsushi Murai /* 706af57ed9fSAtsushi Murai * Process on-demand dialup. Output packets are queued within tunnel 707af57ed9fSAtsushi Murai * device until IPCP is opened. 708af57ed9fSAtsushi Murai */ 709af57ed9fSAtsushi Murai if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 710af57ed9fSAtsushi Murai pri = PacketCheck(rbuff, n, 2); 711af57ed9fSAtsushi Murai if (pri >= 0) { 712af57ed9fSAtsushi Murai if (RedialTimer.state == TIMER_RUNNING) { 713af57ed9fSAtsushi Murai /* 714af57ed9fSAtsushi Murai * We are in redial wait state. Ignore packet. 715af57ed9fSAtsushi Murai */ 716af57ed9fSAtsushi Murai continue; 717af57ed9fSAtsushi Murai } 718af57ed9fSAtsushi Murai modem = OpenModem(mode); 719af57ed9fSAtsushi Murai #ifdef DEBUG 720af57ed9fSAtsushi Murai logprintf("going to dial: modem = %d\n", modem); 721af57ed9fSAtsushi Murai #endif 722af57ed9fSAtsushi Murai if (modem < 0) { 723af57ed9fSAtsushi Murai printf("failed to open modem.\n"); 724af57ed9fSAtsushi Murai Cleanup(EX_MODEM); 725af57ed9fSAtsushi Murai } 726af57ed9fSAtsushi Murai 727af57ed9fSAtsushi Murai if (DialModem()) { 728af57ed9fSAtsushi Murai sleep(1); /* little pause to allow peer starts */ 729af57ed9fSAtsushi Murai ModemTimeout(); 730af57ed9fSAtsushi Murai PacketMode(); 731af57ed9fSAtsushi Murai } else { 732af57ed9fSAtsushi Murai CloseModem(); 733af57ed9fSAtsushi Murai /* Dial failed. Keep quite during redial wait period. */ 734af57ed9fSAtsushi Murai /* XXX: We shoud implement re-dial */ 735af57ed9fSAtsushi Murai StartRedialTimer(); 736af57ed9fSAtsushi Murai continue; 737af57ed9fSAtsushi Murai } 738af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 739af57ed9fSAtsushi Murai } 740af57ed9fSAtsushi Murai continue; 741af57ed9fSAtsushi Murai } 742af57ed9fSAtsushi Murai pri = PacketCheck(rbuff, n, 1); 743af57ed9fSAtsushi Murai if (pri >= 0) 744af57ed9fSAtsushi Murai IpEnqueue(pri, rbuff, n); 745af57ed9fSAtsushi Murai } 746af57ed9fSAtsushi Murai } 74753c9f6c0SAtsushi Murai #ifdef SIGALRM 74853c9f6c0SAtsushi Murai itimer.it_value.tv_usec = itimer.it_value.tv_sec = 0; 74953c9f6c0SAtsushi Murai setitimer(ITIMER_REAL, &itimer, NULL); 75053c9f6c0SAtsushi Murai signal(SIGALRM, SIG_DFL); 75153c9f6c0SAtsushi Murai #endif 752af57ed9fSAtsushi Murai logprintf("job done.\n"); 753af57ed9fSAtsushi Murai } 754