xref: /freebsd/usr.sbin/ppp/main.c (revision c3899f8d3cfb8dd100ff3324ba2ae90b453efdcc)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *			User Process PPP
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
2060e218e4SAtsushi Murai  * $Id: main.c,v 1.6 1995/07/06 02:58:57 asami Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *	TODO:
23af57ed9fSAtsushi Murai  *		o Add commands for traffic summary, version display, etc.
24af57ed9fSAtsushi Murai  *		o Add signal handler for misc controls.
25af57ed9fSAtsushi Murai  */
26af57ed9fSAtsushi Murai #include "fsm.h"
27af57ed9fSAtsushi Murai #include <fcntl.h>
28af57ed9fSAtsushi Murai #include <sys/time.h>
29af57ed9fSAtsushi Murai #include <termios.h>
30af57ed9fSAtsushi Murai #include <signal.h>
31af57ed9fSAtsushi Murai #include <sys/wait.h>
32af57ed9fSAtsushi Murai #include <errno.h>
33af57ed9fSAtsushi Murai #include <netdb.h>
34af57ed9fSAtsushi Murai #include <sys/socket.h>
35af57ed9fSAtsushi Murai #include <arpa/inet.h>
36af57ed9fSAtsushi Murai #include "modem.h"
37af57ed9fSAtsushi Murai #include "os.h"
38af57ed9fSAtsushi Murai #include "hdlc.h"
39af57ed9fSAtsushi Murai #include "lcp.h"
40af57ed9fSAtsushi Murai #include "ipcp.h"
41af57ed9fSAtsushi Murai #include "vars.h"
4253c9f6c0SAtsushi Murai #include "auth.h"
4384b8a6ebSAtsushi Murai #include "filter.h"
4453c9f6c0SAtsushi Murai 
4541db6564SAtsushi Murai #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
46bea0b497SSatoshi Asami #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n"
4741db6564SAtsushi Murai 
4853c9f6c0SAtsushi Murai #ifndef O_NONBLOCK
4953c9f6c0SAtsushi Murai #ifdef O_NDELAY
5053c9f6c0SAtsushi Murai #define	O_NONBLOCK O_NDELAY
5153c9f6c0SAtsushi Murai #endif
5253c9f6c0SAtsushi Murai #endif
53af57ed9fSAtsushi Murai 
54af57ed9fSAtsushi Murai extern void VjInit(), AsyncInit();
55af57ed9fSAtsushi Murai extern void AsyncInput(), IpOutput();
56af57ed9fSAtsushi Murai extern int  SelectSystem();
57af57ed9fSAtsushi Murai 
58af57ed9fSAtsushi Murai extern void DecodeCommand(), Prompt();
59af57ed9fSAtsushi Murai extern int IsInteractive();
60af57ed9fSAtsushi Murai extern struct in_addr ifnetmask;
61af57ed9fSAtsushi Murai static void DoLoop(void);
62c3899f8dSAtsushi Murai static void TerminalStop();
63af57ed9fSAtsushi Murai 
64af57ed9fSAtsushi Murai static struct termios oldtio;		/* Original tty mode */
65af57ed9fSAtsushi Murai static struct termios comtio;		/* Command level tty mode */
66af57ed9fSAtsushi Murai static int TermMode;
67af57ed9fSAtsushi Murai static int server, update;
68af57ed9fSAtsushi Murai struct sockaddr_in ifsin;
69af57ed9fSAtsushi Murai 
70af57ed9fSAtsushi Murai static void
71af57ed9fSAtsushi Murai TtyInit()
72af57ed9fSAtsushi Murai {
73af57ed9fSAtsushi Murai   struct termios newtio;
74af57ed9fSAtsushi Murai   int stat;
75af57ed9fSAtsushi Murai 
76af57ed9fSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
77af57ed9fSAtsushi Murai   stat |= O_NONBLOCK;
78af57ed9fSAtsushi Murai   fcntl(0, F_SETFL, stat);
79af57ed9fSAtsushi Murai   newtio = oldtio;
80af57ed9fSAtsushi Murai   newtio.c_lflag &= ~(ECHO|ISIG|ICANON);
81af57ed9fSAtsushi Murai   newtio.c_iflag = 0;
82af57ed9fSAtsushi Murai   newtio.c_oflag &= ~OPOST;
83af57ed9fSAtsushi Murai   newtio.c_cc[VEOF] = _POSIX_VDISABLE;
84af57ed9fSAtsushi Murai   newtio.c_cc[VINTR] = _POSIX_VDISABLE;
85af57ed9fSAtsushi Murai   newtio.c_cc[VMIN] = 1;
86af57ed9fSAtsushi Murai   newtio.c_cc[VTIME] = 0;
87af57ed9fSAtsushi Murai   newtio.c_cflag |= CS8;
8853c9f6c0SAtsushi Murai   tcsetattr(0, TCSADRAIN, &newtio);
89af57ed9fSAtsushi Murai   comtio = newtio;
90af57ed9fSAtsushi Murai }
91af57ed9fSAtsushi Murai 
92af57ed9fSAtsushi Murai /*
93af57ed9fSAtsushi Murai  *  Set tty into command mode. We allow canonical input and echo processing.
94af57ed9fSAtsushi Murai  */
95c3899f8dSAtsushi Murai void
96c3899f8dSAtsushi Murai TtyCommandMode(prompt)
97c3899f8dSAtsushi Murai int prompt;
98af57ed9fSAtsushi Murai {
99af57ed9fSAtsushi Murai   struct termios newtio;
100af57ed9fSAtsushi Murai   int stat;
101af57ed9fSAtsushi Murai 
102af57ed9fSAtsushi Murai   if (!(mode & MODE_INTER))
103af57ed9fSAtsushi Murai     return;
10453c9f6c0SAtsushi Murai   tcgetattr(0, &newtio);
105c3899f8dSAtsushi Murai   newtio.c_lflag |= (ECHO|ISIG|ICANON);
106af57ed9fSAtsushi Murai   newtio.c_iflag = oldtio.c_iflag;
107af57ed9fSAtsushi Murai   newtio.c_oflag |= OPOST;
10853c9f6c0SAtsushi Murai   tcsetattr(0, TCSADRAIN, &newtio);
109af57ed9fSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
110af57ed9fSAtsushi Murai   stat |= O_NONBLOCK;
111af57ed9fSAtsushi Murai   fcntl(0, F_SETFL, stat);
112af57ed9fSAtsushi Murai   TermMode = 0;
113c3899f8dSAtsushi Murai   if(prompt) Prompt(0);
114af57ed9fSAtsushi Murai }
115af57ed9fSAtsushi Murai 
116af57ed9fSAtsushi Murai /*
117af57ed9fSAtsushi Murai  * Set tty into terminal mode which is used while we invoke term command.
118af57ed9fSAtsushi Murai  */
119af57ed9fSAtsushi Murai void
120af57ed9fSAtsushi Murai TtyTermMode()
121af57ed9fSAtsushi Murai {
122af57ed9fSAtsushi Murai   int stat;
123af57ed9fSAtsushi Murai 
12453c9f6c0SAtsushi Murai   tcsetattr(0, TCSADRAIN, &comtio);
125af57ed9fSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
126af57ed9fSAtsushi Murai   stat &= ~O_NONBLOCK;
127af57ed9fSAtsushi Murai   fcntl(0, F_SETFL, stat);
128af57ed9fSAtsushi Murai   TermMode = 1;
129af57ed9fSAtsushi Murai }
130af57ed9fSAtsushi Murai 
131af57ed9fSAtsushi Murai void
132c3899f8dSAtsushi Murai TtyOldMode()
133c3899f8dSAtsushi Murai {
134c3899f8dSAtsushi Murai   int stat;
135c3899f8dSAtsushi Murai 
136c3899f8dSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
137c3899f8dSAtsushi Murai   stat &= ~O_NONBLOCK;
138c3899f8dSAtsushi Murai   fcntl(0, F_SETFL, stat);
139c3899f8dSAtsushi Murai   tcsetattr(0, TCSANOW, &oldtio);
140c3899f8dSAtsushi Murai }
141c3899f8dSAtsushi Murai 
142c3899f8dSAtsushi Murai void
143af57ed9fSAtsushi Murai Cleanup(excode)
144af57ed9fSAtsushi Murai int excode;
145af57ed9fSAtsushi Murai {
146af57ed9fSAtsushi Murai   int stat;
147af57ed9fSAtsushi Murai 
148af57ed9fSAtsushi Murai   OsLinkdown();
149af57ed9fSAtsushi Murai   OsCloseLink(1);
150af57ed9fSAtsushi Murai   sleep(1);
151af57ed9fSAtsushi Murai   if (mode & MODE_AUTO)
152af57ed9fSAtsushi Murai     DeleteIfRoutes(1);
153af57ed9fSAtsushi Murai   OsInterfaceDown(1);
154af57ed9fSAtsushi Murai   LogPrintf(LOG_PHASE, "PPP Terminated.\n");
155af57ed9fSAtsushi Murai   LogClose();
156af57ed9fSAtsushi Murai   if (server > 0)
157af57ed9fSAtsushi Murai     close(server);
158c3899f8dSAtsushi Murai   TtyOldMode();
159af57ed9fSAtsushi Murai 
160af57ed9fSAtsushi Murai   exit(excode);
161af57ed9fSAtsushi Murai }
162af57ed9fSAtsushi Murai 
163af57ed9fSAtsushi Murai static void
164af57ed9fSAtsushi Murai Hangup()
165af57ed9fSAtsushi Murai {
166af57ed9fSAtsushi Murai   LogPrintf(LOG_PHASE, "SIGHUP\n");
167af57ed9fSAtsushi Murai   Cleanup(EX_HANGUP);
168af57ed9fSAtsushi Murai }
169af57ed9fSAtsushi Murai 
170af57ed9fSAtsushi Murai static void
171af57ed9fSAtsushi Murai CloseSession()
172af57ed9fSAtsushi Murai {
173af57ed9fSAtsushi Murai   LogPrintf(LOG_PHASE, "SIGTERM\n");
174af57ed9fSAtsushi Murai   LcpClose();
175af57ed9fSAtsushi Murai   Cleanup(EX_TERM);
176af57ed9fSAtsushi Murai }
177af57ed9fSAtsushi Murai 
178c3899f8dSAtsushi Murai 
179c3899f8dSAtsushi Murai static void
180c3899f8dSAtsushi Murai TerminalCont()
181c3899f8dSAtsushi Murai {
182c3899f8dSAtsushi Murai   (void)signal(SIGCONT, SIG_DFL);
183c3899f8dSAtsushi Murai   (void)signal(SIGTSTP, TerminalStop);
184c3899f8dSAtsushi Murai   TtyCommandMode(getpgrp() == tcgetpgrp(0));
185c3899f8dSAtsushi Murai }
186c3899f8dSAtsushi Murai 
187c3899f8dSAtsushi Murai static void
188c3899f8dSAtsushi Murai TerminalStop(signo)
189c3899f8dSAtsushi Murai int signo;
190c3899f8dSAtsushi Murai {
191c3899f8dSAtsushi Murai   (void)signal(SIGCONT, TerminalCont);
192c3899f8dSAtsushi Murai   TtyOldMode();
193c3899f8dSAtsushi Murai   signal(SIGTSTP, SIG_DFL);
194c3899f8dSAtsushi Murai   kill(getpid(), signo);
195c3899f8dSAtsushi Murai }
196c3899f8dSAtsushi Murai 
197c3899f8dSAtsushi Murai 
198af57ed9fSAtsushi Murai void
199af57ed9fSAtsushi Murai Usage()
200af57ed9fSAtsushi Murai {
201c3899f8dSAtsushi Murai   fprintf(stderr, "Usage: ppp [-auto | -direct | -dedicated] [system]\n");
202af57ed9fSAtsushi Murai   exit(EX_START);
203af57ed9fSAtsushi Murai }
204af57ed9fSAtsushi Murai 
205af57ed9fSAtsushi Murai void
206af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv)
207af57ed9fSAtsushi Murai {
208af57ed9fSAtsushi Murai   int optc;
209af57ed9fSAtsushi Murai   char *cp;
210af57ed9fSAtsushi Murai 
211af57ed9fSAtsushi Murai   optc = 0;
212af57ed9fSAtsushi Murai   while (argc > 0 && **argv == '-') {
213af57ed9fSAtsushi Murai     cp = *argv + 1;
214af57ed9fSAtsushi Murai     if (strcmp(cp, "auto") == 0)
215af57ed9fSAtsushi Murai       mode |= MODE_AUTO;
216af57ed9fSAtsushi Murai     else if (strcmp(cp, "direct") == 0)
217af57ed9fSAtsushi Murai       mode |= MODE_DIRECT;
218af57ed9fSAtsushi Murai     else if (strcmp(cp, "dedicated") == 0)
219af57ed9fSAtsushi Murai       mode |= MODE_DEDICATED;
220af57ed9fSAtsushi Murai     else
221af57ed9fSAtsushi Murai       Usage();
222af57ed9fSAtsushi Murai     optc++;
223af57ed9fSAtsushi Murai     argv++; argc--;
224af57ed9fSAtsushi Murai   }
225af57ed9fSAtsushi Murai   if (argc > 1) {
226af57ed9fSAtsushi Murai     fprintf(stderr, "specify only one system label.\n");
227af57ed9fSAtsushi Murai     exit(EX_START);
228af57ed9fSAtsushi Murai   }
229af57ed9fSAtsushi Murai   if (argc == 1) dstsystem = *argv;
230af57ed9fSAtsushi Murai 
231af57ed9fSAtsushi Murai   if (optc > 1) {
232af57ed9fSAtsushi Murai     fprintf(stderr, "specify only one mode.\n");
233af57ed9fSAtsushi Murai     exit(EX_START);
234af57ed9fSAtsushi Murai   }
235af57ed9fSAtsushi Murai }
236af57ed9fSAtsushi Murai 
237af57ed9fSAtsushi Murai static void
238af57ed9fSAtsushi Murai Greetings()
239af57ed9fSAtsushi Murai {
240af57ed9fSAtsushi Murai   printf("User Process PPP. Written by Toshiharu OHNO.\r\n");
241af57ed9fSAtsushi Murai   fflush(stdout);
242af57ed9fSAtsushi Murai }
243af57ed9fSAtsushi Murai 
244af57ed9fSAtsushi Murai void
245af57ed9fSAtsushi Murai main(argc, argv)
246af57ed9fSAtsushi Murai int argc;
247af57ed9fSAtsushi Murai char **argv;
248af57ed9fSAtsushi Murai {
249af57ed9fSAtsushi Murai   int tunno;
250af57ed9fSAtsushi Murai   int on = 1;
251af57ed9fSAtsushi Murai 
252af57ed9fSAtsushi Murai   argc--; argv++;
253af57ed9fSAtsushi Murai 
254af57ed9fSAtsushi Murai   mode = MODE_INTER;		/* default operation is interactive mode */
255af57ed9fSAtsushi Murai   netfd = -1;
256af57ed9fSAtsushi Murai   ProcessArgs(argc, argv);
257af57ed9fSAtsushi Murai   Greetings();
258af57ed9fSAtsushi Murai   GetUid();
259af57ed9fSAtsushi Murai   IpcpDefAddress();
260af57ed9fSAtsushi Murai 
261af57ed9fSAtsushi Murai   if (SelectSystem("default", CONFFILE) < 0) {
262af57ed9fSAtsushi Murai     fprintf(stderr, "Warning: No default entry is given in config file.\n");
263af57ed9fSAtsushi Murai   }
264af57ed9fSAtsushi Murai 
265af57ed9fSAtsushi Murai   if (LogOpen())
266af57ed9fSAtsushi Murai     exit(EX_START);
267af57ed9fSAtsushi Murai 
26853c9f6c0SAtsushi Murai   switch ( LocalAuthInit() ) {
26953c9f6c0SAtsushi Murai     case NOT_FOUND:
27041db6564SAtsushi Murai     	fprintf(stderr,LAUTH_M1);
27141db6564SAtsushi Murai     	fprintf(stderr,LAUTH_M2);
27241db6564SAtsushi Murai 	fflush (stderr);
27341db6564SAtsushi Murai 	/* Fall down */
27441db6564SAtsushi Murai     case VALID:
27553c9f6c0SAtsushi Murai 	VarLocalAuth = LOCAL_AUTH;
27653c9f6c0SAtsushi Murai 	break;
27753c9f6c0SAtsushi Murai     default:
27853c9f6c0SAtsushi Murai 	break;
27953c9f6c0SAtsushi Murai   }
28053c9f6c0SAtsushi Murai 
281af57ed9fSAtsushi Murai   if (OpenTunnel(&tunno) < 0) {
282af57ed9fSAtsushi Murai     perror("open_tun");
283af57ed9fSAtsushi Murai     exit(EX_START);
284af57ed9fSAtsushi Murai   }
285af57ed9fSAtsushi Murai 
286af57ed9fSAtsushi Murai   if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED))
287af57ed9fSAtsushi Murai     mode &= ~MODE_INTER;
288af57ed9fSAtsushi Murai   if (mode & MODE_INTER) {
289af57ed9fSAtsushi Murai     printf("Interactive mode\n");
290af57ed9fSAtsushi Murai     netfd = 0;
291af57ed9fSAtsushi Murai   } else if (mode & MODE_AUTO) {
292af57ed9fSAtsushi Murai     printf("Automatic mode\n");
293af57ed9fSAtsushi Murai     if (dstsystem == NULL) {
294af57ed9fSAtsushi Murai       fprintf(stderr, "Destination system must be specified in auto mode.\n");
295af57ed9fSAtsushi Murai       exit(EX_START);
296af57ed9fSAtsushi Murai     }
297af57ed9fSAtsushi Murai   }
298af57ed9fSAtsushi Murai 
29953c9f6c0SAtsushi Murai   tcgetattr(0, &oldtio);		/* Save original tty mode */
300af57ed9fSAtsushi Murai 
301af57ed9fSAtsushi Murai   signal(SIGHUP, Hangup);
302af57ed9fSAtsushi Murai   signal(SIGTERM, CloseSession);
303af57ed9fSAtsushi Murai   signal(SIGINT, CloseSession);
304c3899f8dSAtsushi Murai   signal(SIGQUIT, CloseSession);
30553c9f6c0SAtsushi Murai #ifdef SIGSEGV
306af57ed9fSAtsushi Murai   signal(SIGSEGV, Hangup);
30753c9f6c0SAtsushi Murai #endif
30853c9f6c0SAtsushi Murai #ifdef SIGPIPE
30953c9f6c0SAtsushi Murai   signal(SIGPIPE, Hangup);
31053c9f6c0SAtsushi Murai #endif
31153c9f6c0SAtsushi Murai #ifdef SIGALRM
31253c9f6c0SAtsushi Murai   signal(SIGALRM, SIG_IGN);
31353c9f6c0SAtsushi Murai #endif
314c3899f8dSAtsushi Murai   if(mode & MODE_INTER)
315c3899f8dSAtsushi Murai     {
316c3899f8dSAtsushi Murai #ifdef SIGTSTP
317c3899f8dSAtsushi Murai       signal(SIGTSTP, TerminalStop);
318c3899f8dSAtsushi Murai #endif
319c3899f8dSAtsushi Murai #ifdef SIGTTIN
320c3899f8dSAtsushi Murai       signal(SIGTTIN, TerminalStop);
321c3899f8dSAtsushi Murai #endif
322c3899f8dSAtsushi Murai #ifdef SIGTTOU
323c3899f8dSAtsushi Murai       signal(SIGTTOU, SIG_IGN);
324c3899f8dSAtsushi Murai #endif
325c3899f8dSAtsushi Murai     }
326af57ed9fSAtsushi Murai 
327af57ed9fSAtsushi Murai   if (dstsystem) {
328af57ed9fSAtsushi Murai     if (SelectSystem(dstsystem, CONFFILE) < 0) {
329af57ed9fSAtsushi Murai       fprintf(stderr, "Destination system not found in conf file.\n");
330af57ed9fSAtsushi Murai       Cleanup(EX_START);
331af57ed9fSAtsushi Murai     }
332af57ed9fSAtsushi Murai     if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
333af57ed9fSAtsushi Murai       fprintf(stderr, "Must specify dstaddr with auto mode.\n");
334af57ed9fSAtsushi Murai       Cleanup(EX_START);
335af57ed9fSAtsushi Murai     }
336af57ed9fSAtsushi Murai   }
337af57ed9fSAtsushi Murai   if (mode & MODE_DIRECT)
338af57ed9fSAtsushi Murai     printf("Packet mode enabled.\n");
339af57ed9fSAtsushi Murai 
340af57ed9fSAtsushi Murai #ifdef notdef
341af57ed9fSAtsushi Murai   if (mode & MODE_AUTO) {
342af57ed9fSAtsushi Murai     OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask);
343af57ed9fSAtsushi Murai   }
344af57ed9fSAtsushi Murai #endif
345af57ed9fSAtsushi Murai 
346af57ed9fSAtsushi Murai   if (!(mode & MODE_INTER)) {
347af57ed9fSAtsushi Murai      int port = SERVER_PORT + tunno;
348af57ed9fSAtsushi Murai     /*
349af57ed9fSAtsushi Murai      *  Create server socket and listen at there.
350af57ed9fSAtsushi Murai      */
351af57ed9fSAtsushi Murai     server = socket(PF_INET, SOCK_STREAM, 0);
352af57ed9fSAtsushi Murai     if (server < 0) {
353af57ed9fSAtsushi Murai       perror("socket");
354af57ed9fSAtsushi Murai       Cleanup(EX_SOCK);
355af57ed9fSAtsushi Murai     }
356af57ed9fSAtsushi Murai     ifsin.sin_family = AF_INET;
357af57ed9fSAtsushi Murai     ifsin.sin_addr.s_addr = INADDR_ANY;
358af57ed9fSAtsushi Murai     ifsin.sin_port = htons(port);
359af57ed9fSAtsushi Murai     if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) {
360af57ed9fSAtsushi Murai       perror("bind");
361af57ed9fSAtsushi Murai       if (errno == EADDRINUSE)
362af57ed9fSAtsushi Murai 	fprintf(stderr, "Wait for a while, then try again.\n");
363af57ed9fSAtsushi Murai       Cleanup(EX_SOCK);
364af57ed9fSAtsushi Murai     }
365af57ed9fSAtsushi Murai     listen(server, 5);
366af57ed9fSAtsushi Murai 
367af57ed9fSAtsushi Murai     DupLog();
368af57ed9fSAtsushi Murai     if (!(mode & MODE_DIRECT)) {
369af57ed9fSAtsushi Murai       if (fork())
370af57ed9fSAtsushi Murai         exit(0);
371af57ed9fSAtsushi Murai     }
372af57ed9fSAtsushi Murai     LogPrintf(LOG_PHASE, "Listening at %d.\n", port);
373af57ed9fSAtsushi Murai #ifdef DOTTYINIT
37453c9f6c0SAtsushi Murai     if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */
375af57ed9fSAtsushi Murai #else
376af57ed9fSAtsushi Murai     if (mode & MODE_DIRECT) {
377af57ed9fSAtsushi Murai #endif
378af57ed9fSAtsushi Murai       TtyInit();
379af57ed9fSAtsushi Murai     } else {
380af57ed9fSAtsushi Murai       setsid();			/* detach control tty */
381af57ed9fSAtsushi Murai     }
382af57ed9fSAtsushi Murai   } else {
383af57ed9fSAtsushi Murai     server = -1;
384af57ed9fSAtsushi Murai     TtyInit();
385c3899f8dSAtsushi Murai     TtyCommandMode(1);
386af57ed9fSAtsushi Murai   }
387af57ed9fSAtsushi Murai   LogPrintf(LOG_PHASE, "PPP Started.\n");
388af57ed9fSAtsushi Murai 
389af57ed9fSAtsushi Murai 
390af57ed9fSAtsushi Murai   do
391af57ed9fSAtsushi Murai    DoLoop();
392af57ed9fSAtsushi Murai   while (mode & MODE_DEDICATED);
393af57ed9fSAtsushi Murai 
394af57ed9fSAtsushi Murai   Cleanup(EX_DONE);
395af57ed9fSAtsushi Murai }
396af57ed9fSAtsushi Murai 
397af57ed9fSAtsushi Murai /*
398af57ed9fSAtsushi Murai  *  Turn into packet mode, where we speek PPP.
399af57ed9fSAtsushi Murai  */
400af57ed9fSAtsushi Murai void
401af57ed9fSAtsushi Murai PacketMode()
402af57ed9fSAtsushi Murai {
403af57ed9fSAtsushi Murai   if (RawModem(modem) < 0) {
404af57ed9fSAtsushi Murai     fprintf(stderr, "Not connected.\r\n");
405af57ed9fSAtsushi Murai     return;
406af57ed9fSAtsushi Murai   }
407af57ed9fSAtsushi Murai 
408af57ed9fSAtsushi Murai   AsyncInit();
409af57ed9fSAtsushi Murai   VjInit();
410af57ed9fSAtsushi Murai   LcpInit();
411af57ed9fSAtsushi Murai   IpcpInit();
412af57ed9fSAtsushi Murai   CcpInit();
413af57ed9fSAtsushi Murai   LcpUp();
414af57ed9fSAtsushi Murai 
415af57ed9fSAtsushi Murai   if (mode & (MODE_DIRECT|MODE_DEDICATED))
416af57ed9fSAtsushi Murai     LcpOpen(OPEN_ACTIVE);
417af57ed9fSAtsushi Murai   else
418af57ed9fSAtsushi Murai     LcpOpen(VarOpenMode);
419af57ed9fSAtsushi Murai   if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) {
420c3899f8dSAtsushi Murai     TtyCommandMode(1);
421af57ed9fSAtsushi Murai     fprintf(stderr, "Packet mode.\r\n");
422af57ed9fSAtsushi Murai   }
423af57ed9fSAtsushi Murai }
424af57ed9fSAtsushi Murai 
425af57ed9fSAtsushi Murai static void
426af57ed9fSAtsushi Murai ShowHelp()
427af57ed9fSAtsushi Murai {
428c3899f8dSAtsushi Murai   fprintf(stderr, "The following commands are available:\r\n");
429af57ed9fSAtsushi Murai   fprintf(stderr, " ~p\tEnter to Packet mode\r\n");
430af57ed9fSAtsushi Murai   fprintf(stderr, " ~.\tTerminate program\r\n");
431af57ed9fSAtsushi Murai }
432af57ed9fSAtsushi Murai 
433af57ed9fSAtsushi Murai static void
434af57ed9fSAtsushi Murai ReadTty()
435af57ed9fSAtsushi Murai {
436af57ed9fSAtsushi Murai   int n;
437af57ed9fSAtsushi Murai   char ch;
438af57ed9fSAtsushi Murai   static int ttystate;
439af57ed9fSAtsushi Murai #define MAXLINESIZE 200
440af57ed9fSAtsushi Murai   char linebuff[MAXLINESIZE];
441af57ed9fSAtsushi Murai 
442af57ed9fSAtsushi Murai #ifdef DEBUG
443af57ed9fSAtsushi Murai   logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode);
444af57ed9fSAtsushi Murai #endif
445af57ed9fSAtsushi Murai   if (!TermMode) {
446af57ed9fSAtsushi Murai     n = read(netfd, linebuff, sizeof(linebuff)-1);
44753c9f6c0SAtsushi Murai     if (n > 0) {
448af57ed9fSAtsushi Murai       DecodeCommand(linebuff, n, 1);
44953c9f6c0SAtsushi Murai     } else {
450af57ed9fSAtsushi Murai #ifdef DEBUG
451af57ed9fSAtsushi Murai       logprintf("connection closed.\n");
452af57ed9fSAtsushi Murai #endif
453af57ed9fSAtsushi Murai       close(netfd);
454af57ed9fSAtsushi Murai       netfd = -1;
455af57ed9fSAtsushi Murai       mode &= ~MODE_INTER;
456af57ed9fSAtsushi Murai     }
457af57ed9fSAtsushi Murai     return;
458af57ed9fSAtsushi Murai   }
459af57ed9fSAtsushi Murai 
460af57ed9fSAtsushi Murai   /*
461af57ed9fSAtsushi Murai    *  We are in terminal mode, decode special sequences
462af57ed9fSAtsushi Murai    */
463af57ed9fSAtsushi Murai   n = read(0, &ch, 1);
464af57ed9fSAtsushi Murai #ifdef DEBUG
465af57ed9fSAtsushi Murai   logprintf("got %d bytes\n", n);
466af57ed9fSAtsushi Murai #endif
467af57ed9fSAtsushi Murai 
468af57ed9fSAtsushi Murai   if (n > 0) {
469af57ed9fSAtsushi Murai     switch (ttystate) {
470af57ed9fSAtsushi Murai     case 0:
471af57ed9fSAtsushi Murai       if (ch == '~')
472af57ed9fSAtsushi Murai 	ttystate++;
473af57ed9fSAtsushi Murai       else
474af57ed9fSAtsushi Murai 	write(modem, &ch, n);
475af57ed9fSAtsushi Murai       break;
476af57ed9fSAtsushi Murai     case 1:
477af57ed9fSAtsushi Murai       switch (ch) {
478af57ed9fSAtsushi Murai       case '?':
479af57ed9fSAtsushi Murai 	ShowHelp();
480af57ed9fSAtsushi Murai 	break;
481af57ed9fSAtsushi Murai       case '-':
482af57ed9fSAtsushi Murai 	if (loglevel > 0) {
483af57ed9fSAtsushi Murai 	  loglevel--;
484af57ed9fSAtsushi Murai 	  fprintf(stderr, "New loglevel is %d\r\n", loglevel);
485af57ed9fSAtsushi Murai 	}
486af57ed9fSAtsushi Murai 	break;
487af57ed9fSAtsushi Murai       case '+':
488af57ed9fSAtsushi Murai 	loglevel++;
489af57ed9fSAtsushi Murai 	fprintf(stderr, "New loglevel is %d\r\n", loglevel);
490af57ed9fSAtsushi Murai 	break;
491af57ed9fSAtsushi Murai #ifdef DEBUG
492af57ed9fSAtsushi Murai       case 'm':
493af57ed9fSAtsushi Murai 	ShowMemMap();
494af57ed9fSAtsushi Murai 	break;
495af57ed9fSAtsushi Murai #endif
496af57ed9fSAtsushi Murai       case 'p':
497af57ed9fSAtsushi Murai 	/*
498af57ed9fSAtsushi Murai 	 * XXX: Should check carrier.
499af57ed9fSAtsushi Murai 	 */
500af57ed9fSAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED) {
501af57ed9fSAtsushi Murai 	  VarOpenMode = OPEN_ACTIVE;
502af57ed9fSAtsushi Murai 	  PacketMode();
503af57ed9fSAtsushi Murai 	}
504af57ed9fSAtsushi Murai 	break;
505af57ed9fSAtsushi Murai #ifdef DEBUG
506af57ed9fSAtsushi Murai       case 't':
507af57ed9fSAtsushi Murai 	ShowTimers();
508af57ed9fSAtsushi Murai 	break;
509af57ed9fSAtsushi Murai #endif
510af57ed9fSAtsushi Murai       case '.':
511af57ed9fSAtsushi Murai 	TermMode = 1;
512c3899f8dSAtsushi Murai 	TtyCommandMode(1);
513af57ed9fSAtsushi Murai 	break;
514af57ed9fSAtsushi Murai       default:
515af57ed9fSAtsushi Murai 	if (write(modem, &ch, n) < 0)
516af57ed9fSAtsushi Murai 	  fprintf(stderr, "err in write.\r\n");
517af57ed9fSAtsushi Murai 	break;
518af57ed9fSAtsushi Murai       }
519af57ed9fSAtsushi Murai       ttystate = 0;
520af57ed9fSAtsushi Murai       break;
521af57ed9fSAtsushi Murai     }
522af57ed9fSAtsushi Murai   }
523af57ed9fSAtsushi Murai }
524af57ed9fSAtsushi Murai 
525af57ed9fSAtsushi Murai 
526af57ed9fSAtsushi Murai /*
527af57ed9fSAtsushi Murai  *  Here, we'll try to detect HDLC frame
528af57ed9fSAtsushi Murai  */
529af57ed9fSAtsushi Murai 
530af57ed9fSAtsushi Murai static char *FrameHeaders[] = {
53153c9f6c0SAtsushi Murai   "\176\377\003\300\041",
53253c9f6c0SAtsushi Murai   "\176\377\175\043\300\041",
53353c9f6c0SAtsushi Murai   "\176\177\175\043\100\041",
53453c9f6c0SAtsushi Murai   "\176\175\337\175\043\300\041",
53553c9f6c0SAtsushi Murai   "\176\175\137\175\043\100\041",
536af57ed9fSAtsushi Murai   NULL,
537af57ed9fSAtsushi Murai };
538af57ed9fSAtsushi Murai 
539af57ed9fSAtsushi Murai u_char *
540af57ed9fSAtsushi Murai HdlcDetect(cp, n)
541af57ed9fSAtsushi Murai u_char *cp;
542af57ed9fSAtsushi Murai int n;
543af57ed9fSAtsushi Murai {
54453c9f6c0SAtsushi Murai   char *ptr, *fp, **hp;
545af57ed9fSAtsushi Murai 
546af57ed9fSAtsushi Murai   cp[n] = '\0';	/* be sure to null terminated */
547af57ed9fSAtsushi Murai   ptr = NULL;
548af57ed9fSAtsushi Murai   for (hp = FrameHeaders; *hp; hp++) {
54953c9f6c0SAtsushi Murai     fp = *hp;
55053c9f6c0SAtsushi Murai     if (DEV_IS_SYNC)
55153c9f6c0SAtsushi Murai       fp++;
55253c9f6c0SAtsushi Murai     if (ptr = strstr((char *)cp, fp))
553af57ed9fSAtsushi Murai       break;
554af57ed9fSAtsushi Murai   }
555af57ed9fSAtsushi Murai   return((u_char *)ptr);
556af57ed9fSAtsushi Murai }
557af57ed9fSAtsushi Murai 
558af57ed9fSAtsushi Murai static struct pppTimer RedialTimer;
559af57ed9fSAtsushi Murai 
560af57ed9fSAtsushi Murai static void
561af57ed9fSAtsushi Murai RedialTimeout()
562af57ed9fSAtsushi Murai {
563af57ed9fSAtsushi Murai   StopTimer(&RedialTimer);
564af57ed9fSAtsushi Murai   LogPrintf(LOG_PHASE, "Redialing timer expired.\n");
565af57ed9fSAtsushi Murai }
566af57ed9fSAtsushi Murai 
567af57ed9fSAtsushi Murai static void
568af57ed9fSAtsushi Murai StartRedialTimer()
569af57ed9fSAtsushi Murai {
570af57ed9fSAtsushi Murai   LogPrintf(LOG_PHASE, "Enter pause for redialing.\n");
571af57ed9fSAtsushi Murai   StopTimer(&RedialTimer);
572af57ed9fSAtsushi Murai   RedialTimer.state = TIMER_STOPPED;
573af57ed9fSAtsushi Murai   RedialTimer.load = REDIAL_PERIOD * SECTICKS;
574af57ed9fSAtsushi Murai   RedialTimer.func = RedialTimeout;
575af57ed9fSAtsushi Murai   StartTimer(&RedialTimer);
576af57ed9fSAtsushi Murai }
577af57ed9fSAtsushi Murai 
578af57ed9fSAtsushi Murai 
579af57ed9fSAtsushi Murai static void
580af57ed9fSAtsushi Murai DoLoop()
581af57ed9fSAtsushi Murai {
582af57ed9fSAtsushi Murai   fd_set rfds, wfds, efds;
583af57ed9fSAtsushi Murai   int pri, i, n, wfd;
584af57ed9fSAtsushi Murai   struct sockaddr_in hisaddr;
585af57ed9fSAtsushi Murai   struct timeval timeout, *tp;
586af57ed9fSAtsushi Murai   int ssize = sizeof(hisaddr);
587af57ed9fSAtsushi Murai   u_char *cp;
588af57ed9fSAtsushi Murai   u_char rbuff[MAX_MRU];
58984b8a6ebSAtsushi Murai   int dial_up;
59060e218e4SAtsushi Murai   int qlen;
591c3899f8dSAtsushi Murai   pid_t pgroup;
592c3899f8dSAtsushi Murai 
593c3899f8dSAtsushi Murai   pgroup = getpgrp();
594af57ed9fSAtsushi Murai 
595af57ed9fSAtsushi Murai   if (mode & MODE_DIRECT) {
596af57ed9fSAtsushi Murai     modem = OpenModem(mode);
59760e218e4SAtsushi Murai     LogPrintf(LOG_PHASE, "Packet mode enabled\n");
598af57ed9fSAtsushi Murai     PacketMode();
599af57ed9fSAtsushi Murai   } else if (mode & MODE_DEDICATED) {
600af57ed9fSAtsushi Murai     if (!modem)
601af57ed9fSAtsushi Murai       modem = OpenModem(mode);
602af57ed9fSAtsushi Murai   }
603af57ed9fSAtsushi Murai 
604af57ed9fSAtsushi Murai   fflush(stdout);
605af57ed9fSAtsushi Murai 
60653c9f6c0SAtsushi Murai #ifdef SIGALRM
60784b8a6ebSAtsushi Murai   timeout.tv_sec = 0;
60853c9f6c0SAtsushi Murai #else
609af57ed9fSAtsushi Murai   timeout.tv_usec = 0;
61053c9f6c0SAtsushi Murai #endif
611af57ed9fSAtsushi Murai 
61284b8a6ebSAtsushi Murai   dial_up = FALSE;			/* XXXX */
613af57ed9fSAtsushi Murai   for (;;) {
61484b8a6ebSAtsushi Murai     if ( modem )
615af57ed9fSAtsushi Murai 	IpStartOutput();
616af57ed9fSAtsushi Murai     FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
61784b8a6ebSAtsushi Murai 
61884b8a6ebSAtsushi Murai    /*
61984b8a6ebSAtsushi Murai     * If Ip packet for output is enqueued and require dial up,
62084b8a6ebSAtsushi Murai     * Just do it!
62184b8a6ebSAtsushi Murai     */
62284b8a6ebSAtsushi Murai     if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */
62384b8a6ebSAtsushi Murai #ifdef DEBUG
62484b8a6ebSAtsushi Murai       logprintf("going to dial: modem = %d\n", modem);
62584b8a6ebSAtsushi Murai #endif
62684b8a6ebSAtsushi Murai        modem = OpenModem(mode);
62784b8a6ebSAtsushi Murai        if (modem < 0) {
62884b8a6ebSAtsushi Murai          modem = 0;	       /* Set intial value for next OpenModem */
62984b8a6ebSAtsushi Murai          StartRedialTimer();
63084b8a6ebSAtsushi Murai        } else {
63184b8a6ebSAtsushi Murai          if (DialModem()) {
63284b8a6ebSAtsushi Murai            sleep(1);	       /* little pause to allow peer starts */
63384b8a6ebSAtsushi Murai            ModemTimeout();
63484b8a6ebSAtsushi Murai            PacketMode();
63584b8a6ebSAtsushi Murai            dial_up = FALSE;
63684b8a6ebSAtsushi Murai          } else {
63784b8a6ebSAtsushi Murai            CloseModem();
63884b8a6ebSAtsushi Murai            /* Dial failed. Keep quite during redial wait period. */
63984b8a6ebSAtsushi Murai            StartRedialTimer();
64084b8a6ebSAtsushi Murai          }
64184b8a6ebSAtsushi Murai        }
64284b8a6ebSAtsushi Murai     }
64360e218e4SAtsushi Murai     qlen = ModemQlen();
64484b8a6ebSAtsushi Murai     if (modem) {
64584b8a6ebSAtsushi Murai       FD_SET(modem, &rfds);
64684b8a6ebSAtsushi Murai       FD_SET(modem, &efds);
64760e218e4SAtsushi Murai       if (qlen > 0) {
64884b8a6ebSAtsushi Murai 	FD_SET(modem, &wfds);
64984b8a6ebSAtsushi Murai       }
65084b8a6ebSAtsushi Murai     }
651af57ed9fSAtsushi Murai     if (server > 0) FD_SET(server, &rfds);
652af57ed9fSAtsushi Murai 
653af57ed9fSAtsushi Murai     /*  *** IMPORTANT ***
654af57ed9fSAtsushi Murai      *
655af57ed9fSAtsushi Murai      *  CPU is serviced every TICKUNIT micro seconds.
656af57ed9fSAtsushi Murai      *	This value must be chosen with great care. If this values is
657af57ed9fSAtsushi Murai      *  too big, it results loss of characters from modem and poor responce.
658af57ed9fSAtsushi Murai      *  If this values is too small, ppp process eats many CPU time.
659af57ed9fSAtsushi Murai      */
66053c9f6c0SAtsushi Murai #ifndef SIGALRM
661af57ed9fSAtsushi Murai     usleep(TICKUNIT);
662af57ed9fSAtsushi Murai     TimerService();
66353c9f6c0SAtsushi Murai #endif
66460e218e4SAtsushi Murai     if ( qlen < 20 ) {
66560e218e4SAtsushi Murai       /*
66660e218e4SAtsushi Murai        *  If there are many packets queued, wait until they are drained.
66760e218e4SAtsushi Murai        */
66884b8a6ebSAtsushi Murai         FD_SET(tun_in, &rfds);
66960e218e4SAtsushi Murai     }
670af57ed9fSAtsushi Murai     if (netfd > -1) {
671af57ed9fSAtsushi Murai       FD_SET(netfd, &rfds);
672af57ed9fSAtsushi Murai       FD_SET(netfd, &efds);
673af57ed9fSAtsushi Murai     }
67484b8a6ebSAtsushi Murai 
67584b8a6ebSAtsushi Murai 
67653c9f6c0SAtsushi Murai #ifndef SIGALRM
677af57ed9fSAtsushi Murai     /*
67884b8a6ebSAtsushi Murai      *  Normally, select() will not block because modem is writable.
67984b8a6ebSAtsushi Murai      *  In AUTO mode, select will block until we find packet from tun
680af57ed9fSAtsushi Murai      */
681af57ed9fSAtsushi Murai     tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL;
682af57ed9fSAtsushi Murai     i = select(tun_in+10, &rfds, &wfds, &efds, tp);
68353c9f6c0SAtsushi Murai #else
68484b8a6ebSAtsushi Murai     /*
68584b8a6ebSAtsushi Murai      * When SIGALRM timer is running, a select function will be
68684b8a6ebSAtsushi Murai      * return -1 and EINTR after a Time Service signal hundler
68784b8a6ebSAtsushi Murai      * is done.
68884b8a6ebSAtsushi Murai      */
68953c9f6c0SAtsushi Murai     i = select(tun_in+10, &rfds, &wfds, &efds, NULL);
69053c9f6c0SAtsushi Murai #endif
691af57ed9fSAtsushi Murai     if ( i == 0 ) {
692af57ed9fSAtsushi Murai         continue;
693af57ed9fSAtsushi Murai     }
69453c9f6c0SAtsushi Murai 
695af57ed9fSAtsushi Murai     if ( i < 0 ) {
69684b8a6ebSAtsushi Murai        if ( errno == EINTR ) {
69784b8a6ebSAtsushi Murai           continue;            /* Got SIGALRM, Do check a queue for dailing */
69884b8a6ebSAtsushi Murai        }
699af57ed9fSAtsushi Murai        perror("select");
700af57ed9fSAtsushi Murai        break;
701af57ed9fSAtsushi Murai     }
70284b8a6ebSAtsushi Murai 
703af57ed9fSAtsushi Murai     if ((netfd > 0 && FD_ISSET(netfd, &efds)) || FD_ISSET(modem, &efds)) {
704af57ed9fSAtsushi Murai       logprintf("Exception detected.\n");
705af57ed9fSAtsushi Murai       break;
706af57ed9fSAtsushi Murai     }
707af57ed9fSAtsushi Murai 
708af57ed9fSAtsushi Murai     if (server > 0 && FD_ISSET(server, &rfds)) {
709af57ed9fSAtsushi Murai #ifdef DEBUG
710af57ed9fSAtsushi Murai       logprintf("connected to client.\n");
711af57ed9fSAtsushi Murai #endif
712af57ed9fSAtsushi Murai       wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize);
713af57ed9fSAtsushi Murai       if (netfd > 0) {
714af57ed9fSAtsushi Murai 	write(wfd, "already in use.\n", 16);
715af57ed9fSAtsushi Murai 	close(wfd);
716af57ed9fSAtsushi Murai 	continue;
717af57ed9fSAtsushi Murai       } else
718af57ed9fSAtsushi Murai 	netfd = wfd;
719af57ed9fSAtsushi Murai       if (dup2(netfd, 1) < 0)
720af57ed9fSAtsushi Murai 	perror("dup2");
721af57ed9fSAtsushi Murai       mode |= MODE_INTER;
722af57ed9fSAtsushi Murai       Greetings();
72341db6564SAtsushi Murai       switch ( LocalAuthInit() ) {
72441db6564SAtsushi Murai          case NOT_FOUND:
72541db6564SAtsushi Murai     	    fprintf(stdout,LAUTH_M1);
72641db6564SAtsushi Murai     	    fprintf(stdout,LAUTH_M2);
72741db6564SAtsushi Murai             fflush(stdout);
72841db6564SAtsushi Murai 	    /* Fall down */
72941db6564SAtsushi Murai          case VALID:
73041db6564SAtsushi Murai 	    VarLocalAuth = LOCAL_AUTH;
73141db6564SAtsushi Murai 	    break;
73241db6564SAtsushi Murai          default:
73341db6564SAtsushi Murai 	    break;
73441db6564SAtsushi Murai       }
735af57ed9fSAtsushi Murai       (void) IsInteractive();
736af57ed9fSAtsushi Murai       Prompt(0);
737af57ed9fSAtsushi Murai     }
738af57ed9fSAtsushi Murai 
739c3899f8dSAtsushi Murai     if ((mode & MODE_INTER) && FD_ISSET(netfd, &rfds) &&
740c3899f8dSAtsushi Murai 	pgroup == tcgetpgrp(0)) {
741af57ed9fSAtsushi Murai       /* something to read from tty */
742af57ed9fSAtsushi Murai       ReadTty();
743af57ed9fSAtsushi Murai     }
744af57ed9fSAtsushi Murai     if (modem) {
745af57ed9fSAtsushi Murai       if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
746af57ed9fSAtsushi Murai 	 ModemStartOutput(modem);
747af57ed9fSAtsushi Murai       }
748af57ed9fSAtsushi Murai       if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
74953c9f6c0SAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED)
75053c9f6c0SAtsushi Murai 	  usleep(10000);
751af57ed9fSAtsushi Murai 	n = read(modem, rbuff, sizeof(rbuff));
752af57ed9fSAtsushi Murai 	if ((mode & MODE_DIRECT) && n <= 0) {
753af57ed9fSAtsushi Murai 	  DownConnection();
754af57ed9fSAtsushi Murai 	} else
755af57ed9fSAtsushi Murai           LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n);
756af57ed9fSAtsushi Murai 
757af57ed9fSAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED) {
758af57ed9fSAtsushi Murai 	  /*
759af57ed9fSAtsushi Murai 	   *  In dedicated mode, we just discard input until LCP is started.
760af57ed9fSAtsushi Murai 	   */
761af57ed9fSAtsushi Murai 	  if (!(mode & MODE_DEDICATED)) {
762af57ed9fSAtsushi Murai 	    cp = HdlcDetect(rbuff, n);
763af57ed9fSAtsushi Murai 	    if (cp) {
764af57ed9fSAtsushi Murai 	      /*
765af57ed9fSAtsushi Murai 	       * LCP packet is detected. Turn ourselves into packet mode.
766af57ed9fSAtsushi Murai 	       */
767af57ed9fSAtsushi Murai 	      if (cp != rbuff) {
768af57ed9fSAtsushi Murai 	        write(1, rbuff, cp - rbuff);
769af57ed9fSAtsushi Murai 	        write(1, "\r\n", 2);
770af57ed9fSAtsushi Murai 	      }
771af57ed9fSAtsushi Murai 	      PacketMode();
772af57ed9fSAtsushi Murai #ifdef notdef
773af57ed9fSAtsushi Murai 	      AsyncInput(cp, n - (cp - rbuff));
774af57ed9fSAtsushi Murai #endif
775af57ed9fSAtsushi Murai 	    } else
776af57ed9fSAtsushi Murai 	      write(1, rbuff, n);
777af57ed9fSAtsushi Murai 	  }
778af57ed9fSAtsushi Murai 	} else {
779af57ed9fSAtsushi Murai 	  if (n > 0)
780af57ed9fSAtsushi Murai 	    AsyncInput(rbuff, n);
781af57ed9fSAtsushi Murai #ifdef notdef
782af57ed9fSAtsushi Murai 	  continue;			/* THIS LINE RESULT AS POOR PERFORMANCE */
783af57ed9fSAtsushi Murai #endif
784af57ed9fSAtsushi Murai 	}
785af57ed9fSAtsushi Murai       }
786af57ed9fSAtsushi Murai     }
78784b8a6ebSAtsushi Murai 
788af57ed9fSAtsushi Murai     if (FD_ISSET(tun_in, &rfds)) {	/* something to read from tun */
789af57ed9fSAtsushi Murai       n = read(tun_in, rbuff, sizeof(rbuff));
790af57ed9fSAtsushi Murai       if (n < 0) {
791af57ed9fSAtsushi Murai 	perror("read from tun");
792af57ed9fSAtsushi Murai 	continue;
793af57ed9fSAtsushi Murai       }
794af57ed9fSAtsushi Murai       /*
795af57ed9fSAtsushi Murai        *  Process on-demand dialup. Output packets are queued within tunnel
796af57ed9fSAtsushi Murai        *  device until IPCP is opened.
797af57ed9fSAtsushi Murai        */
798af57ed9fSAtsushi Murai       if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
79984b8a6ebSAtsushi Murai 	pri = PacketCheck(rbuff, n, FL_DIAL);
800af57ed9fSAtsushi Murai 	if (pri >= 0) {
801af57ed9fSAtsushi Murai 	  IpEnqueue(pri, rbuff, n);
80284b8a6ebSAtsushi Murai           dial_up = TRUE;		/* XXX */
803af57ed9fSAtsushi Murai 	}
804af57ed9fSAtsushi Murai 	continue;
805af57ed9fSAtsushi Murai       }
80684b8a6ebSAtsushi Murai       pri = PacketCheck(rbuff, n, FL_OUT);
807af57ed9fSAtsushi Murai       if (pri >= 0)
808af57ed9fSAtsushi Murai 	IpEnqueue(pri, rbuff, n);
809af57ed9fSAtsushi Murai     }
810af57ed9fSAtsushi Murai   }
811af57ed9fSAtsushi Murai   logprintf("job done.\n");
812af57ed9fSAtsushi Murai }
813