1 /* 2 * User Process PPP 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan, Inc. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $Id: main.c,v 1.68 1997/06/29 13:54:31 brian Exp $ 21 * 22 * TODO: 23 * o Add commands for traffic summary, version display, etc. 24 * o Add signal handler for misc controls. 25 */ 26 #include "fsm.h" 27 #include <fcntl.h> 28 #include <paths.h> 29 #include <sys/time.h> 30 #include <termios.h> 31 #include <signal.h> 32 #include <sys/wait.h> 33 #include <errno.h> 34 #include <netdb.h> 35 #include <unistd.h> 36 #include <sys/socket.h> 37 #include <arpa/inet.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/ip.h> 40 #include "modem.h" 41 #include "os.h" 42 #include "hdlc.h" 43 #include "ccp.h" 44 #include "lcp.h" 45 #include "ipcp.h" 46 #include "loadalias.h" 47 #include "vars.h" 48 #include "auth.h" 49 #include "filter.h" 50 #include "systems.h" 51 #include "ip.h" 52 #include "sig.h" 53 #include "server.h" 54 55 #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n" 56 #define LAUTH_M2 "Warning: Manipulation is allowed by anyone\n" 57 58 #ifndef O_NONBLOCK 59 #ifdef O_NDELAY 60 #define O_NONBLOCK O_NDELAY 61 #endif 62 #endif 63 64 extern void VjInit(), AsyncInit(); 65 extern void AsyncInput(); 66 extern int SelectSystem(); 67 68 extern void DecodeCommand(), Prompt(); 69 extern int aft_cmd; 70 extern int IsInteractive(); 71 static void DoLoop(void); 72 static void TerminalStop(); 73 static char *ex_desc(); 74 75 static struct termios oldtio; /* Original tty mode */ 76 static struct termios comtio; /* Command level tty mode */ 77 int TermMode; 78 static pid_t BGPid = 0; 79 static char pid_filename[MAXPATHLEN]; 80 static char if_filename[MAXPATHLEN]; 81 int tunno; 82 static int dial_up; 83 84 static void 85 TtyInit(int DontWantInt) 86 { 87 struct termios newtio; 88 int stat; 89 90 stat = fcntl(0, F_GETFL, 0); 91 if (stat > 0) { 92 stat |= O_NONBLOCK; 93 (void)fcntl(0, F_SETFL, stat); 94 } 95 newtio = oldtio; 96 newtio.c_lflag &= ~(ECHO|ISIG|ICANON); 97 newtio.c_iflag = 0; 98 newtio.c_oflag &= ~OPOST; 99 newtio.c_cc[VEOF] = _POSIX_VDISABLE; 100 if (DontWantInt) 101 newtio.c_cc[VINTR] = _POSIX_VDISABLE; 102 newtio.c_cc[VMIN] = 1; 103 newtio.c_cc[VTIME] = 0; 104 newtio.c_cflag |= CS8; 105 tcsetattr(0, TCSADRAIN, &newtio); 106 comtio = newtio; 107 } 108 109 /* 110 * Set tty into command mode. We allow canonical input and echo processing. 111 */ 112 void 113 TtyCommandMode(prompt) 114 int prompt; 115 { 116 struct termios newtio; 117 int stat; 118 119 if (!(mode & MODE_INTER)) 120 return; 121 tcgetattr(0, &newtio); 122 newtio.c_lflag |= (ECHO|ISIG|ICANON); 123 newtio.c_iflag = oldtio.c_iflag; 124 newtio.c_oflag |= OPOST; 125 tcsetattr(0, TCSADRAIN, &newtio); 126 stat = fcntl(0, F_GETFL, 0); 127 if (stat > 0) { 128 stat |= O_NONBLOCK; 129 (void)fcntl(0, F_SETFL, stat); 130 } 131 TermMode = 0; 132 if(prompt) Prompt(); 133 } 134 135 /* 136 * Set tty into terminal mode which is used while we invoke term command. 137 */ 138 void 139 TtyTermMode() 140 { 141 int stat; 142 143 tcsetattr(0, TCSADRAIN, &comtio); 144 stat = fcntl(0, F_GETFL, 0); 145 if (stat > 0) { 146 stat &= ~O_NONBLOCK; 147 (void)fcntl(0, F_SETFL, stat); 148 } 149 TermMode = 1; 150 } 151 152 void 153 TtyOldMode() 154 { 155 int stat; 156 157 stat = fcntl(0, F_GETFL, 0); 158 if (stat > 0) { 159 stat &= ~O_NONBLOCK; 160 (void)fcntl(0, F_SETFL, stat); 161 } 162 tcsetattr(0, TCSANOW, &oldtio); 163 } 164 165 void 166 Cleanup(excode) 167 int excode; 168 { 169 170 OsLinkdown(); 171 OsCloseLink(1); 172 sleep(1); 173 if (mode & MODE_AUTO) 174 DeleteIfRoutes(1); 175 (void)unlink(pid_filename); 176 (void)unlink(if_filename); 177 OsInterfaceDown(1); 178 if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) { 179 char c = EX_ERRDEAD; 180 if (write(BGFiledes[1],&c,1) == 1) 181 LogPrintf(LogPHASE,"Parent notified of failure.\n"); 182 else 183 LogPrintf(LogPHASE,"Failed to notify parent of failure.\n"); 184 close(BGFiledes[1]); 185 } 186 LogPrintf(LogPHASE, "PPP Terminated (%s).\n",ex_desc(excode)); 187 LogClose(); 188 ServerClose(); 189 TtyOldMode(); 190 191 exit(excode); 192 } 193 194 static void 195 CloseConnection(signo) 196 int signo; 197 { 198 /* NOTE, these are manual, we've done a setsid() */ 199 LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo); 200 reconnectState = RECON_FALSE; \ 201 reconnectCount = 0; \ 202 DownConnection(); 203 dial_up = FALSE; 204 } 205 206 static void 207 CloseSession(signo) 208 int signo; 209 { 210 if (BGPid) { 211 kill (BGPid, SIGINT); 212 exit (EX_TERM); 213 } 214 LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo); 215 reconnect(RECON_FALSE); 216 LcpClose(); 217 Cleanup(EX_TERM); 218 } 219 220 static void 221 TerminalCont() 222 { 223 pending_signal(SIGCONT, SIG_DFL); 224 pending_signal(SIGTSTP, TerminalStop); 225 TtyCommandMode(getpgrp() == tcgetpgrp(0)); 226 } 227 228 static void 229 TerminalStop(signo) 230 int signo; 231 { 232 pending_signal(SIGCONT, TerminalCont); 233 TtyOldMode(); 234 pending_signal(SIGTSTP, SIG_DFL); 235 kill(getpid(), signo); 236 } 237 238 static void 239 SetUpServer(signo) 240 int signo; 241 { 242 int res; 243 if ((res = ServerTcpOpen(SERVER_PORT+tunno)) != 0) 244 LogPrintf(LogERROR, "Failed %d to open port %d\n", res, SERVER_PORT+tunno); 245 } 246 247 static char * 248 ex_desc(int ex) 249 { 250 static char num[12]; 251 static char *desc[] = { "normal", "start", "sock", 252 "modem", "dial", "dead", "done", "reboot", "errdead", 253 "hangup", "term", "nodial", "nologin" }; 254 255 if (ex >= 0 && ex < sizeof(desc)/sizeof(*desc)) 256 return desc[ex]; 257 snprintf(num, sizeof num, "%d", ex); 258 return num; 259 } 260 261 void 262 Usage() 263 { 264 fprintf(stderr, 265 "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n"); 266 exit(EX_START); 267 } 268 269 void 270 ProcessArgs(int argc, char **argv) 271 { 272 int optc; 273 char *cp; 274 275 optc = 0; 276 while (argc > 0 && **argv == '-') { 277 cp = *argv + 1; 278 if (strcmp(cp, "auto") == 0) 279 mode |= MODE_AUTO; 280 else if (strcmp(cp, "background") == 0) 281 mode |= MODE_BACKGROUND|MODE_AUTO; 282 else if (strcmp(cp, "direct") == 0) 283 mode |= MODE_DIRECT; 284 else if (strcmp(cp, "dedicated") == 0) 285 mode |= MODE_DEDICATED; 286 else if (strcmp(cp, "ddial") == 0) 287 mode |= MODE_DDIAL|MODE_AUTO; 288 else if (strcmp(cp, "alias") == 0) { 289 if (loadAliasHandlers(&VarAliasHandlers) == 0) 290 mode |= MODE_ALIAS; 291 else 292 LogPrintf(LogWARN, "Cannot load alias library\n"); 293 optc--; /* this option isn't exclusive */ 294 } 295 else 296 Usage(); 297 optc++; 298 argv++; argc--; 299 } 300 if (argc > 1) { 301 fprintf(stderr, "specify only one system label.\n"); 302 exit(EX_START); 303 } 304 if (argc == 1) dstsystem = *argv; 305 306 if (optc > 1) { 307 fprintf(stderr, "specify only one mode.\n"); 308 exit(EX_START); 309 } 310 } 311 312 static void 313 Greetings() 314 { 315 if (VarTerm) { 316 fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n"); 317 fflush(VarTerm); 318 } 319 } 320 321 int 322 main(argc, argv) 323 int argc; 324 char **argv; 325 { 326 FILE *lockfile; 327 char *name; 328 329 VarTerm = 0; 330 name = rindex(argv[0], '/'); 331 LogOpen(name ? name+1 : argv[0]); 332 333 argc--; argv++; 334 mode = MODE_INTER; /* default operation is interactive mode */ 335 netfd = modem = tun_in = -1; 336 server = -2; 337 ProcessArgs(argc, argv); 338 if (!(mode & MODE_DIRECT)) 339 VarTerm = stdout; 340 Greetings(); 341 GetUid(); 342 IpcpDefAddress(); 343 344 if (SelectSystem("default", CONFFILE) < 0 && VarTerm) 345 fprintf(VarTerm, "Warning: No default entry is given in config file.\n"); 346 347 if (OpenTunnel(&tunno) < 0) { 348 LogPrintf(LogWARN, "open_tun: %s\n", strerror(errno)); 349 return EX_START; 350 } 351 352 if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED)) 353 mode &= ~MODE_INTER; 354 if (mode & MODE_INTER) { 355 fprintf(VarTerm, "Interactive mode\n"); 356 netfd = STDOUT_FILENO; 357 } else if (mode & MODE_AUTO) { 358 fprintf(VarTerm, "Automatic Dialer mode\n"); 359 if (dstsystem == NULL) { 360 if (VarTerm) 361 fprintf(VarTerm, "Destination system must be specified in" 362 " auto, background or ddial mode.\n"); 363 return EX_START; 364 } 365 } 366 367 tcgetattr(0, &oldtio); /* Save original tty mode */ 368 369 pending_signal(SIGHUP, CloseSession); 370 pending_signal(SIGTERM, CloseSession); 371 pending_signal(SIGINT, CloseConnection); 372 pending_signal(SIGQUIT, CloseSession); 373 #ifdef SIGPIPE 374 signal(SIGPIPE, SIG_IGN); 375 #endif 376 #ifdef SIGALRM 377 pending_signal(SIGALRM, SIG_IGN); 378 #endif 379 if(mode & MODE_INTER) { 380 #ifdef SIGTSTP 381 pending_signal(SIGTSTP, TerminalStop); 382 #endif 383 #ifdef SIGTTIN 384 pending_signal(SIGTTIN, TerminalStop); 385 #endif 386 #ifdef SIGTTOU 387 pending_signal(SIGTTOU, SIG_IGN); 388 #endif 389 } 390 #ifdef SIGUSR1 391 if (mode != MODE_INTER) 392 pending_signal(SIGUSR1, SetUpServer); 393 #endif 394 395 if (dstsystem) { 396 if (SelectSystem(dstsystem, CONFFILE) < 0) { 397 LogPrintf(LogWARN, "Destination system not found in conf file.\n"); 398 Cleanup(EX_START); 399 } 400 if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) { 401 LogPrintf(LogWARN, "Must specify dstaddr with" 402 " auto, background or ddial mode.\n"); 403 Cleanup(EX_START); 404 } 405 } 406 407 if (ServerType() != NO_SERVER) 408 switch ( LocalAuthInit() ) { 409 case NOT_FOUND: 410 if (VarTerm) { 411 fprintf(VarTerm,LAUTH_M1); 412 fprintf(VarTerm,LAUTH_M2); 413 fflush(VarTerm); 414 } 415 /* Fall down */ 416 case VALID: 417 VarLocalAuth = LOCAL_AUTH; 418 break; 419 default: 420 break; 421 } 422 423 if (!(mode & MODE_INTER)) { 424 if (mode & MODE_BACKGROUND) { 425 if (pipe (BGFiledes)) { 426 LogPrintf(LogERROR, "pipe: %s", strerror(errno)); 427 Cleanup(EX_SOCK); 428 } 429 } 430 431 /* Create server socket and listen. */ 432 if (server == -2 && ServerTcpOpen(SERVER_PORT + tunno) != 0) 433 Cleanup(EX_SOCK); 434 435 if (!(mode & MODE_DIRECT)) { 436 pid_t bgpid; 437 438 bgpid = fork (); 439 if (bgpid == -1) { 440 LogPrintf(LogERROR, "fork: %s", strerror(errno)); 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 fprintf(VarTerm, "Child exit, no status.\n"); 452 LogPrintf (LogPHASE, "Parent: Child exit, no status.\n"); 453 } else if (c == EX_NORMAL) { 454 fprintf(VarTerm, "PPP enabled.\n"); 455 LogPrintf (LogPHASE, "Parent: PPP enabled.\n"); 456 } else { 457 fprintf(VarTerm, "Child failed (%s).\n",ex_desc((int)c)); 458 LogPrintf(LogPHASE, "Parent: Child failed (%s).\n", 459 ex_desc((int)c)); 460 } 461 close(BGFiledes[0]); 462 } 463 return c; 464 } else if (mode & MODE_BACKGROUND) 465 close(BGFiledes[0]); 466 } 467 468 snprintf(pid_filename, sizeof (pid_filename), "%stun%d.pid", 469 _PATH_VARRUN, tunno); 470 (void)unlink(pid_filename); 471 472 if ((lockfile = fopen(pid_filename, "w")) != NULL) { 473 fprintf(lockfile, "%d\n", (int)getpid()); 474 fclose(lockfile); 475 } else 476 LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 477 pid_filename, strerror(errno)); 478 479 snprintf(if_filename, sizeof if_filename, "%s%s.if", 480 _PATH_VARRUN, VarBaseDevice); 481 (void)unlink(if_filename); 482 483 if ((lockfile = fopen(if_filename, "w")) != NULL) { 484 fprintf(lockfile, "tun%d\n", tunno); 485 fclose(lockfile); 486 } else 487 LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", 488 if_filename, strerror(errno)); 489 490 VarTerm = 0; /* We know it's currently stdout */ 491 close(0); 492 close(2); 493 494 #ifdef DOTTYINIT 495 if (mode & (MODE_DIRECT|MODE_DEDICATED)) 496 #else 497 if (mode & MODE_DIRECT) 498 #endif 499 TtyInit(1); 500 else { 501 setsid(); 502 close(1); 503 } 504 } else { 505 TtyInit(0); 506 TtyCommandMode(1); 507 } 508 LogPrintf(LogPHASE, "PPP Started.\n"); 509 510 511 do 512 DoLoop(); 513 while (mode & MODE_DEDICATED); 514 515 Cleanup(EX_DONE); 516 return 0; 517 } 518 519 /* 520 * Turn into packet mode, where we speak PPP. 521 */ 522 void 523 PacketMode() 524 { 525 if (RawModem(modem) < 0) { 526 LogPrintf(LogWARN, "PacketMode: Not connected.\n"); 527 return; 528 } 529 530 AsyncInit(); 531 VjInit(); 532 LcpInit(); 533 IpcpInit(); 534 CcpInit(); 535 LcpUp(); 536 537 LcpOpen(VarOpenMode); 538 if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) { 539 TtyCommandMode(1); 540 if (VarTerm) { 541 fprintf(VarTerm, "Packet mode.\n"); 542 aft_cmd = 1; 543 } 544 } 545 } 546 547 static void 548 ShowHelp() 549 { 550 fprintf(stderr, "The following commands are available:\r\n"); 551 fprintf(stderr, " ~p\tEnter Packet mode\r\n"); 552 fprintf(stderr, " ~-\tDecrease log level\r\n"); 553 fprintf(stderr, " ~+\tIncrease log level\r\n"); 554 fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n"); 555 fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n"); 556 fprintf(stderr, " ~.\tTerminate program\r\n"); 557 fprintf(stderr, " ~?\tThis help\r\n"); 558 } 559 560 static void 561 ReadTty() 562 { 563 int n; 564 char ch; 565 static int ttystate; 566 FILE *oVarTerm; 567 #define MAXLINESIZE 200 568 char linebuff[MAXLINESIZE]; 569 570 LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n", 571 TermMode, netfd, mode); 572 if (!TermMode) { 573 n = read(netfd, linebuff, sizeof(linebuff)-1); 574 if (n > 0) { 575 aft_cmd = 1; 576 DecodeCommand(linebuff, n, 1); 577 } else { 578 LogPrintf(LogPHASE, "client connection closed.\n"); 579 VarLocalAuth = LOCAL_NO_AUTH; 580 mode &= ~MODE_INTER; 581 oVarTerm = VarTerm; 582 VarTerm = 0; 583 if (oVarTerm && oVarTerm != stdout) 584 fclose(oVarTerm); 585 close(netfd); 586 netfd = -1; 587 } 588 return; 589 } 590 591 /* 592 * We are in terminal mode, decode special sequences 593 */ 594 n = read(fileno(VarTerm), &ch, 1); 595 LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)", n); 596 597 if (n > 0) { 598 switch (ttystate) { 599 case 0: 600 if (ch == '~') 601 ttystate++; 602 else 603 write(modem, &ch, n); 604 break; 605 case 1: 606 switch (ch) { 607 case '?': 608 ShowHelp(); 609 break; 610 case 'p': 611 /* 612 * XXX: Should check carrier. 613 */ 614 if (LcpFsm.state <= ST_CLOSED) { 615 VarOpenMode = OPEN_ACTIVE; 616 PacketMode(); 617 } 618 break; 619 case '.': 620 TermMode = 1; 621 aft_cmd = 1; 622 TtyCommandMode(1); 623 break; 624 case 't': 625 if (LogIsKept(LogDEBUG)) { 626 ShowTimers(); 627 break; 628 } 629 case 'm': 630 if (LogIsKept(LogDEBUG)) { 631 ShowMemMap(); 632 break; 633 } 634 default: 635 if (write(modem, &ch, n) < 0) 636 LogPrintf(LogERROR, "error writing to modem.\n"); 637 break; 638 } 639 ttystate = 0; 640 break; 641 } 642 } 643 } 644 645 646 /* 647 * Here, we'll try to detect HDLC frame 648 */ 649 650 static char *FrameHeaders[] = { 651 "\176\377\003\300\041", 652 "\176\377\175\043\300\041", 653 "\176\177\175\043\100\041", 654 "\176\175\337\175\043\300\041", 655 "\176\175\137\175\043\100\041", 656 NULL, 657 }; 658 659 u_char * 660 HdlcDetect(cp, n) 661 u_char *cp; 662 int n; 663 { 664 char *ptr, *fp, **hp; 665 666 cp[n] = '\0'; /* be sure to null terminated */ 667 ptr = NULL; 668 for (hp = FrameHeaders; *hp; hp++) { 669 fp = *hp; 670 if (DEV_IS_SYNC) 671 fp++; 672 ptr = strstr((char *)cp, fp); 673 if (ptr) 674 break; 675 } 676 return((u_char *)ptr); 677 } 678 679 static struct pppTimer RedialTimer; 680 681 static void 682 RedialTimeout() 683 { 684 StopTimer(&RedialTimer); 685 LogPrintf(LogPHASE, "Redialing timer expired.\n"); 686 } 687 688 static void 689 StartRedialTimer(Timeout) 690 int Timeout; 691 { 692 StopTimer(&RedialTimer); 693 694 if (Timeout) { 695 RedialTimer.state = TIMER_STOPPED; 696 697 if (Timeout > 0) 698 RedialTimer.load = Timeout * SECTICKS; 699 else 700 RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS; 701 702 LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n", 703 RedialTimer.load / SECTICKS); 704 705 RedialTimer.func = RedialTimeout; 706 StartTimer(&RedialTimer); 707 } 708 } 709 710 711 static void 712 DoLoop() 713 { 714 fd_set rfds, wfds, efds; 715 int pri, i, n, wfd, nfds; 716 struct sockaddr_in hisaddr; 717 struct timeval timeout, *tp; 718 int ssize = sizeof(hisaddr); 719 u_char *cp; 720 u_char rbuff[MAX_MRU]; 721 int tries; 722 int qlen; 723 int res; 724 pid_t pgroup; 725 726 pgroup = getpgrp(); 727 728 if (mode & MODE_DIRECT) { 729 LogPrintf(LogDEBUG, "Opening modem\n"); 730 modem = OpenModem(mode); 731 LogPrintf(LogPHASE, "Packet mode enabled\n"); 732 PacketMode(); 733 } else if (mode & MODE_DEDICATED) { 734 if (modem < 0) 735 modem = OpenModem(mode); 736 } 737 738 fflush(VarTerm); 739 740 timeout.tv_sec = 0; 741 timeout.tv_usec = 0; 742 reconnectState = RECON_UNKNOWN; 743 744 if (mode & MODE_BACKGROUND) 745 dial_up = TRUE; /* Bring the line up */ 746 else 747 dial_up = FALSE; /* XXXX */ 748 tries = 0; 749 for (;;) { 750 nfds = 0; 751 FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 752 753 /* 754 * If the link is down and we're in DDIAL mode, bring it back 755 * up. 756 */ 757 if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED) 758 dial_up = TRUE; 759 760 /* 761 * If we lost carrier and want to re-establish the connection 762 * due to the "set reconnect" value, we'd better bring the line 763 * back up. 764 */ 765 if (LcpFsm.state <= ST_CLOSED) { 766 if (dial_up != TRUE && reconnectState == RECON_TRUE) { 767 if (++reconnectCount <= VarReconnectTries) { 768 LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n", 769 reconnectCount, VarReconnectTries); 770 StartRedialTimer(VarReconnectTimer); 771 dial_up = TRUE; 772 } else { 773 if (VarReconnectTries) 774 LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n", 775 VarReconnectTries); 776 reconnectCount = 0; 777 if (mode & MODE_BACKGROUND) 778 Cleanup(EX_DEAD); 779 } 780 reconnectState = RECON_ENVOKED; 781 } 782 } 783 784 /* 785 * If Ip packet for output is enqueued and require dial up, 786 * Just do it! 787 */ 788 if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { 789 LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem); 790 modem = OpenModem(mode); 791 if (modem < 0) { 792 tries++; 793 if (!(mode & MODE_DDIAL) && VarDialTries) 794 LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n", 795 tries, VarDialTries); 796 else 797 LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries); 798 799 if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) { 800 if (mode & MODE_BACKGROUND) 801 Cleanup(EX_DIAL); /* Can't get the modem */ 802 dial_up = FALSE; 803 reconnectState = RECON_UNKNOWN; 804 reconnectCount = 0; 805 tries = 0; 806 } else 807 StartRedialTimer(VarRedialTimeout); 808 } else { 809 tries++; /* Tries are per number, not per list of numbers. */ 810 if (!(mode & MODE_DDIAL) && VarDialTries) 811 LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries); 812 else 813 LogPrintf(LogCHAT, "Dial attempt %u\n", tries); 814 815 if ((res = DialModem()) == EX_DONE) { 816 sleep(1); /* little pause to allow peer starts */ 817 ModemTimeout(); 818 PacketMode(); 819 dial_up = FALSE; 820 reconnectState = RECON_UNKNOWN; 821 tries = 0; 822 } else { 823 CloseModem(); 824 if (mode & MODE_BACKGROUND) { 825 if (VarNextPhone == NULL || res == EX_SIG) 826 Cleanup(EX_DIAL); /* Tried all numbers - no luck */ 827 else 828 /* Try all numbers in background mode */ 829 StartRedialTimer(VarRedialNextTimeout); 830 } else if (!(mode & MODE_DDIAL) && 831 ((VarDialTries && tries >= VarDialTries) || 832 res == EX_SIG)) { 833 /* I give up ! Can't get through :( */ 834 StartRedialTimer(VarRedialTimeout); 835 dial_up = FALSE; 836 reconnectState = RECON_UNKNOWN; 837 reconnectCount = 0; 838 tries = 0; 839 } else if (VarNextPhone == NULL) 840 /* Dial failed. Keep quite during redial wait period. */ 841 StartRedialTimer(VarRedialTimeout); 842 else 843 StartRedialTimer(VarRedialNextTimeout); 844 } 845 } 846 } 847 qlen = ModemQlen(); 848 849 if (qlen == 0) { 850 IpStartOutput(); 851 qlen = ModemQlen(); 852 } 853 854 if (modem >= 0) { 855 if (modem + 1 > nfds) 856 nfds = modem + 1; 857 FD_SET(modem, &rfds); 858 FD_SET(modem, &efds); 859 if (qlen > 0) { 860 FD_SET(modem, &wfds); 861 } 862 } 863 if (server >= 0) { 864 if (server + 1 > nfds) 865 nfds = server + 1; 866 FD_SET(server, &rfds); 867 } 868 869 /* *** IMPORTANT *** 870 * 871 * CPU is serviced every TICKUNIT micro seconds. 872 * This value must be chosen with great care. If this values is 873 * too big, it results loss of characters from modem and poor responce. 874 * If this values is too small, ppp process eats many CPU time. 875 */ 876 #ifndef SIGALRM 877 usleep(TICKUNIT); 878 TimerService(); 879 #else 880 handle_signals(); 881 #endif 882 883 /* If there are aren't many packets queued, look for some more. */ 884 if (qlen < 20 && tun_in >= 0) { 885 if (tun_in + 1 > nfds) 886 nfds = tun_in + 1; 887 FD_SET(tun_in, &rfds); 888 } 889 890 if (netfd >= 0) { 891 if (netfd + 1 > nfds) 892 nfds = netfd + 1; 893 FD_SET(netfd, &rfds); 894 FD_SET(netfd, &efds); 895 } 896 897 #ifndef SIGALRM 898 /* 899 * Normally, select() will not block because modem is writable. 900 * In AUTO mode, select will block until we find packet from tun 901 */ 902 tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 903 i = select(nfds, &rfds, &wfds, &efds, tp); 904 #else 905 /* 906 * When SIGALRM timer is running, a select function will be 907 * return -1 and EINTR after a Time Service signal hundler 908 * is done. If the redial timer is not running and we are 909 * trying to dial, poll with a 0 value timer. 910 */ 911 tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 912 i = select(nfds, &rfds, &wfds, &efds, tp); 913 #endif 914 915 if ( i == 0 ) { 916 continue; 917 } 918 919 if ( i < 0 ) { 920 if ( errno == EINTR ) { 921 handle_signals(); 922 continue; 923 } 924 LogPrintf(LogERROR, "select: %s", strerror(errno)); 925 break; 926 } 927 928 if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) { 929 LogPrintf(LogALERT, "Exception detected.\n"); 930 break; 931 } 932 933 if (server >= 0 && FD_ISSET(server, &rfds)) { 934 LogPrintf(LogPHASE, "connected to client.\n"); 935 wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 936 if (wfd < 0) { 937 LogPrintf(LogERROR, "accept: %s", strerror(errno)); 938 continue; 939 } 940 if (netfd >= 0) { 941 write(wfd, "already in use.\n", 16); 942 close(wfd); 943 continue; 944 } else 945 netfd = wfd; 946 VarTerm = fdopen(netfd, "a+"); 947 mode |= MODE_INTER; 948 Greetings(); 949 switch ( LocalAuthInit() ) { 950 case NOT_FOUND: 951 if (VarTerm) { 952 fprintf(VarTerm,LAUTH_M1); 953 fprintf(VarTerm,LAUTH_M2); 954 fflush(VarTerm); 955 } 956 /* Fall down */ 957 case VALID: 958 VarLocalAuth = LOCAL_AUTH; 959 break; 960 default: 961 break; 962 } 963 (void) IsInteractive(); 964 Prompt(); 965 } 966 967 if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) && 968 ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 969 /* something to read from tty */ 970 ReadTty(); 971 } 972 if (modem >= 0) { 973 if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 974 ModemStartOutput(modem); 975 } 976 if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 977 if (LcpFsm.state <= ST_CLOSED) 978 usleep(10000); 979 n = read(modem, rbuff, sizeof(rbuff)); 980 if ((mode & MODE_DIRECT) && n <= 0) { 981 DownConnection(); 982 } else 983 LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n); 984 985 if (LcpFsm.state <= ST_CLOSED) { 986 /* 987 * In dedicated mode, we just discard input until LCP is started. 988 */ 989 if (!(mode & MODE_DEDICATED)) { 990 cp = HdlcDetect(rbuff, n); 991 if (cp) { 992 /* 993 * LCP packet is detected. Turn ourselves into packet mode. 994 */ 995 if (cp != rbuff) { 996 write(modem, rbuff, cp - rbuff); 997 write(modem, "\r\n", 2); 998 } 999 PacketMode(); 1000 } else 1001 write(fileno(VarTerm), rbuff, n); 1002 } 1003 } else { 1004 if (n > 0) 1005 AsyncInput(rbuff, n); 1006 } 1007 } 1008 } 1009 1010 if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 1011 n = read(tun_in, rbuff, sizeof(rbuff)); 1012 if (n < 0) { 1013 LogPrintf(LogERROR, "read from tun: %s", strerror(errno)); 1014 continue; 1015 } 1016 /* 1017 * Process on-demand dialup. Output packets are queued within tunnel 1018 * device until IPCP is opened. 1019 */ 1020 if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 1021 pri = PacketCheck(rbuff, n, FL_DIAL); 1022 if (pri >= 0) { 1023 if (mode & MODE_ALIAS) { 1024 VarPacketAliasOut(rbuff, sizeof rbuff); 1025 n = ntohs(((struct ip *)rbuff)->ip_len); 1026 } 1027 IpEnqueue(pri, rbuff, n); 1028 dial_up = TRUE; /* XXX */ 1029 } 1030 continue; 1031 } 1032 pri = PacketCheck(rbuff, n, FL_OUT); 1033 if (pri >= 0) { 1034 if (mode & MODE_ALIAS) { 1035 VarPacketAliasOut(rbuff, sizeof rbuff); 1036 n = ntohs(((struct ip *)rbuff)->ip_len); 1037 } 1038 IpEnqueue(pri, rbuff, n); 1039 } 1040 } 1041 } 1042 LogPrintf(LogDEBUG, "Job (DoLoop) done.\n"); 1043 } 1044