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