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