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