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