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