main.c revision 13389
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.12 1996/01/10 21:27:53 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 58extern void VjInit(), AsyncInit(); 59extern void AsyncInput(), IpOutput(); 60extern int SelectSystem(); 61 62extern void DecodeCommand(), Prompt(); 63extern int IsInteractive(); 64extern struct in_addr ifnetmask; 65static void DoLoop(void); 66static void TerminalStop(); 67 68static struct termios oldtio; /* Original tty mode */ 69static struct termios comtio; /* Command level tty mode */ 70static int TermMode; 71static int server; 72struct sockaddr_in ifsin; 73char pid_filename[128]; 74 75static void 76TtyInit() 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 */ 100void 101TtyCommandMode(prompt) 102int 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 */ 124void 125TtyTermMode() 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 136void 137TtyOldMode() 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 147void 148Cleanup(excode) 149int 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 169static void 170Hangup() 171{ 172 LogPrintf(LOG_PHASE, "SIGHUP\n"); 173 Cleanup(EX_HANGUP); 174} 175 176static void 177CloseSession() 178{ 179 LogPrintf(LOG_PHASE, "SIGTERM\n"); 180 LcpClose(); 181 Cleanup(EX_TERM); 182} 183 184 185static void 186TerminalCont() 187{ 188 (void)signal(SIGCONT, SIG_DFL); 189 (void)signal(SIGTSTP, TerminalStop); 190 TtyCommandMode(getpgrp() == tcgetpgrp(0)); 191} 192 193static void 194TerminalStop(signo) 195int signo; 196{ 197 (void)signal(SIGCONT, TerminalCont); 198 TtyOldMode(); 199 signal(SIGTSTP, SIG_DFL); 200 kill(getpid(), signo); 201} 202 203 204void 205Usage() 206{ 207 fprintf(stderr, "Usage: ppp [-auto | -direct | -dedicated] [system]\n"); 208 exit(EX_START); 209} 210 211void 212ProcessArgs(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 243static void 244Greetings() 245{ 246 printf("User Process PPP. Written by Toshiharu OHNO.\r\n"); 247 fflush(stdout); 248} 249 250void 251main(argc, argv) 252int argc; 253char **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 */ 419void 420PacketMode() 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 444static void 445ShowHelp() 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 452static void 453ReadTty() 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 549static 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 558u_char * 559HdlcDetect(cp, n) 560u_char *cp; 561int 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 578static struct pppTimer RedialTimer; 579 580static void 581RedialTimeout() 582{ 583 StopTimer(&RedialTimer); 584 LogPrintf(LOG_PHASE, "Redialing timer expired.\n"); 585} 586 587static void 588StartRedialTimer() 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 607static void 608DoLoop() 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 if ( modem ) 642 IpStartOutput(); 643 FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); 644 645 /* 646 * If Ip packet for output is enqueued and require dial up, 647 * Just do it! 648 */ 649 if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */ 650#ifdef DEBUG 651 logprintf("going to dial: modem = %d\n", modem); 652#endif 653 modem = OpenModem(mode); 654 if (modem < 0) { 655 modem = 0; /* Set intial value for next OpenModem */ 656 StartRedialTimer(); 657 } else { 658 tries++; 659 LogPrintf(LOG_CHAT, "Dial attempt %u\n", tries); 660 if (DialModem()) { 661 sleep(1); /* little pause to allow peer starts */ 662 ModemTimeout(); 663 PacketMode(); 664 dial_up = FALSE; 665 tries = 0; 666 } else { 667 CloseModem(); 668 /* Dial failed. Keep quite during redial wait period. */ 669 StartRedialTimer(); 670 671 if (VarDialTries && tries >= VarDialTries) { 672 dial_up = FALSE; 673 tries = 0; 674 } 675 } 676 } 677 } 678 qlen = ModemQlen(); 679 if (modem) { 680 FD_SET(modem, &rfds); 681 FD_SET(modem, &efds); 682 if (qlen > 0) { 683 FD_SET(modem, &wfds); 684 } 685 } 686 if (server > 0) FD_SET(server, &rfds); 687 688 /* *** IMPORTANT *** 689 * 690 * CPU is serviced every TICKUNIT micro seconds. 691 * This value must be chosen with great care. If this values is 692 * too big, it results loss of characters from modem and poor responce. 693 * If this values is too small, ppp process eats many CPU time. 694 */ 695#ifndef SIGALRM 696 usleep(TICKUNIT); 697 TimerService(); 698#endif 699 700 /* If there are aren't many packets queued, look for some more. */ 701 if (qlen < 20) 702 FD_SET(tun_in, &rfds); 703 704 if (netfd > -1) { 705 FD_SET(netfd, &rfds); 706 FD_SET(netfd, &efds); 707 } 708 709#ifndef SIGALRM 710 /* 711 * Normally, select() will not block because modem is writable. 712 * In AUTO mode, select will block until we find packet from tun 713 */ 714 tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL; 715 i = select(tun_in+10, &rfds, &wfds, &efds, tp); 716#else 717 /* 718 * When SIGALRM timer is running, a select function will be 719 * return -1 and EINTR after a Time Service signal hundler 720 * is done. If the redial timer is not running and we are 721 * trying to dial, poll with a 0 value timer. 722 */ 723 tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL; 724 i = select(tun_in+10, &rfds, &wfds, &efds, tp); 725#endif 726 if ( i == 0 ) { 727 continue; 728 } 729 730 if ( i < 0 ) { 731 if ( errno == EINTR ) { 732 continue; /* Got SIGALRM, Do check a queue for dialing */ 733 } 734 perror("select"); 735 break; 736 } 737 738 if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) { 739 logprintf("Exception detected.\n"); 740 break; 741 } 742 743 if (server > 0 && FD_ISSET(server, &rfds)) { 744#ifdef DEBUG 745 logprintf("connected to client.\n"); 746#endif 747 wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize); 748 if (netfd > 0) { 749 write(wfd, "already in use.\n", 16); 750 close(wfd); 751 continue; 752 } else 753 netfd = wfd; 754 if (dup2(netfd, 1) < 0) 755 perror("dup2"); 756 mode |= MODE_INTER; 757 Greetings(); 758 switch ( LocalAuthInit() ) { 759 case NOT_FOUND: 760 fprintf(stdout,LAUTH_M1); 761 fprintf(stdout,LAUTH_M2); 762 fflush(stdout); 763 /* Fall down */ 764 case VALID: 765 VarLocalAuth = LOCAL_AUTH; 766 break; 767 default: 768 break; 769 } 770 (void) IsInteractive(); 771 Prompt(0); 772 } 773 774 if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds) && 775 ((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) { 776 /* something to read from tty */ 777 ReadTty(); 778 } 779 if (modem) { 780 if (FD_ISSET(modem, &wfds)) { /* ready to write into modem */ 781 ModemStartOutput(modem); 782 } 783 if (FD_ISSET(modem, &rfds)) { /* something to read from modem */ 784 if (LcpFsm.state <= ST_CLOSED) 785 usleep(10000); 786 n = read(modem, rbuff, sizeof(rbuff)); 787 if ((mode & MODE_DIRECT) && n <= 0) { 788 DownConnection(); 789 } else 790 LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n); 791 792 if (LcpFsm.state <= ST_CLOSED) { 793 /* 794 * In dedicated mode, we just discard input until LCP is started. 795 */ 796 if (!(mode & MODE_DEDICATED)) { 797 cp = HdlcDetect(rbuff, n); 798 if (cp) { 799 /* 800 * LCP packet is detected. Turn ourselves into packet mode. 801 */ 802 if (cp != rbuff) { 803 write(1, rbuff, cp - rbuff); 804 write(1, "\r\n", 2); 805 } 806 PacketMode(); 807#ifdef notdef 808 AsyncInput(cp, n - (cp - rbuff)); 809#endif 810 } else 811 write(1, rbuff, n); 812 } 813 } else { 814 if (n > 0) 815 AsyncInput(rbuff, n); 816#ifdef notdef 817 continue; /* THIS LINE RESULT AS POOR PERFORMANCE */ 818#endif 819 } 820 } 821 } 822 823 if (FD_ISSET(tun_in, &rfds)) { /* something to read from tun */ 824 n = read(tun_in, rbuff, sizeof(rbuff)); 825 if (n < 0) { 826 perror("read from tun"); 827 continue; 828 } 829 /* 830 * Process on-demand dialup. Output packets are queued within tunnel 831 * device until IPCP is opened. 832 */ 833 if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) { 834 pri = PacketCheck(rbuff, n, FL_DIAL); 835 if (pri >= 0) { 836 IpEnqueue(pri, rbuff, n); 837 dial_up = TRUE; /* XXX */ 838 } 839 continue; 840 } 841 pri = PacketCheck(rbuff, n, FL_OUT); 842 if (pri >= 0) 843 IpEnqueue(pri, rbuff, n); 844 } 845 } 846 logprintf("job done.\n"); 847} 848