xref: /freebsd/usr.sbin/ppp/main.c (revision e627b39baccd1ec9129690167cf5e6d860509655)
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