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