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