main.c revision 24843
1129198Scognet/* 2129198Scognet * User Process PPP 3139735Simp * 4129198Scognet * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5129198Scognet * 6129198Scognet * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7129198Scognet * 8129198Scognet * Redistribution and use in source and binary forms are permitted 9129198Scognet * provided that the above copyright notice and this paragraph are 10129198Scognet * duplicated in all such forms and that any documentation, 11129198Scognet * advertising materials, and other materials related to such 12129198Scognet * distribution and use acknowledge that the software was developed 13129198Scognet * by the Internet Initiative Japan, Inc. The name of the 14129198Scognet * IIJ may not be used to endorse or promote products derived 15129198Scognet * from this software without specific prior written permission. 16129198Scognet * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17129198Scognet * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18129198Scognet * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19129198Scognet * 20129198Scognet * $Id: main.c,v 1.41 1997/04/09 17:35:54 ache Exp $ 21129198Scognet * 22129198Scognet * TODO: 23129198Scognet * o Add commands for traffic summary, version display, etc. 24129198Scognet * o Add signal handler for misc controls. 25129198Scognet */ 26129198Scognet#include "fsm.h" 27129198Scognet#include <fcntl.h> 28129198Scognet#include <paths.h> 29129198Scognet#include <sys/time.h> 30129198Scognet#include <termios.h> 31129198Scognet#include <signal.h> 32129198Scognet#include <sys/wait.h> 33129198Scognet#include <errno.h> 34129198Scognet#include <netdb.h> 35129198Scognet#include <unistd.h> 36129198Scognet#include <sys/socket.h> 37129198Scognet#include <arpa/inet.h> 38129198Scognet#include <netinet/in_systm.h> 39129198Scognet#include <netinet/ip.h> 40129198Scognet#include "modem.h" 41129198Scognet#include "os.h" 42129198Scognet#include "hdlc.h" 43129198Scognet#include "ccp.h" 44129198Scognet#include "lcp.h" 45129198Scognet#include "ipcp.h" 46129198Scognet#include "vars.h" 47129198Scognet#include "auth.h" 48129198Scognet#include "filter.h" 49129198Scognet#include "systems.h" 50129198Scognet#include "ip.h" 51129198Scognet#include "alias.h" 52129198Scognet#include "sig.h" 53129198Scognet 54129198Scognet#define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 55129198Scognet#define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n" 56129198Scognet 57129198Scognet#ifndef O_NONBLOCK 58129198Scognet#ifdef O_NDELAY 59129198Scognet#define O_NONBLOCK O_NDELAY 60129198Scognet#endif 61129198Scognet#endif 62129198Scognet 63129198Scognetextern void VjInit(), AsyncInit(); 64129198Scognetextern void AsyncInput(), IpOutput(); 65129198Scognetextern int SelectSystem(); 66129198Scognet 67129198Scognetextern void DecodeCommand(), Prompt(); 68129198Scognetextern int aft_cmd; 69239268Sgonzoextern int IsInteractive(); 70239268Sgonzoextern struct in_addr ifnetmask; 71239268Sgonzostatic void DoLoop(void); 72266341Sianstatic void TerminalStop(); 73266341Sian 74266341Sianstatic struct termios oldtio; /* Original tty mode */ 75239268Sgonzostatic struct termios comtio; /* Command level tty mode */ 76129198Scognetint TermMode; 77129198Scognetstatic int server; 78129198Scognetstatic pid_t BGPid = 0; 79129198Scognetstruct sockaddr_in ifsin; 80129198Scognetchar pid_filename[128]; 81236992Simp 82129198Scognetstatic void 83129198ScognetTtyInit() 84129198Scognet{ 85129198Scognet struct termios newtio; 86129198Scognet int stat; 87129198Scognet 88129198Scognet stat = fcntl(0, F_GETFL, 0); 89129198Scognet stat |= O_NONBLOCK; 90 fcntl(0, F_SETFL, stat); 91 newtio = oldtio; 92 newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 93 newtio.c_iflag = 0; 94 newtio.c_oflag &= ~OPOST; 95 newtio.c_cc[VEOF] = _POSIX_VDISABLE; 96 newtio.c_cc[VINTR] = _POSIX_VDISABLE; 97 newtio.c_cc[VMIN] = 1; 98 newtio.c_cc[VTIME] = 0; 99 newtio.c_cflag |= CS8; 100 tcsetattr(0, TCSADRAIN, &newtio); 101 comtio = newtio; 102} 103 104/* 105 * Set tty into command mode. We allow canonical input and echo processing. 106 */ 107void 108TtyCommandMode(prompt) 109int prompt; 110{ 111 struct termios newtio; 112 int stat; 113 114 if (!(mode & MODE_INTER)) 115 return; 116 tcgetattr(0, &newtio); 117 newtio.c_lflag |= (ECHO|ISIG|ICANON); 118 newtio.c_iflag = oldtio.c_iflag; 119 newtio.c_oflag |= OPOST; 120 tcsetattr(0, TCSADRAIN, &newtio); 121 stat = fcntl(0, F_GETFL, 0); 122 stat |= O_NONBLOCK; 123 fcntl(0, F_SETFL, stat); 124 TermMode = 0; 125 if(prompt) Prompt(0); 126} 127 128/* 129 * Set tty into terminal mode which is used while we invoke term command. 130 */ 131void 132TtyTermMode() 133{ 134 int stat; 135 136 tcsetattr(0, TCSADRAIN, &comtio); 137 stat = fcntl(0, F_GETFL, 0); 138 stat &= ~O_NONBLOCK; 139 fcntl(0, F_SETFL, stat); 140 TermMode = 1; 141} 142 143void 144TtyOldMode() 145{ 146 int stat; 147 148 stat = fcntl(0, F_GETFL, 0); 149 stat &= ~O_NONBLOCK; 150 fcntl(0, F_SETFL, stat); 151 tcsetattr(0, TCSANOW, &oldtio); 152} 153 154void 155Cleanup(excode) 156int excode; 157{ 158 159 OsLinkdown(); 160 OsCloseLink(1); 161 sleep(1); 162 if (mode & (MODE_AUTO | MODE_BACKGROUND)) { 163 DeleteIfRoutes(1); 164 unlink(pid_filename); 165 } 166 OsInterfaceDown(1); 167 if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 168 char c = EX_ERRDEAD; 169 if (write(BGFiledes[1],&c,1) == 1) 170 LogPrintf(LOG_PHASE_BIT,"Parent notified of failure.\n"); 171 else 172 LogPrintf(LOG_PHASE_BIT,"Failed to notify parent of failure.\n"); 173 close(BGFiledes[1]); 174 } 175 LogPrintf(LOG_PHASE_BIT, "PPP Terminated.\n"); 176 LogClose(); 177 if (server >= 0) { 178 close(server); 179 server = -1; 180 } 181 TtyOldMode(); 182 183 exit(excode); 184} 185 186static void 187Hangup(signo) 188int signo; 189{ 190 if (signo == SIGSEGV) { 191 LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo); 192 LogClose(); 193 abort(); 194 } 195 if (BGPid) { 196 kill (BGPid, SIGTERM); 197 exit (EX_HANGUP); 198 } 199 else { 200 LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo); 201 Cleanup(EX_HANGUP); 202 } 203} 204 205static void 206CloseSession(signo) 207int signo; 208{ 209 if (BGPid) { 210 kill (BGPid, SIGINT); 211 exit (EX_TERM); 212 } 213 else { 214 LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo); 215 LcpClose(); 216 Cleanup(EX_TERM); 217 } 218} 219 220static void 221TerminalCont() 222{ 223 pending_signal(SIGCONT, SIG_DFL); 224 pending_signal(SIGTSTP, TerminalStop); 225 TtyCommandMode(getpgrp() == tcgetpgrp(0)); 226} 227 228static void 229TerminalStop(signo) 230int signo; 231{ 232 pending_signal(SIGCONT, TerminalCont); 233 TtyOldMode(); 234 pending_signal(SIGTSTP, SIG_DFL); 235 kill(getpid(), signo); 236} 237 238 239void 240Usage() 241{ 242 fprintf(stderr, 243 "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 244 exit(EX_START); 245} 246 247void 248ProcessArgs(int argc, char **argv) 249{ 250 int optc; 251 char *cp; 252 253 optc = 0; 254 while (argc > 0 && **argv == '-') { 255 cp = *argv + 1; 256 if (strcmp(cp, "auto") == 0) 257 mode |= MODE_AUTO; 258 else if (strcmp(cp, "background") == 0) 259 mode |= MODE_BACKGROUND; 260 else if (strcmp(cp, "direct") == 0) 261 mode |= MODE_DIRECT; 262 else if (strcmp(cp, "dedicated") == 0) 263 mode |= MODE_DEDICATED; 264 else if (strcmp(cp, "ddial") == 0) 265 mode |= MODE_DDIAL|MODE_AUTO; 266 else if (strcmp(cp, "alias") == 0) { 267 mode |= MODE_ALIAS; 268 optc--; /* this option isn't exclusive */ 269 } 270 else 271 Usage(); 272 optc++; 273 argv++; argc--; 274 } 275 if (argc > 1) { 276 fprintf(stderr, "specify only one system label.\n"); 277 exit(EX_START); 278 } 279 if (argc == 1) dstsystem = *argv; 280 281 if (optc > 1) { 282 fprintf(stderr, "specify only one mode.\n"); 283 exit(EX_START); 284 } 285} 286 287static void 288Greetings() 289{ 290 printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 291 fflush(stdout); 292} 293 294void 295main(argc, argv) 296int argc; 297char **argv; 298{ 299 int tunno; 300 301 argc--; argv++; 302 303 mode = MODE_INTER; /* default operation is interactive mode */ 304 netfd = server = modem = tun_in = -1; 305 ProcessArgs(argc, argv); 306 Greetings(); 307 GetUid(); 308 IpcpDefAddress(); 309 InitAlias(); 310 311 if (SelectSystem("default", CONFFILE) < 0) { 312 fprintf(stderr, "Warning: No default entry is given in config file.\n"); 313 } 314 315 if (LogOpen()) 316 exit(EX_START); 317 318 switch ( LocalAuthInit() ) { 319 case NOT_FOUND: 320 fprintf(stderr,LAUTH_M1); 321 fprintf(stderr,LAUTH_M2); 322 fflush (stderr); 323 /* Fall down */ 324 case VALID: 325 VarLocalAuth = LOCAL_AUTH; 326 break; 327 default: 328 break; 329 } 330 331 if (OpenTunnel(&tunno) < 0) { 332 perror("open_tun"); 333 exit(EX_START); 334 } 335 336 if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND)) 337 mode &= ~MODE_INTER; 338 if (mode & MODE_INTER) { 339 printf("Interactive mode\n"); 340 netfd = STDIN_FILENO; 341 } else if (mode & MODE_AUTO) { 342 printf("Automatic Dialer mode\n"); 343 if (dstsystem == NULL) { 344 fprintf(stderr, 345 "Destination system must be specified in auto or ddial mode.\n"); 346 exit(EX_START); 347 } 348 } else if (mode & MODE_BACKGROUND) { 349 printf("Background mode\n"); 350 if (dstsystem == NULL) { 351 fprintf(stderr, "Destination system must be specified in background mode.\n"); 352 exit(EX_START); 353 } 354 } 355 356 tcgetattr(0, &oldtio); /* Save original tty mode */ 357 358 pending_signal(SIGHUP, LogReOpen); 359 pending_signal(SIGTERM, CloseSession); 360 pending_signal(SIGINT, CloseSession); 361 pending_signal(SIGQUIT, CloseSession); 362#ifdef SIGSEGV 363 signal(SIGSEGV, Hangup); 364#endif 365#ifdef SIGPIPE 366 signal(SIGPIPE, SIG_IGN); 367#endif 368#ifdef SIGALRM 369 pending_signal(SIGALRM, SIG_IGN); 370#endif 371 if(mode & MODE_INTER) 372 { 373#ifdef SIGTSTP 374 pending_signal(SIGTSTP, TerminalStop); 375#endif 376#ifdef SIGTTIN 377 pending_signal(SIGTTIN, TerminalStop); 378#endif 379#ifdef SIGTTOU 380 pending_signal(SIGTTOU, SIG_IGN); 381#endif 382 } 383 384 if (dstsystem) { 385 if (SelectSystem(dstsystem, CONFFILE) < 0) { 386 fprintf(stderr, "Destination system not found in conf file.\n"); 387 Cleanup(EX_START); 388 } 389 if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 390 fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n"); 391 Cleanup(EX_START); 392 } 393 } 394 if (mode & MODE_DIRECT) 395 printf("Packet mode enabled.\n"); 396 397#ifdef notdef 398 if (mode & MODE_AUTO) { 399 OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask); 400 } 401#endif 402 403 if (!(mode & MODE_INTER)) { 404 int port = SERVER_PORT + tunno; 405 if (mode & MODE_BACKGROUND) { 406 if (pipe (BGFiledes)) { 407 perror("pipe"); 408 Cleanup(EX_SOCK); 409 } 410 } 411 else { 412 /* 413 * Create server socket and listen at there. 414 */ 415 server = socket(PF_INET, SOCK_STREAM, 0); 416 if (server < 0) { 417 perror("socket"); 418 Cleanup(EX_SOCK); 419 } 420 ifsin.sin_family = AF_INET; 421 ifsin.sin_addr.s_addr = INADDR_ANY; 422 ifsin.sin_port = htons(port); 423 if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) { 424 perror("bind"); 425 if (errno == EADDRINUSE) 426 fprintf(stderr, "Wait for a while, then try again.\n"); 427 Cleanup(EX_SOCK); 428 } 429 listen(server, 5); 430 } 431 432 DupLog(); 433 if (!(mode & MODE_DIRECT)) { 434 int fd; 435 char pid[32]; 436 pid_t bgpid; 437 438 bgpid = fork (); 439 if (bgpid == -1) { 440 perror ("fork"); 441 Cleanup (EX_SOCK); 442 } 443 if (bgpid) { 444 char c = EX_NORMAL; 445 446 if (mode & MODE_BACKGROUND) { 447 /* Wait for our child to close its pipe before we exit. */ 448 BGPid = bgpid; 449 close (BGFiledes[1]); 450 if (read(BGFiledes[0], &c, 1) != 1) 451 LogPrintf (LOG_PHASE_BIT, "Parent: Child exit, no status.\n"); 452 else if (c == EX_NORMAL) 453 LogPrintf (LOG_PHASE_BIT, "Parent: PPP enabled.\n"); 454 else 455 LogPrintf (LOG_PHASE_BIT, "Parent: Child failed %d.\n",(int)c); 456 close (BGFiledes[0]); 457 } 458 exit(c); 459 } else if (mode & MODE_BACKGROUND) 460 close(BGFiledes[0]); 461 462 snprintf(pid_filename, sizeof (pid_filename), "%s/ppp.tun%d.pid", 463 _PATH_VARRUN, tunno); 464 unlink(pid_filename); 465 snprintf(pid, sizeof(pid), "%d\n", (int)getpid()); 466 467 if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1) 468 { 469 write(fd, pid, strlen(pid)); 470 close(fd); 471 } 472 } 473 if (server >= 0) 474 LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port); 475#ifdef DOTTYINIT 476 if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */ 477#else 478 if (mode & MODE_DIRECT) { 479#endif 480 TtyInit(); 481 } else { 482 int fd; 483 484 setsid(); /* detach control tty */ 485 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 486 (void)dup2(fd, STDIN_FILENO); 487 (void)dup2(fd, STDOUT_FILENO); 488 (void)dup2(fd, STDERR_FILENO); 489 if (fd > 2) 490 (void)close (fd); 491 } 492 } 493 } else { 494 TtyInit(); 495 TtyCommandMode(1); 496 } 497 LogPrintf(LOG_PHASE_BIT, "PPP Started.\n"); 498 499 500 do 501 DoLoop(); 502 while (mode & MODE_DEDICATED); 503 504 Cleanup(EX_DONE); 505} 506 507/* 508 * Turn into packet mode, where we speak PPP. 509 */ 510void 511PacketMode() 512{ 513 if (RawModem(modem) < 0) { 514 fprintf(stderr, "Not connected.\r\n"); 515 return; 516 } 517 518 AsyncInit(); 519 VjInit(); 520 LcpInit(); 521 IpcpInit(); 522 CcpInit(); 523 LcpUp(); 524 525 if (mode & (MODE_DIRECT|MODE_DEDICATED)) 526 LcpOpen(OPEN_ACTIVE); 527 else 528 LcpOpen(VarOpenMode); 529 if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 530 TtyCommandMode(1); 531 fprintf(stderr, "Packet mode.\r\n"); 532 aft_cmd = 1; 533 } 534} 535 536static void 537ShowHelp() 538{ 539 fprintf(stderr, "The following commands are available:\r\n"); 540 fprintf(stderr, " ~p\tEnter to Packet mode\r\n"); 541 fprintf(stderr, " ~-\tDecrease log level\r\n"); 542 fprintf(stderr, " ~+\tIncrease log level\r\n"); 543 fprintf(stderr, " ~.\tTerminate program\r\n"); 544 fprintf(stderr, " ~?\tThis help\r\n"); 545} 546 547static void 548ReadTty() 549{ 550 int n; 551 char ch; 552 static int ttystate; 553#define MAXLINESIZE 200 554 char linebuff[MAXLINESIZE]; 555 556#ifdef DEBUG 557 logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode); 558#endif 559 if (!TermMode) { 560 n = read(netfd, linebuff, sizeof(linebuff)-1); 561 aft_cmd = 1; 562 if (n > 0) { 563 DecodeCommand(linebuff, n, 1); 564 } else { 565 LogPrintf(LOG_PHASE_BIT, "client connection closed.\n"); 566 VarLocalAuth = LOCAL_NO_AUTH; 567 close(netfd); 568 close(1); 569 dup2(2, 1); /* Have to have something here or the modem will be 1 */ 570 netfd = -1; 571 mode &= ~MODE_INTER; 572 } 573 return; 574 } 575 576 /* 577 * We are in terminal mode, decode special sequences 578 */ 579 n = read(0, &ch, 1); 580#ifdef DEBUG 581 logprintf("got %d bytes\n", n); 582#endif 583 584 if (n > 0) { 585 switch (ttystate) { 586 case 0: 587 if (ch == '~') 588 ttystate++; 589 else 590 write(modem, &ch, n); 591 break; 592 case 1: 593 switch (ch) { 594 case '?': 595 ShowHelp(); 596 break; 597 case '-': 598 if (loglevel > 0) { 599 loglevel--; 600 fprintf(stderr, "New loglevel is %d\r\n", loglevel); 601 } 602 break; 603 case '+': 604 loglevel++; 605 fprintf(stderr, "New loglevel is %d\r\n", loglevel); 606 break; 607#ifdef DEBUG 608 case 'm': 609 ShowMemMap(); 610 break; 611#endif 612 case 'p': 613 /* 614 * XXX: Should check carrier. 615 */ 616 if (LcpFsm.state <= ST_CLOSED) { 617 VarOpenMode = OPEN_ACTIVE; 618 PacketMode(); 619 } 620 break; 621#ifdef DEBUG 622 case 't': 623 ShowTimers(); 624 break; 625#endif 626 case '.': 627 TermMode = 1; 628 TtyCommandMode(1); 629 break; 630 default: 631 if (write(modem, &ch, n) < 0) 632 fprintf(stderr, "err in write.\r\n"); 633 break; 634 } 635 ttystate = 0; 636 break; 637 } 638 } 639} 640 641 642/* 643 * Here, we'll try to detect HDLC frame 644 */ 645 646static char *FrameHeaders[] = { 647 "\176\377\003\300\041", 648 "\176\377\175\043\300\041", 649 "\176\177\175\043\100\041", 650 "\176\175\337\175\043\300\041", 651 "\176\175\137\175\043\100\041", 652 NULL, 653}; 654 655u_char * 656HdlcDetect(cp, n) 657u_char *cp; 658int n; 659{ 660 char *ptr, *fp, **hp; 661 662 cp[n] = '\0'; /* be sure to null terminated */ 663 ptr = NULL; 664 for (hp = FrameHeaders; *hp; hp++) { 665 fp = *hp; 666 if (DEV_IS_SYNC) 667 fp++; 668 ptr = strstr((char *)cp, fp); 669 if (ptr) 670 break; 671 } 672 return((u_char *)ptr); 673} 674 675static struct pppTimer RedialTimer; 676 677static void 678RedialTimeout() 679{ 680 StopTimer(&RedialTimer); 681 LogPrintf(LOG_PHASE_BIT, "Redialing timer expired.\n"); 682} 683 684static void 685StartRedialTimer() 686{ 687 StopTimer(&RedialTimer); 688 689 if (VarRedialTimeout) { 690 LogPrintf(LOG_PHASE_BIT, "Enter pause for redialing.\n"); 691 RedialTimer.state = TIMER_STOPPED; 692 693 if (VarRedialTimeout > 0) 694 RedialTimer.load = VarRedialTimeout * SECTICKS; 695 else 696 RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 697 698 RedialTimer.func = RedialTimeout; 699 StartTimer(&RedialTimer); 700 } 701} 702 703 704static void 705DoLoop() 706{ 707 fd_set rfds, wfds, efds; 708 int pri, i, n, wfd, nfds; 709 struct sockaddr_in hisaddr; 710 struct timeval timeout, *tp; 711 int ssize = sizeof(hisaddr); 712 u_char *cp; 713 u_char rbuff[MAX_MRU]; 714 int dial_up; 715 int tries; 716 int qlen; 717 pid_t pgroup; 718 719 pgroup = getpgrp(); 720 721 if (mode & (MODE_DIRECT|MODE_BACKGROUND)) { 722 modem = OpenModem(mode); 723 LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n"); 724 fflush(stderr); 725 PacketMode(); 726 } else if (mode & MODE_DEDICATED) { 727 if (modem < 0) 728 modem = OpenModem(mode); 729 } 730 731 fflush(stdout); 732 733 timeout.tv_sec = 0; 734 timeout.tv_usec = 0; 735 736 if (mode & MODE_BACKGROUND) 737 dial_up = TRUE; /* Bring the line up */ 738 else 739 dial_up = FALSE; /* XXXX */ 740 tries = 0; 741 for (;;) { 742 nfds = 0; 743 FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 744 745 /* 746 * If the link is down and we're in DDIAL mode, bring it back 747 * up. 748 */ 749 if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 750 dial_up = TRUE; 751 752 /* 753 * If Ip packet for output is enqueued and require dial up, 754 * Just do it! 755 */ 756 if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ 757#ifdef DEBUG 758 logprintf("going to dial: modem = %d\n", modem); 759#endif 760 modem = OpenModem(mode); 761 if (modem < 0) { 762 StartRedialTimer(); 763 } else { 764 tries++; /* Tries are per number, not per list of numbers. */ 765 if (VarDialTries) 766 LogPrintf(LOG_CHAT_BIT, "Dial attempt %u of %d\n", tries, 767 VarDialTries); 768 else 769 LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries); 770 if (DialModem()) { 771 sleep(1); /* little pause to allow peer starts */ 772 ModemTimeout(); 773 PacketMode(); 774 dial_up = FALSE; 775 tries = 0; 776 } else { 777 CloseModem(); 778 if (VarDialTries && tries >= VarDialTries) { 779 /* I give up ! Can't get through :( */ 780 StartRedialTimer(); 781 dial_up = FALSE; 782 tries = 0; 783 } else if (VarNextPhone == NULL) 784 /* Dial failed. Keep quite during redial wait period. */ 785 StartRedialTimer(); 786 else 787 /* 788 * Give the modem a chance to recover, then dial the next 789 * number in our list 790 */ 791 sleep(1); 792 } 793 } 794 } 795 qlen = ModemQlen(); 796 797 if (qlen == 0) { 798 IpStartOutput(); 799 qlen = ModemQlen(); 800 } 801 802 if (modem >= 0) { 803 if (modem + 1 > nfds) 804 nfds = modem + 1; 805 FD_SET(modem, &rfds); 806 FD_SET(modem, &efds); 807 if (qlen > 0) { 808 FD_SET(modem, &wfds); 809 } 810 } 811 if (server >= 0) { 812 if (server + 1 > nfds) 813 nfds = server + 1; 814 FD_SET(server, &rfds); 815 } 816 817 /* *** IMPORTANT *** 818 * 819 * CPU is serviced every TICKUNIT micro seconds. 820 * This value must be chosen with great care. If this values is 821 * too big, it results loss of characters from modem and poor responce. 822 * If this values is too small, ppp process eats many CPU time. 823 */ 824#ifndef SIGALRM 825 usleep(TICKUNIT); 826 TimerService(); 827#else 828 handle_signals(); 829#endif 830 831 /* If there are aren't many packets queued, look for some more. */ 832 if (qlen < 20 && tun_in >= 0) { 833 if (tun_in + 1 > nfds) 834 nfds = tun_in + 1; 835 FD_SET(tun_in, &rfds); 836 } 837 838 if (netfd >= 0) { 839 if (netfd + 1 > nfds) 840 nfds = netfd + 1; 841 FD_SET(netfd, &rfds); 842 FD_SET(netfd, &efds); 843 } 844 845#ifndef SIGALRM 846 /* 847 * Normally, select() will not block because modem is writable. 848 * In AUTO mode, select will block until we find packet from tun 849 */ 850 tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 851 i = select(nfds, &rfds, &wfds, &efds, tp); 852#else 853 /* 854 * When SIGALRM timer is running, a select function will be 855 * return -1 and EINTR after a Time Service signal hundler 856 * is done. If the redial timer is not running and we are 857 * trying to dial, poll with a 0 value timer. 858 */ 859 tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 860 i = select(nfds, &rfds, &wfds, &efds, tp); 861#endif 862 863 if ( i == 0 ) { 864 continue; 865 } 866 867 if ( i < 0 ) { 868 if ( errno == EINTR ) { 869 handle_signals(); 870 continue; 871 } 872 perror("select"); 873 break; 874 } 875 876 if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 877 logprintf("Exception detected.\n"); 878 break; 879 } 880 881 if (server >= 0 && FD_ISSET(server, &rfds)) { 882 LogPrintf(LOG_PHASE_BIT, "connected to client.\n"); 883 wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 884 if (wfd < 0) { 885 perror("accept"); 886 continue; 887 } 888 if (netfd >= 0) { 889 write(wfd, "already in use.\n", 16); 890 close(wfd); 891 continue; 892 } else 893 netfd = wfd; 894 if (dup2(netfd, 1) < 0) { 895 perror("dup2"); 896 close(netfd); 897 netfd = -1; 898 continue; 899 } 900 mode |= MODE_INTER; 901 Greetings(); 902 switch ( LocalAuthInit() ) { 903 case NOT_FOUND: 904 fprintf(stdout,LAUTH_M1); 905 fprintf(stdout,LAUTH_M2); 906 fflush(stdout); 907 /* Fall down */ 908 case VALID: 909 VarLocalAuth = LOCAL_AUTH; 910 break; 911 default: 912 break; 913 } 914 (void) IsInteractive(); 915 Prompt(0); 916 } 917 918 if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 919 ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 920 /* something to read from tty */ 921 ReadTty(); 922 } 923 if (modem >= 0) { 924 if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 925 ModemStartOutput(modem); 926 } 927 if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 928 if (LcpFsm.state <= ST_CLOSED) 929 usleep(10000); 930 n = read(modem, rbuff, sizeof(rbuff)); 931 if ((mode & MODE_DIRECT) && n <= 0) { 932 DownConnection(); 933 } else 934 LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 935 936 if (LcpFsm.state <= ST_CLOSED) { 937 /* 938 * In dedicated mode, we just discard input until LCP is started. 939 */ 940 if (!(mode & MODE_DEDICATED)) { 941 cp = HdlcDetect(rbuff, n); 942 if (cp) { 943 /* 944 * LCP packet is detected. Turn ourselves into packet mode. 945 */ 946 if (cp != rbuff) { 947 write(1, rbuff, cp - rbuff); 948 write(1, "\r\n", 2); 949 } 950 PacketMode(); 951#ifdef notdef 952 AsyncInput(cp, n - (cp - rbuff)); 953#endif 954 } else 955 write(1, rbuff, n); 956 } 957 } else { 958 if (n > 0) 959 AsyncInput(rbuff, n); 960#ifdef notdef 961 continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 962#endif 963 } 964 } 965 } 966 967 if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 968 n = read(tun_in, rbuff, sizeof(rbuff)); 969 if (n < 0) { 970 perror("read from tun"); 971 continue; 972 } 973 /* 974 * Process on-demand dialup. Output packets are queued within tunnel 975 * device until IPCP is opened. 976 */ 977 if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 978 pri = PacketCheck(rbuff, n, FL_DIAL); 979 if (pri >= 0) { 980 if (mode & MODE_ALIAS) { 981 PacketAliasOut((struct ip *)rbuff); 982 n = ntohs(((struct ip *)rbuff)->ip_len); 983 } 984 IpEnqueue(pri, rbuff, n); 985 dial_up = TRUE; /* XXX */ 986 } 987 continue; 988 } 989 pri = PacketCheck(rbuff, n, FL_OUT); 990 if (pri >= 0) { 991 if (mode & MODE_ALIAS) { 992 PacketAliasOut((struct ip *)rbuff); 993 n = ntohs(((struct ip *)rbuff)->ip_len); 994 } 995 IpEnqueue(pri, rbuff, n); 996 } 997 } 998 } 999 logprintf("job done.\n"); 1000} 1001