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