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