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