xref: /freebsd/usr.sbin/ppp/main.c (revision 780700e5edabde1b1d8c607f151848c452975c89)
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  *
20780700e5SAndrey A. Chernov  * $Id: main.c,v 1.36 1997/03/09 20:03:39 ache 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>
31c3b6ad66SBrian Somers #include <signal.h>
32af57ed9fSAtsushi Murai #include <sys/wait.h>
33af57ed9fSAtsushi Murai #include <errno.h>
34af57ed9fSAtsushi Murai #include <netdb.h>
359f202f0cSJordan K. Hubbard #include <unistd.h>
36af57ed9fSAtsushi Murai #include <sys/socket.h>
37af57ed9fSAtsushi Murai #include <arpa/inet.h>
38a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h>
39a9f484e5SJordan K. Hubbard #include <netinet/ip.h>
40af57ed9fSAtsushi Murai #include "modem.h"
41af57ed9fSAtsushi Murai #include "os.h"
42af57ed9fSAtsushi Murai #include "hdlc.h"
43ed6a16c1SPoul-Henning Kamp #include "ccp.h"
44af57ed9fSAtsushi Murai #include "lcp.h"
45af57ed9fSAtsushi Murai #include "ipcp.h"
46af57ed9fSAtsushi Murai #include "vars.h"
4753c9f6c0SAtsushi Murai #include "auth.h"
4884b8a6ebSAtsushi Murai #include "filter.h"
49ed6a16c1SPoul-Henning Kamp #include "systems.h"
50ed6a16c1SPoul-Henning Kamp #include "ip.h"
51a9f484e5SJordan K. Hubbard #include "alias.h"
5253c9f6c0SAtsushi Murai 
5341db6564SAtsushi Murai #define LAUTH_M1 "Warning: No password entry for this host in ppp.secret\n"
54bea0b497SSatoshi Asami #define LAUTH_M2 "Warning: All manipulation is allowed by anyone in the world\n"
5541db6564SAtsushi Murai 
5653c9f6c0SAtsushi Murai #ifndef O_NONBLOCK
5753c9f6c0SAtsushi Murai #ifdef O_NDELAY
5853c9f6c0SAtsushi Murai #define	O_NONBLOCK O_NDELAY
5953c9f6c0SAtsushi Murai #endif
6053c9f6c0SAtsushi Murai #endif
61af57ed9fSAtsushi Murai 
62af57ed9fSAtsushi Murai extern void VjInit(), AsyncInit();
63af57ed9fSAtsushi Murai extern void AsyncInput(), IpOutput();
64af57ed9fSAtsushi Murai extern int  SelectSystem();
65af57ed9fSAtsushi Murai 
66af57ed9fSAtsushi Murai extern void DecodeCommand(), Prompt();
67b0cdb3ceSJordan K. Hubbard extern int aft_cmd;
68af57ed9fSAtsushi Murai extern int IsInteractive();
69af57ed9fSAtsushi Murai extern struct in_addr ifnetmask;
70af57ed9fSAtsushi Murai static void DoLoop(void);
71c3899f8dSAtsushi Murai static void TerminalStop();
72af57ed9fSAtsushi Murai 
73af57ed9fSAtsushi Murai static struct termios oldtio;		/* Original tty mode */
74af57ed9fSAtsushi Murai static struct termios comtio;		/* Command level tty mode */
751dff3fc5SAndrey A. Chernov int TermMode;
767b64106aSPoul-Henning Kamp static int server;
776d14e2a8SJordan K. Hubbard static pid_t BGPid = 0;
78af57ed9fSAtsushi Murai struct sockaddr_in ifsin;
79a9c6b5dfSAtsushi Murai char pid_filename[128];
80af57ed9fSAtsushi Murai 
81af57ed9fSAtsushi Murai static void
82af57ed9fSAtsushi Murai TtyInit()
83af57ed9fSAtsushi Murai {
84af57ed9fSAtsushi Murai   struct termios newtio;
85af57ed9fSAtsushi Murai   int stat;
86af57ed9fSAtsushi Murai 
87af57ed9fSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
88af57ed9fSAtsushi Murai   stat |= O_NONBLOCK;
89af57ed9fSAtsushi Murai   fcntl(0, F_SETFL, stat);
90af57ed9fSAtsushi Murai   newtio = oldtio;
91af57ed9fSAtsushi Murai   newtio.c_lflag &= ~(ECHO|ISIG|ICANON);
92af57ed9fSAtsushi Murai   newtio.c_iflag = 0;
93af57ed9fSAtsushi Murai   newtio.c_oflag &= ~OPOST;
94af57ed9fSAtsushi Murai   newtio.c_cc[VEOF] = _POSIX_VDISABLE;
95af57ed9fSAtsushi Murai   newtio.c_cc[VINTR] = _POSIX_VDISABLE;
96af57ed9fSAtsushi Murai   newtio.c_cc[VMIN] = 1;
97af57ed9fSAtsushi Murai   newtio.c_cc[VTIME] = 0;
98af57ed9fSAtsushi Murai   newtio.c_cflag |= CS8;
9953c9f6c0SAtsushi Murai   tcsetattr(0, TCSADRAIN, &newtio);
100af57ed9fSAtsushi Murai   comtio = newtio;
101af57ed9fSAtsushi Murai }
102af57ed9fSAtsushi Murai 
103af57ed9fSAtsushi Murai /*
104af57ed9fSAtsushi Murai  *  Set tty into command mode. We allow canonical input and echo processing.
105af57ed9fSAtsushi Murai  */
106c3899f8dSAtsushi Murai void
107c3899f8dSAtsushi Murai TtyCommandMode(prompt)
108c3899f8dSAtsushi Murai int prompt;
109af57ed9fSAtsushi Murai {
110af57ed9fSAtsushi Murai   struct termios newtio;
111af57ed9fSAtsushi Murai   int stat;
112af57ed9fSAtsushi Murai 
113af57ed9fSAtsushi Murai   if (!(mode & MODE_INTER))
114af57ed9fSAtsushi Murai     return;
11553c9f6c0SAtsushi Murai   tcgetattr(0, &newtio);
116c3899f8dSAtsushi Murai   newtio.c_lflag |= (ECHO|ISIG|ICANON);
117af57ed9fSAtsushi Murai   newtio.c_iflag = oldtio.c_iflag;
118af57ed9fSAtsushi Murai   newtio.c_oflag |= OPOST;
11953c9f6c0SAtsushi Murai   tcsetattr(0, TCSADRAIN, &newtio);
120af57ed9fSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
121af57ed9fSAtsushi Murai   stat |= O_NONBLOCK;
122af57ed9fSAtsushi Murai   fcntl(0, F_SETFL, stat);
123af57ed9fSAtsushi Murai   TermMode = 0;
124c3899f8dSAtsushi Murai   if(prompt) Prompt(0);
125af57ed9fSAtsushi Murai }
126af57ed9fSAtsushi Murai 
127af57ed9fSAtsushi Murai /*
128af57ed9fSAtsushi Murai  * Set tty into terminal mode which is used while we invoke term command.
129af57ed9fSAtsushi Murai  */
130af57ed9fSAtsushi Murai void
131af57ed9fSAtsushi Murai TtyTermMode()
132af57ed9fSAtsushi Murai {
133af57ed9fSAtsushi Murai   int stat;
134af57ed9fSAtsushi Murai 
13553c9f6c0SAtsushi Murai   tcsetattr(0, TCSADRAIN, &comtio);
136af57ed9fSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
137af57ed9fSAtsushi Murai   stat &= ~O_NONBLOCK;
138af57ed9fSAtsushi Murai   fcntl(0, F_SETFL, stat);
139af57ed9fSAtsushi Murai   TermMode = 1;
140af57ed9fSAtsushi Murai }
141af57ed9fSAtsushi Murai 
142af57ed9fSAtsushi Murai void
143c3899f8dSAtsushi Murai TtyOldMode()
144c3899f8dSAtsushi Murai {
145c3899f8dSAtsushi Murai   int stat;
146c3899f8dSAtsushi Murai 
147c3899f8dSAtsushi Murai   stat = fcntl(0, F_GETFL, 0);
148c3899f8dSAtsushi Murai   stat &= ~O_NONBLOCK;
149c3899f8dSAtsushi Murai   fcntl(0, F_SETFL, stat);
150c3899f8dSAtsushi Murai   tcsetattr(0, TCSANOW, &oldtio);
151c3899f8dSAtsushi Murai }
152c3899f8dSAtsushi Murai 
153c3899f8dSAtsushi Murai void
154af57ed9fSAtsushi Murai Cleanup(excode)
155af57ed9fSAtsushi Murai int excode;
156af57ed9fSAtsushi Murai {
157af57ed9fSAtsushi Murai 
158af57ed9fSAtsushi Murai   OsLinkdown();
159af57ed9fSAtsushi Murai   OsCloseLink(1);
160af57ed9fSAtsushi Murai   sleep(1);
161a9c6b5dfSAtsushi Murai   if (mode & MODE_AUTO) {
162af57ed9fSAtsushi Murai     DeleteIfRoutes(1);
1636d14e2a8SJordan K. Hubbard   }
1646d14e2a8SJordan K. Hubbard   if (mode & (MODE_AUTO | MODE_BACKGROUND)) {
165a9c6b5dfSAtsushi Murai     unlink(pid_filename);
166a9c6b5dfSAtsushi Murai   }
167af57ed9fSAtsushi Murai   OsInterfaceDown(1);
1689c749ffbSPoul-Henning Kamp   LogPrintf(LOG_PHASE_BIT, "PPP Terminated.\n");
169af57ed9fSAtsushi Murai   LogClose();
170780700e5SAndrey A. Chernov   if (server >= 0) {
171af57ed9fSAtsushi Murai     close(server);
172780700e5SAndrey A. Chernov     server = -1;
173780700e5SAndrey A. Chernov   }
174c3899f8dSAtsushi Murai   TtyOldMode();
175af57ed9fSAtsushi Murai 
176af57ed9fSAtsushi Murai   exit(excode);
177af57ed9fSAtsushi Murai }
178af57ed9fSAtsushi Murai 
179af57ed9fSAtsushi Murai static void
1807a8ef19eSAndrey A. Chernov Hangup(signo)
1817a8ef19eSAndrey A. Chernov int signo;
182af57ed9fSAtsushi Murai {
183af83607cSAndrey A. Chernov   if (signo == SIGSEGV) {
184af83607cSAndrey A. Chernov 	LogPrintf(LOG_PHASE_BIT, "Signal %d, core dump.\n", signo);
185af83607cSAndrey A. Chernov 	LogClose();
186af83607cSAndrey A. Chernov 	abort();
187af83607cSAndrey A. Chernov   }
1886d14e2a8SJordan K. Hubbard   if (BGPid) {
1896d14e2a8SJordan K. Hubbard       kill (BGPid, SIGHUP);
1906d14e2a8SJordan K. Hubbard       exit (EX_HANGUP);
1916d14e2a8SJordan K. Hubbard   }
1926d14e2a8SJordan K. Hubbard   else {
1939c749ffbSPoul-Henning Kamp       LogPrintf(LOG_PHASE_BIT, "Signal %d, hangup.\n", signo);
194af57ed9fSAtsushi Murai       Cleanup(EX_HANGUP);
195af57ed9fSAtsushi Murai   }
1966d14e2a8SJordan K. Hubbard }
197af57ed9fSAtsushi Murai 
198af57ed9fSAtsushi Murai static void
1997a8ef19eSAndrey A. Chernov CloseSession(signo)
2007a8ef19eSAndrey A. Chernov int signo;
201af57ed9fSAtsushi Murai {
2026d14e2a8SJordan K. Hubbard    if (BGPid) {
2036d14e2a8SJordan K. Hubbard      kill (BGPid, SIGINT);
2046d14e2a8SJordan K. Hubbard      exit (EX_TERM);
2056d14e2a8SJordan K. Hubbard    }
2066d14e2a8SJordan K. Hubbard    else {
2079c749ffbSPoul-Henning Kamp      LogPrintf(LOG_PHASE_BIT, "Signal %d, terminate.\n", signo);
208af57ed9fSAtsushi Murai      LcpClose();
209af57ed9fSAtsushi Murai      Cleanup(EX_TERM);
210af57ed9fSAtsushi Murai    }
2116d14e2a8SJordan K. Hubbard }
212c3899f8dSAtsushi Murai 
213c3899f8dSAtsushi Murai static void
214c3899f8dSAtsushi Murai TerminalCont()
215c3899f8dSAtsushi Murai {
216bbea88d0SAndrey A. Chernov   (void)signal(SIGCONT, SIG_DFL);
217bbea88d0SAndrey A. Chernov   (void)signal(SIGTSTP, TerminalStop);
218c3899f8dSAtsushi Murai   TtyCommandMode(getpgrp() == tcgetpgrp(0));
219c3899f8dSAtsushi Murai }
220c3899f8dSAtsushi Murai 
221c3899f8dSAtsushi Murai static void
222c3899f8dSAtsushi Murai TerminalStop(signo)
223c3899f8dSAtsushi Murai int signo;
224c3899f8dSAtsushi Murai {
225bbea88d0SAndrey A. Chernov   (void)signal(SIGCONT, TerminalCont);
226c3899f8dSAtsushi Murai   TtyOldMode();
227bbea88d0SAndrey A. Chernov   signal(SIGTSTP, SIG_DFL);
228c3899f8dSAtsushi Murai   kill(getpid(), signo);
229c3899f8dSAtsushi Murai }
230c3899f8dSAtsushi Murai 
231c3899f8dSAtsushi Murai 
232af57ed9fSAtsushi Murai void
233af57ed9fSAtsushi Murai Usage()
234af57ed9fSAtsushi Murai {
235680026d6SNate Williams   fprintf(stderr,
2366d14e2a8SJordan K. Hubbard           "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ] [ -alias ] [system]\n");
237af57ed9fSAtsushi Murai   exit(EX_START);
238af57ed9fSAtsushi Murai }
239af57ed9fSAtsushi Murai 
240af57ed9fSAtsushi Murai void
241af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv)
242af57ed9fSAtsushi Murai {
243af57ed9fSAtsushi Murai   int optc;
244af57ed9fSAtsushi Murai   char *cp;
245af57ed9fSAtsushi Murai 
246af57ed9fSAtsushi Murai   optc = 0;
247af57ed9fSAtsushi Murai   while (argc > 0 && **argv == '-') {
248af57ed9fSAtsushi Murai     cp = *argv + 1;
249af57ed9fSAtsushi Murai     if (strcmp(cp, "auto") == 0)
250af57ed9fSAtsushi Murai       mode |= MODE_AUTO;
2516d14e2a8SJordan K. Hubbard     else if (strcmp(cp, "background") == 0)
2526d14e2a8SJordan K. Hubbard       mode |= MODE_BACKGROUND;
253af57ed9fSAtsushi Murai     else if (strcmp(cp, "direct") == 0)
254af57ed9fSAtsushi Murai       mode |= MODE_DIRECT;
255af57ed9fSAtsushi Murai     else if (strcmp(cp, "dedicated") == 0)
256af57ed9fSAtsushi Murai       mode |= MODE_DEDICATED;
257680026d6SNate Williams     else if (strcmp(cp, "ddial") == 0)
258680026d6SNate Williams       mode |= MODE_DDIAL|MODE_AUTO;
259a9f484e5SJordan K. Hubbard     else if (strcmp(cp, "alias") == 0) {
260a9f484e5SJordan K. Hubbard       mode |= MODE_ALIAS;
261a9f484e5SJordan K. Hubbard       optc--;             /* this option isn't exclusive */
262a9f484e5SJordan K. Hubbard     }
263af57ed9fSAtsushi Murai     else
264af57ed9fSAtsushi Murai       Usage();
265af57ed9fSAtsushi Murai     optc++;
266af57ed9fSAtsushi Murai     argv++; argc--;
267af57ed9fSAtsushi Murai   }
268af57ed9fSAtsushi Murai   if (argc > 1) {
269af57ed9fSAtsushi Murai     fprintf(stderr, "specify only one system label.\n");
270af57ed9fSAtsushi Murai     exit(EX_START);
271af57ed9fSAtsushi Murai   }
272af57ed9fSAtsushi Murai   if (argc == 1) dstsystem = *argv;
273af57ed9fSAtsushi Murai 
274af57ed9fSAtsushi Murai   if (optc > 1) {
275af57ed9fSAtsushi Murai     fprintf(stderr, "specify only one mode.\n");
276af57ed9fSAtsushi Murai     exit(EX_START);
277af57ed9fSAtsushi Murai   }
278af57ed9fSAtsushi Murai }
279af57ed9fSAtsushi Murai 
280af57ed9fSAtsushi Murai static void
281af57ed9fSAtsushi Murai Greetings()
282af57ed9fSAtsushi Murai {
283af57ed9fSAtsushi Murai   printf("User Process PPP. Written by Toshiharu OHNO.\r\n");
284af57ed9fSAtsushi Murai   fflush(stdout);
285af57ed9fSAtsushi Murai }
286af57ed9fSAtsushi Murai 
287af57ed9fSAtsushi Murai void
288af57ed9fSAtsushi Murai main(argc, argv)
289af57ed9fSAtsushi Murai int argc;
290af57ed9fSAtsushi Murai char **argv;
291af57ed9fSAtsushi Murai {
292af57ed9fSAtsushi Murai   int tunno;
293af57ed9fSAtsushi Murai 
294af57ed9fSAtsushi Murai   argc--; argv++;
295af57ed9fSAtsushi Murai 
296af57ed9fSAtsushi Murai   mode = MODE_INTER;		/* default operation is interactive mode */
297780700e5SAndrey A. Chernov   netfd = server = modem = tun_in = -1;
298af57ed9fSAtsushi Murai   ProcessArgs(argc, argv);
299af57ed9fSAtsushi Murai   Greetings();
300af57ed9fSAtsushi Murai   GetUid();
301af57ed9fSAtsushi Murai   IpcpDefAddress();
302a9f484e5SJordan K. Hubbard   InitAlias();
303af57ed9fSAtsushi Murai 
304af57ed9fSAtsushi Murai   if (SelectSystem("default", CONFFILE) < 0) {
305af57ed9fSAtsushi Murai     fprintf(stderr, "Warning: No default entry is given in config file.\n");
306af57ed9fSAtsushi Murai   }
307af57ed9fSAtsushi Murai 
308af57ed9fSAtsushi Murai   if (LogOpen())
309af57ed9fSAtsushi Murai     exit(EX_START);
310af57ed9fSAtsushi Murai 
31153c9f6c0SAtsushi Murai   switch ( LocalAuthInit() ) {
31253c9f6c0SAtsushi Murai     case NOT_FOUND:
31341db6564SAtsushi Murai     	fprintf(stderr,LAUTH_M1);
31441db6564SAtsushi Murai     	fprintf(stderr,LAUTH_M2);
31541db6564SAtsushi Murai 	fflush (stderr);
31641db6564SAtsushi Murai 	/* Fall down */
31741db6564SAtsushi Murai     case VALID:
31853c9f6c0SAtsushi Murai 	VarLocalAuth = LOCAL_AUTH;
31953c9f6c0SAtsushi Murai 	break;
32053c9f6c0SAtsushi Murai     default:
32153c9f6c0SAtsushi Murai 	break;
32253c9f6c0SAtsushi Murai   }
32353c9f6c0SAtsushi Murai 
324af57ed9fSAtsushi Murai   if (OpenTunnel(&tunno) < 0) {
325af57ed9fSAtsushi Murai     perror("open_tun");
326af57ed9fSAtsushi Murai     exit(EX_START);
327af57ed9fSAtsushi Murai   }
328af57ed9fSAtsushi Murai 
3296d14e2a8SJordan K. Hubbard   if (mode & (MODE_AUTO|MODE_DIRECT|MODE_DEDICATED|MODE_BACKGROUND))
330af57ed9fSAtsushi Murai     mode &= ~MODE_INTER;
331af57ed9fSAtsushi Murai   if (mode & MODE_INTER) {
332af57ed9fSAtsushi Murai     printf("Interactive mode\n");
333780700e5SAndrey A. Chernov     netfd = STDIN_FILENO;
334af57ed9fSAtsushi Murai   } else if (mode & MODE_AUTO) {
335680026d6SNate Williams     printf("Automatic Dialer mode\n");
336af57ed9fSAtsushi Murai     if (dstsystem == NULL) {
337680026d6SNate Williams       fprintf(stderr,
338680026d6SNate Williams               "Destination system must be specified in auto or ddial mode.\n");
339af57ed9fSAtsushi Murai       exit(EX_START);
340af57ed9fSAtsushi Murai     }
3416d14e2a8SJordan K. Hubbard   } else if (mode & MODE_BACKGROUND) {
3426d14e2a8SJordan K. Hubbard     printf("Background mode\n");
3436d14e2a8SJordan K. Hubbard     if (dstsystem == NULL) {
3446d14e2a8SJordan K. Hubbard       fprintf(stderr, "Destination system must be specified in background mode.\n");
3456d14e2a8SJordan K. Hubbard       exit(EX_START);
3466d14e2a8SJordan K. Hubbard     }
347af57ed9fSAtsushi Murai   }
348af57ed9fSAtsushi Murai 
34953c9f6c0SAtsushi Murai   tcgetattr(0, &oldtio);		/* Save original tty mode */
350af57ed9fSAtsushi Murai 
351d7f5ee41SAndrey A. Chernov   signal(SIGHUP, Hangup);
35206257ca4SAndrey A. Chernov   signal(SIGTERM, CloseSession);
35306257ca4SAndrey A. Chernov   signal(SIGINT, CloseSession);
35406257ca4SAndrey A. Chernov   signal(SIGQUIT, CloseSession);
35553c9f6c0SAtsushi Murai #ifdef SIGSEGV
356d7f5ee41SAndrey A. Chernov   signal(SIGSEGV, Hangup);
35753c9f6c0SAtsushi Murai #endif
35853c9f6c0SAtsushi Murai #ifdef SIGPIPE
359d7f5ee41SAndrey A. Chernov   signal(SIGPIPE, Hangup);
36053c9f6c0SAtsushi Murai #endif
36153c9f6c0SAtsushi Murai #ifdef SIGALRM
36206257ca4SAndrey A. Chernov   signal(SIGALRM, SIG_IGN);
36353c9f6c0SAtsushi Murai #endif
364c3899f8dSAtsushi Murai   if(mode & MODE_INTER)
365c3899f8dSAtsushi Murai     {
366c3899f8dSAtsushi Murai #ifdef SIGTSTP
367bbea88d0SAndrey A. Chernov       signal(SIGTSTP, TerminalStop);
368c3899f8dSAtsushi Murai #endif
369c3899f8dSAtsushi Murai #ifdef SIGTTIN
370bbea88d0SAndrey A. Chernov       signal(SIGTTIN, TerminalStop);
371c3899f8dSAtsushi Murai #endif
372c3899f8dSAtsushi Murai #ifdef SIGTTOU
373bbea88d0SAndrey A. Chernov       signal(SIGTTOU, SIG_IGN);
374c3899f8dSAtsushi Murai #endif
375c3899f8dSAtsushi Murai     }
376af57ed9fSAtsushi Murai 
377af57ed9fSAtsushi Murai   if (dstsystem) {
378af57ed9fSAtsushi Murai     if (SelectSystem(dstsystem, CONFFILE) < 0) {
379af57ed9fSAtsushi Murai       fprintf(stderr, "Destination system not found in conf file.\n");
380af57ed9fSAtsushi Murai       Cleanup(EX_START);
381af57ed9fSAtsushi Murai     }
382af57ed9fSAtsushi Murai     if ((mode & MODE_AUTO) && DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
383680026d6SNate Williams       fprintf(stderr, "Must specify dstaddr with auto or ddial mode.\n");
384af57ed9fSAtsushi Murai       Cleanup(EX_START);
385af57ed9fSAtsushi Murai     }
386af57ed9fSAtsushi Murai   }
387af57ed9fSAtsushi Murai   if (mode & MODE_DIRECT)
388af57ed9fSAtsushi Murai     printf("Packet mode enabled.\n");
389af57ed9fSAtsushi Murai 
390af57ed9fSAtsushi Murai #ifdef notdef
391af57ed9fSAtsushi Murai   if (mode & MODE_AUTO) {
392af57ed9fSAtsushi Murai     OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr, ifnetmask);
393af57ed9fSAtsushi Murai   }
394af57ed9fSAtsushi Murai #endif
395af57ed9fSAtsushi Murai 
396af57ed9fSAtsushi Murai   if (!(mode & MODE_INTER)) {
397af57ed9fSAtsushi Murai     int port = SERVER_PORT + tunno;
3986d14e2a8SJordan K. Hubbard     if (mode & MODE_BACKGROUND) {
3996d14e2a8SJordan K. Hubbard       if (pipe (BGFiledes)) {
4006d14e2a8SJordan K. Hubbard 	perror("pipe");
4016d14e2a8SJordan K. Hubbard 	Cleanup(EX_SOCK);
4026d14e2a8SJordan K. Hubbard       }
4036d14e2a8SJordan K. Hubbard     }
4046d14e2a8SJordan K. Hubbard     else {
405af57ed9fSAtsushi Murai       /*
406af57ed9fSAtsushi Murai        *  Create server socket and listen at there.
407af57ed9fSAtsushi Murai        */
408af57ed9fSAtsushi Murai       server = socket(PF_INET, SOCK_STREAM, 0);
409af57ed9fSAtsushi Murai       if (server < 0) {
410af57ed9fSAtsushi Murai 	perror("socket");
411af57ed9fSAtsushi Murai 	Cleanup(EX_SOCK);
412af57ed9fSAtsushi Murai       }
413af57ed9fSAtsushi Murai       ifsin.sin_family = AF_INET;
414af57ed9fSAtsushi Murai       ifsin.sin_addr.s_addr = INADDR_ANY;
415af57ed9fSAtsushi Murai       ifsin.sin_port = htons(port);
416af57ed9fSAtsushi Murai       if (bind(server, (struct sockaddr *) &ifsin, sizeof(ifsin)) < 0) {
417af57ed9fSAtsushi Murai 	perror("bind");
418af57ed9fSAtsushi Murai 	if (errno == EADDRINUSE)
419af57ed9fSAtsushi Murai 	  fprintf(stderr, "Wait for a while, then try again.\n");
420af57ed9fSAtsushi Murai 	Cleanup(EX_SOCK);
421af57ed9fSAtsushi Murai       }
422af57ed9fSAtsushi Murai       listen(server, 5);
4236d14e2a8SJordan K. Hubbard     }
424af57ed9fSAtsushi Murai 
425af57ed9fSAtsushi Murai     DupLog();
426af57ed9fSAtsushi Murai     if (!(mode & MODE_DIRECT)) {
427a9c6b5dfSAtsushi Murai       int fd;
428a9c6b5dfSAtsushi Murai       char pid[32];
4296d14e2a8SJordan K. Hubbard       pid_t bgpid;
430a9c6b5dfSAtsushi Murai 
4316d14e2a8SJordan K. Hubbard       bgpid = fork ();
4326d14e2a8SJordan K. Hubbard       if (bgpid == -1) {
4336d14e2a8SJordan K. Hubbard 	perror ("fork");
4346d14e2a8SJordan K. Hubbard 	Cleanup (EX_SOCK);
4356d14e2a8SJordan K. Hubbard       }
4366d14e2a8SJordan K. Hubbard       if (bgpid) {
4376d14e2a8SJordan K. Hubbard 	char c = EX_NORMAL;
438a9c6b5dfSAtsushi Murai 
4396d14e2a8SJordan K. Hubbard 	if (mode & MODE_BACKGROUND) {
4406d14e2a8SJordan K. Hubbard 	  /* Wait for our child to close its pipe before we exit. */
4416d14e2a8SJordan K. Hubbard 	  BGPid = bgpid;
4426d14e2a8SJordan K. Hubbard 	  read (BGFiledes[0], &c, 1);
4436d14e2a8SJordan K. Hubbard 	  if (c == EX_NORMAL)
4446d14e2a8SJordan K. Hubbard 	    LogPrintf (LOG_CHAT, "PPP enabled.\n");
4456d14e2a8SJordan K. Hubbard 	}
4466d14e2a8SJordan K. Hubbard         exit(c);
4476d14e2a8SJordan K. Hubbard       }
4486d14e2a8SJordan K. Hubbard 
4496d14e2a8SJordan K. Hubbard       snprintf(pid_filename, sizeof (pid_filename), "%s/ppp.tun%d.pid",
4506d14e2a8SJordan K. Hubbard 		  _PATH_VARRUN, tunno);
451a9c6b5dfSAtsushi Murai       unlink(pid_filename);
45299c02d39SWarner Losh       snprintf(pid, sizeof(pid), "%d\n", (int)getpid());
453a9c6b5dfSAtsushi Murai 
454a9c6b5dfSAtsushi Murai       if ((fd = open(pid_filename, O_RDWR|O_CREAT, 0666)) != -1)
455a9c6b5dfSAtsushi Murai       {
456a9c6b5dfSAtsushi Murai 	  write(fd, pid, strlen(pid));
457a9c6b5dfSAtsushi Murai 	  close(fd);
458a9c6b5dfSAtsushi Murai       }
459af57ed9fSAtsushi Murai     }
460780700e5SAndrey A. Chernov     if (server >= 0)
4619c749ffbSPoul-Henning Kamp 	LogPrintf(LOG_PHASE_BIT, "Listening at %d.\n", port);
462af57ed9fSAtsushi Murai #ifdef DOTTYINIT
46353c9f6c0SAtsushi Murai     if (mode & (MODE_DIRECT|MODE_DEDICATED)) { /* } */
464af57ed9fSAtsushi Murai #else
465af57ed9fSAtsushi Murai     if (mode & MODE_DIRECT) {
466af57ed9fSAtsushi Murai #endif
467af57ed9fSAtsushi Murai       TtyInit();
468af57ed9fSAtsushi Murai     } else {
469d91680eaSAndrey A. Chernov       int fd;
470d91680eaSAndrey A. Chernov 
471af57ed9fSAtsushi Murai       setsid();			/* detach control tty */
472d91680eaSAndrey A. Chernov       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
473d91680eaSAndrey A. Chernov 	(void)dup2(fd, STDIN_FILENO);
474d91680eaSAndrey A. Chernov 	(void)dup2(fd, STDOUT_FILENO);
475d91680eaSAndrey A. Chernov 	(void)dup2(fd, STDERR_FILENO);
476d91680eaSAndrey A. Chernov 	if (fd > 2)
477d91680eaSAndrey A. Chernov 		(void)close (fd);
478d91680eaSAndrey A. Chernov       }
479af57ed9fSAtsushi Murai     }
480af57ed9fSAtsushi Murai   } else {
481af57ed9fSAtsushi Murai     TtyInit();
482c3899f8dSAtsushi Murai     TtyCommandMode(1);
483af57ed9fSAtsushi Murai   }
4849c749ffbSPoul-Henning Kamp   LogPrintf(LOG_PHASE_BIT, "PPP Started.\n");
485af57ed9fSAtsushi Murai 
486af57ed9fSAtsushi Murai 
487af57ed9fSAtsushi Murai   do
488af57ed9fSAtsushi Murai    DoLoop();
489af57ed9fSAtsushi Murai   while (mode & MODE_DEDICATED);
490af57ed9fSAtsushi Murai 
491af57ed9fSAtsushi Murai   Cleanup(EX_DONE);
492af57ed9fSAtsushi Murai }
493af57ed9fSAtsushi Murai 
494af57ed9fSAtsushi Murai /*
4956d14e2a8SJordan K. Hubbard  *  Turn into packet mode, where we speak PPP.
496af57ed9fSAtsushi Murai  */
497af57ed9fSAtsushi Murai void
498af57ed9fSAtsushi Murai PacketMode()
499af57ed9fSAtsushi Murai {
500af57ed9fSAtsushi Murai   if (RawModem(modem) < 0) {
501af57ed9fSAtsushi Murai     fprintf(stderr, "Not connected.\r\n");
502af57ed9fSAtsushi Murai     return;
503af57ed9fSAtsushi Murai   }
504af57ed9fSAtsushi Murai 
505af57ed9fSAtsushi Murai   AsyncInit();
506af57ed9fSAtsushi Murai   VjInit();
507af57ed9fSAtsushi Murai   LcpInit();
508af57ed9fSAtsushi Murai   IpcpInit();
509af57ed9fSAtsushi Murai   CcpInit();
510af57ed9fSAtsushi Murai   LcpUp();
511af57ed9fSAtsushi Murai 
512af57ed9fSAtsushi Murai   if (mode & (MODE_DIRECT|MODE_DEDICATED))
513af57ed9fSAtsushi Murai     LcpOpen(OPEN_ACTIVE);
514af57ed9fSAtsushi Murai   else
515af57ed9fSAtsushi Murai     LcpOpen(VarOpenMode);
516af57ed9fSAtsushi Murai   if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) {
517c3899f8dSAtsushi Murai     TtyCommandMode(1);
518af57ed9fSAtsushi Murai     fprintf(stderr, "Packet mode.\r\n");
519b0cdb3ceSJordan K. Hubbard     aft_cmd = 1;
520af57ed9fSAtsushi Murai   }
521af57ed9fSAtsushi Murai }
522af57ed9fSAtsushi Murai 
523af57ed9fSAtsushi Murai static void
524af57ed9fSAtsushi Murai ShowHelp()
525af57ed9fSAtsushi Murai {
526c3899f8dSAtsushi Murai   fprintf(stderr, "The following commands are available:\r\n");
527af57ed9fSAtsushi Murai   fprintf(stderr, " ~p\tEnter to Packet mode\r\n");
5281dff3fc5SAndrey A. Chernov   fprintf(stderr, " ~-\tDecrease log level\r\n");
5291dff3fc5SAndrey A. Chernov   fprintf(stderr, " ~+\tIncrease log level\r\n");
530af57ed9fSAtsushi Murai   fprintf(stderr, " ~.\tTerminate program\r\n");
5311dff3fc5SAndrey A. Chernov   fprintf(stderr, " ~?\tThis help\r\n");
532af57ed9fSAtsushi Murai }
533af57ed9fSAtsushi Murai 
534af57ed9fSAtsushi Murai static void
535af57ed9fSAtsushi Murai ReadTty()
536af57ed9fSAtsushi Murai {
537af57ed9fSAtsushi Murai   int n;
538af57ed9fSAtsushi Murai   char ch;
539af57ed9fSAtsushi Murai   static int ttystate;
540af57ed9fSAtsushi Murai #define MAXLINESIZE 200
541af57ed9fSAtsushi Murai   char linebuff[MAXLINESIZE];
542af57ed9fSAtsushi Murai 
543af57ed9fSAtsushi Murai #ifdef DEBUG
544af57ed9fSAtsushi Murai   logprintf("termode = %d, netfd = %d, mode = %d\n", TermMode, netfd, mode);
545af57ed9fSAtsushi Murai #endif
546af57ed9fSAtsushi Murai   if (!TermMode) {
547af57ed9fSAtsushi Murai     n = read(netfd, linebuff, sizeof(linebuff)-1);
548b0cdb3ceSJordan K. Hubbard     aft_cmd = 1;
54953c9f6c0SAtsushi Murai     if (n > 0) {
550af57ed9fSAtsushi Murai       DecodeCommand(linebuff, n, 1);
55153c9f6c0SAtsushi Murai     } else {
552af57ed9fSAtsushi Murai #ifdef DEBUG
553af57ed9fSAtsushi Murai       logprintf("connection closed.\n");
554af57ed9fSAtsushi Murai #endif
555af57ed9fSAtsushi Murai       close(netfd);
556af57ed9fSAtsushi Murai       netfd = -1;
557af57ed9fSAtsushi Murai       mode &= ~MODE_INTER;
558af57ed9fSAtsushi Murai     }
559af57ed9fSAtsushi Murai     return;
560af57ed9fSAtsushi Murai   }
561af57ed9fSAtsushi Murai 
562af57ed9fSAtsushi Murai   /*
563af57ed9fSAtsushi Murai    *  We are in terminal mode, decode special sequences
564af57ed9fSAtsushi Murai    */
565af57ed9fSAtsushi Murai   n = read(0, &ch, 1);
566af57ed9fSAtsushi Murai #ifdef DEBUG
567af57ed9fSAtsushi Murai   logprintf("got %d bytes\n", n);
568af57ed9fSAtsushi Murai #endif
569af57ed9fSAtsushi Murai 
570af57ed9fSAtsushi Murai   if (n > 0) {
571af57ed9fSAtsushi Murai     switch (ttystate) {
572af57ed9fSAtsushi Murai     case 0:
573af57ed9fSAtsushi Murai       if (ch == '~')
574af57ed9fSAtsushi Murai 	ttystate++;
575af57ed9fSAtsushi Murai       else
576af57ed9fSAtsushi Murai 	write(modem, &ch, n);
577af57ed9fSAtsushi Murai       break;
578af57ed9fSAtsushi Murai     case 1:
579af57ed9fSAtsushi Murai       switch (ch) {
580af57ed9fSAtsushi Murai       case '?':
581af57ed9fSAtsushi Murai 	ShowHelp();
582af57ed9fSAtsushi Murai 	break;
583af57ed9fSAtsushi Murai       case '-':
584af57ed9fSAtsushi Murai 	if (loglevel > 0) {
585af57ed9fSAtsushi Murai 	  loglevel--;
586af57ed9fSAtsushi Murai 	  fprintf(stderr, "New loglevel is %d\r\n", loglevel);
587af57ed9fSAtsushi Murai 	}
588af57ed9fSAtsushi Murai 	break;
589af57ed9fSAtsushi Murai       case '+':
590af57ed9fSAtsushi Murai 	loglevel++;
591af57ed9fSAtsushi Murai 	fprintf(stderr, "New loglevel is %d\r\n", loglevel);
592af57ed9fSAtsushi Murai 	break;
593af57ed9fSAtsushi Murai #ifdef DEBUG
594af57ed9fSAtsushi Murai       case 'm':
595af57ed9fSAtsushi Murai 	ShowMemMap();
596af57ed9fSAtsushi Murai 	break;
597af57ed9fSAtsushi Murai #endif
598af57ed9fSAtsushi Murai       case 'p':
599af57ed9fSAtsushi Murai 	/*
600af57ed9fSAtsushi Murai 	 * XXX: Should check carrier.
601af57ed9fSAtsushi Murai 	 */
602af57ed9fSAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED) {
603af57ed9fSAtsushi Murai 	  VarOpenMode = OPEN_ACTIVE;
604af57ed9fSAtsushi Murai 	  PacketMode();
605af57ed9fSAtsushi Murai 	}
606af57ed9fSAtsushi Murai 	break;
607af57ed9fSAtsushi Murai #ifdef DEBUG
608af57ed9fSAtsushi Murai       case 't':
609af57ed9fSAtsushi Murai 	ShowTimers();
610af57ed9fSAtsushi Murai 	break;
611af57ed9fSAtsushi Murai #endif
612af57ed9fSAtsushi Murai       case '.':
613af57ed9fSAtsushi Murai 	TermMode = 1;
614c3899f8dSAtsushi Murai 	TtyCommandMode(1);
615af57ed9fSAtsushi Murai 	break;
616af57ed9fSAtsushi Murai       default:
617af57ed9fSAtsushi Murai 	if (write(modem, &ch, n) < 0)
618af57ed9fSAtsushi Murai 	  fprintf(stderr, "err in write.\r\n");
619af57ed9fSAtsushi Murai 	break;
620af57ed9fSAtsushi Murai       }
621af57ed9fSAtsushi Murai       ttystate = 0;
622af57ed9fSAtsushi Murai       break;
623af57ed9fSAtsushi Murai     }
624af57ed9fSAtsushi Murai   }
625af57ed9fSAtsushi Murai }
626af57ed9fSAtsushi Murai 
627af57ed9fSAtsushi Murai 
628af57ed9fSAtsushi Murai /*
629af57ed9fSAtsushi Murai  *  Here, we'll try to detect HDLC frame
630af57ed9fSAtsushi Murai  */
631af57ed9fSAtsushi Murai 
632af57ed9fSAtsushi Murai static char *FrameHeaders[] = {
63353c9f6c0SAtsushi Murai   "\176\377\003\300\041",
63453c9f6c0SAtsushi Murai   "\176\377\175\043\300\041",
63553c9f6c0SAtsushi Murai   "\176\177\175\043\100\041",
63653c9f6c0SAtsushi Murai   "\176\175\337\175\043\300\041",
63753c9f6c0SAtsushi Murai   "\176\175\137\175\043\100\041",
638af57ed9fSAtsushi Murai   NULL,
639af57ed9fSAtsushi Murai };
640af57ed9fSAtsushi Murai 
641af57ed9fSAtsushi Murai u_char *
642af57ed9fSAtsushi Murai HdlcDetect(cp, n)
643af57ed9fSAtsushi Murai u_char *cp;
644af57ed9fSAtsushi Murai int n;
645af57ed9fSAtsushi Murai {
64653c9f6c0SAtsushi Murai   char *ptr, *fp, **hp;
647af57ed9fSAtsushi Murai 
648af57ed9fSAtsushi Murai   cp[n] = '\0';	/* be sure to null terminated */
649af57ed9fSAtsushi Murai   ptr = NULL;
650af57ed9fSAtsushi Murai   for (hp = FrameHeaders; *hp; hp++) {
65153c9f6c0SAtsushi Murai     fp = *hp;
65253c9f6c0SAtsushi Murai     if (DEV_IS_SYNC)
65353c9f6c0SAtsushi Murai       fp++;
654ed6a16c1SPoul-Henning Kamp     ptr = strstr((char *)cp, fp);
655ed6a16c1SPoul-Henning Kamp     if (ptr)
656af57ed9fSAtsushi Murai       break;
657af57ed9fSAtsushi Murai   }
658af57ed9fSAtsushi Murai   return((u_char *)ptr);
659af57ed9fSAtsushi Murai }
660af57ed9fSAtsushi Murai 
661af57ed9fSAtsushi Murai static struct pppTimer RedialTimer;
662af57ed9fSAtsushi Murai 
663af57ed9fSAtsushi Murai static void
664af57ed9fSAtsushi Murai RedialTimeout()
665af57ed9fSAtsushi Murai {
666af57ed9fSAtsushi Murai   StopTimer(&RedialTimer);
6679c749ffbSPoul-Henning Kamp   LogPrintf(LOG_PHASE_BIT, "Redialing timer expired.\n");
668af57ed9fSAtsushi Murai }
669af57ed9fSAtsushi Murai 
670af57ed9fSAtsushi Murai static void
671af57ed9fSAtsushi Murai StartRedialTimer()
672af57ed9fSAtsushi Murai {
673af57ed9fSAtsushi Murai   StopTimer(&RedialTimer);
674a9c6b5dfSAtsushi Murai 
675a9c6b5dfSAtsushi Murai   if (VarRedialTimeout) {
6769c749ffbSPoul-Henning Kamp     LogPrintf(LOG_PHASE_BIT, "Enter pause for redialing.\n");
677af57ed9fSAtsushi Murai     RedialTimer.state = TIMER_STOPPED;
678a9c6b5dfSAtsushi Murai 
679a9c6b5dfSAtsushi Murai     if (VarRedialTimeout > 0)
680a9c6b5dfSAtsushi Murai 	RedialTimer.load = VarRedialTimeout * SECTICKS;
681a9c6b5dfSAtsushi Murai     else
682a9c6b5dfSAtsushi Murai 	RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
683a9c6b5dfSAtsushi Murai 
684af57ed9fSAtsushi Murai     RedialTimer.func = RedialTimeout;
685af57ed9fSAtsushi Murai     StartTimer(&RedialTimer);
686af57ed9fSAtsushi Murai   }
687a9c6b5dfSAtsushi Murai }
688af57ed9fSAtsushi Murai 
689af57ed9fSAtsushi Murai 
690af57ed9fSAtsushi Murai static void
691af57ed9fSAtsushi Murai DoLoop()
692af57ed9fSAtsushi Murai {
693af57ed9fSAtsushi Murai   fd_set rfds, wfds, efds;
694780700e5SAndrey A. Chernov   int pri, i, n, wfd, nfds;
695af57ed9fSAtsushi Murai   struct sockaddr_in hisaddr;
696af57ed9fSAtsushi Murai   struct timeval timeout, *tp;
697af57ed9fSAtsushi Murai   int ssize = sizeof(hisaddr);
698af57ed9fSAtsushi Murai   u_char *cp;
699af57ed9fSAtsushi Murai   u_char rbuff[MAX_MRU];
70084b8a6ebSAtsushi Murai   int dial_up;
701a9c6b5dfSAtsushi Murai   int tries;
70260e218e4SAtsushi Murai   int qlen;
703c3899f8dSAtsushi Murai   pid_t pgroup;
704c3899f8dSAtsushi Murai 
705c3899f8dSAtsushi Murai   pgroup = getpgrp();
706af57ed9fSAtsushi Murai 
707af57ed9fSAtsushi Murai   if (mode & MODE_DIRECT) {
708af57ed9fSAtsushi Murai     modem = OpenModem(mode);
7099c749ffbSPoul-Henning Kamp     LogPrintf(LOG_PHASE_BIT, "Packet mode enabled\n");
710b0cdb3ceSJordan K. Hubbard     fflush(stderr);
711af57ed9fSAtsushi Murai     PacketMode();
712af57ed9fSAtsushi Murai   } else if (mode & MODE_DEDICATED) {
713780700e5SAndrey A. Chernov     if (modem < 0)
714af57ed9fSAtsushi Murai       modem = OpenModem(mode);
715af57ed9fSAtsushi Murai   }
716af57ed9fSAtsushi Murai 
717af57ed9fSAtsushi Murai   fflush(stdout);
718af57ed9fSAtsushi Murai 
71984b8a6ebSAtsushi Murai   timeout.tv_sec = 0;
720af57ed9fSAtsushi Murai   timeout.tv_usec = 0;
721af57ed9fSAtsushi Murai 
72284b8a6ebSAtsushi Murai   dial_up = FALSE;			/* XXXX */
723a9c6b5dfSAtsushi Murai   tries = 0;
724af57ed9fSAtsushi Murai   for (;;) {
725780700e5SAndrey A. Chernov     nfds = 0;
726af57ed9fSAtsushi Murai     FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
72784b8a6ebSAtsushi Murai 
72884b8a6ebSAtsushi Murai     /*
729680026d6SNate Williams      * If the link is down and we're in DDIAL mode, bring it back
730680026d6SNate Williams      * up.
731680026d6SNate Williams      */
732680026d6SNate Williams     if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
733680026d6SNate Williams         dial_up = TRUE;
734680026d6SNate Williams 
735680026d6SNate Williams    /*
73684b8a6ebSAtsushi Murai     * If Ip packet for output is enqueued and require dial up,
73784b8a6ebSAtsushi Murai     * Just do it!
73884b8a6ebSAtsushi Murai     */
73984b8a6ebSAtsushi Murai     if ( dial_up && RedialTimer.state != TIMER_RUNNING ) { /* XXX */
74084b8a6ebSAtsushi Murai #ifdef DEBUG
74184b8a6ebSAtsushi Murai       logprintf("going to dial: modem = %d\n", modem);
74284b8a6ebSAtsushi Murai #endif
74384b8a6ebSAtsushi Murai       modem = OpenModem(mode);
74484b8a6ebSAtsushi Murai       if (modem < 0) {
74584b8a6ebSAtsushi Murai 	StartRedialTimer();
74684b8a6ebSAtsushi Murai       } else {
747a9c6b5dfSAtsushi Murai 	tries++;
7489c749ffbSPoul-Henning Kamp 	LogPrintf(LOG_CHAT_BIT, "Dial attempt %u\n", tries);
74984b8a6ebSAtsushi Murai 	if (DialModem()) {
75084b8a6ebSAtsushi Murai 	  sleep(1);	       /* little pause to allow peer starts */
75184b8a6ebSAtsushi Murai 	  ModemTimeout();
75284b8a6ebSAtsushi Murai 	  PacketMode();
75384b8a6ebSAtsushi Murai 	  dial_up = FALSE;
754a9c6b5dfSAtsushi Murai 	  tries = 0;
75584b8a6ebSAtsushi Murai 	} else {
75684b8a6ebSAtsushi Murai 	  CloseModem();
75784b8a6ebSAtsushi Murai 	  /* Dial failed. Keep quite during redial wait period. */
75884b8a6ebSAtsushi Murai 	  StartRedialTimer();
759a9c6b5dfSAtsushi Murai 
760a9c6b5dfSAtsushi Murai 	  if (VarDialTries && tries >= VarDialTries) {
761a9c6b5dfSAtsushi Murai 	      dial_up = FALSE;
762a9c6b5dfSAtsushi Murai 	      tries = 0;
763a9c6b5dfSAtsushi Murai 	  }
76484b8a6ebSAtsushi Murai 	}
76584b8a6ebSAtsushi Murai       }
76684b8a6ebSAtsushi Murai     }
76760e218e4SAtsushi Murai     qlen = ModemQlen();
76876bd0c0aSDoug Rabson 
76976bd0c0aSDoug Rabson     if (qlen == 0) {
77076bd0c0aSDoug Rabson       IpStartOutput();
77176bd0c0aSDoug Rabson       qlen = ModemQlen();
77276bd0c0aSDoug Rabson     }
77376bd0c0aSDoug Rabson 
774780700e5SAndrey A. Chernov     if (modem >= 0) {
775780700e5SAndrey A. Chernov       if (modem + 1 > nfds)
776780700e5SAndrey A. Chernov 	nfds = modem + 1;
77784b8a6ebSAtsushi Murai       FD_SET(modem, &rfds);
77884b8a6ebSAtsushi Murai       FD_SET(modem, &efds);
77960e218e4SAtsushi Murai       if (qlen > 0) {
78084b8a6ebSAtsushi Murai 	FD_SET(modem, &wfds);
78184b8a6ebSAtsushi Murai       }
78284b8a6ebSAtsushi Murai     }
783780700e5SAndrey A. Chernov     if (server >= 0) {
784780700e5SAndrey A. Chernov       if (server + 1 > nfds)
785780700e5SAndrey A. Chernov 	nfds = server + 1;
786780700e5SAndrey A. Chernov       FD_SET(server, &rfds);
787780700e5SAndrey A. Chernov     }
788af57ed9fSAtsushi Murai 
789af57ed9fSAtsushi Murai     /*  *** IMPORTANT ***
790af57ed9fSAtsushi Murai      *
791af57ed9fSAtsushi Murai      *  CPU is serviced every TICKUNIT micro seconds.
792af57ed9fSAtsushi Murai      *	This value must be chosen with great care. If this values is
793af57ed9fSAtsushi Murai      *  too big, it results loss of characters from modem and poor responce.
794af57ed9fSAtsushi Murai      *  If this values is too small, ppp process eats many CPU time.
795af57ed9fSAtsushi Murai      */
79653c9f6c0SAtsushi Murai #ifndef SIGALRM
797af57ed9fSAtsushi Murai     usleep(TICKUNIT);
798af57ed9fSAtsushi Murai     TimerService();
79953c9f6c0SAtsushi Murai #endif
80068d2b4d6SBruce Evans 
80168d2b4d6SBruce Evans     /* If there are aren't many packets queued, look for some more. */
802780700e5SAndrey A. Chernov     if (qlen < 20 && tun_in >= 0) {
803780700e5SAndrey A. Chernov       if (tun_in + 1 > nfds)
804780700e5SAndrey A. Chernov 	nfds = tun_in + 1;
80584b8a6ebSAtsushi Murai       FD_SET(tun_in, &rfds);
806780700e5SAndrey A. Chernov     }
80768d2b4d6SBruce Evans 
808780700e5SAndrey A. Chernov     if (netfd >= 0) {
809780700e5SAndrey A. Chernov       if (netfd + 1 > nfds)
810780700e5SAndrey A. Chernov 	nfds = netfd + 1;
811af57ed9fSAtsushi Murai       FD_SET(netfd, &rfds);
812af57ed9fSAtsushi Murai       FD_SET(netfd, &efds);
813af57ed9fSAtsushi Murai     }
81484b8a6ebSAtsushi Murai 
81553c9f6c0SAtsushi Murai #ifndef SIGALRM
816af57ed9fSAtsushi Murai     /*
81784b8a6ebSAtsushi Murai      *  Normally, select() will not block because modem is writable.
81884b8a6ebSAtsushi Murai      *  In AUTO mode, select will block until we find packet from tun
819af57ed9fSAtsushi Murai      */
820af57ed9fSAtsushi Murai     tp = (RedialTimer.state == TIMER_RUNNING)? &timeout : NULL;
821780700e5SAndrey A. Chernov     i = select(nfds, &rfds, &wfds, &efds, tp);
82253c9f6c0SAtsushi Murai #else
82384b8a6ebSAtsushi Murai     /*
82484b8a6ebSAtsushi Murai      * When SIGALRM timer is running, a select function will be
82584b8a6ebSAtsushi Murai      * return -1 and EINTR after a Time Service signal hundler
826a9c6b5dfSAtsushi Murai      * is done.  If the redial timer is not running and we are
827a9c6b5dfSAtsushi Murai      * trying to dial, poll with a 0 value timer.
82884b8a6ebSAtsushi Murai      */
829a9c6b5dfSAtsushi Murai     tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
830780700e5SAndrey A. Chernov     i = select(nfds, &rfds, &wfds, &efds, tp);
83153c9f6c0SAtsushi Murai #endif
8326b0b88d8SBrian Somers 
833af57ed9fSAtsushi Murai     if ( i == 0 ) {
834af57ed9fSAtsushi Murai         continue;
835af57ed9fSAtsushi Murai     }
83653c9f6c0SAtsushi Murai 
837534fe541SBrian Somers     if ( i < 0 ) {
838534fe541SBrian Somers        if ( errno == EINTR ) {
839bbea88d0SAndrey A. Chernov           continue;            /* Got a signal - should have been dealt with */
84084b8a6ebSAtsushi Murai        }
841af57ed9fSAtsushi Murai        perror("select");
842af57ed9fSAtsushi Murai        break;
843af57ed9fSAtsushi Murai     }
84484b8a6ebSAtsushi Murai 
845780700e5SAndrey A. Chernov     if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
846af57ed9fSAtsushi Murai       logprintf("Exception detected.\n");
847af57ed9fSAtsushi Murai       break;
848af57ed9fSAtsushi Murai     }
849af57ed9fSAtsushi Murai 
850780700e5SAndrey A. Chernov     if (server >= 0 && FD_ISSET(server, &rfds)) {
851af57ed9fSAtsushi Murai #ifdef DEBUG
852af57ed9fSAtsushi Murai       logprintf("connected to client.\n");
853af57ed9fSAtsushi Murai #endif
854af57ed9fSAtsushi Murai       wfd = accept(server, (struct sockaddr *)&hisaddr, &ssize);
855780700e5SAndrey A. Chernov       if (netfd >= 0) {
856af57ed9fSAtsushi Murai 	write(wfd, "already in use.\n", 16);
857af57ed9fSAtsushi Murai 	close(wfd);
858af57ed9fSAtsushi Murai 	continue;
859af57ed9fSAtsushi Murai       } else
860af57ed9fSAtsushi Murai 	netfd = wfd;
861af57ed9fSAtsushi Murai       if (dup2(netfd, 1) < 0)
862af57ed9fSAtsushi Murai 	perror("dup2");
863af57ed9fSAtsushi Murai       mode |= MODE_INTER;
864af57ed9fSAtsushi Murai       Greetings();
86541db6564SAtsushi Murai       switch ( LocalAuthInit() ) {
86641db6564SAtsushi Murai          case NOT_FOUND:
86741db6564SAtsushi Murai     	    fprintf(stdout,LAUTH_M1);
86841db6564SAtsushi Murai     	    fprintf(stdout,LAUTH_M2);
86941db6564SAtsushi Murai             fflush(stdout);
87041db6564SAtsushi Murai 	    /* Fall down */
87141db6564SAtsushi Murai          case VALID:
87241db6564SAtsushi Murai 	    VarLocalAuth = LOCAL_AUTH;
87341db6564SAtsushi Murai 	    break;
87441db6564SAtsushi Murai          default:
87541db6564SAtsushi Murai 	    break;
87641db6564SAtsushi Murai       }
877af57ed9fSAtsushi Murai       (void) IsInteractive();
878af57ed9fSAtsushi Murai       Prompt(0);
879af57ed9fSAtsushi Murai     }
880af57ed9fSAtsushi Murai 
881780700e5SAndrey A. Chernov     if ((mode & MODE_INTER) && (netfd >= 0 && FD_ISSET(netfd, &rfds)) &&
882f1884650SAtsushi Murai 	((mode & MODE_AUTO) || pgroup == tcgetpgrp(0))) {
883af57ed9fSAtsushi Murai       /* something to read from tty */
884af57ed9fSAtsushi Murai       ReadTty();
885af57ed9fSAtsushi Murai     }
886780700e5SAndrey A. Chernov     if (modem >= 0) {
887af57ed9fSAtsushi Murai       if (FD_ISSET(modem, &wfds)) {	/* ready to write into modem */
888af57ed9fSAtsushi Murai 	 ModemStartOutput(modem);
889af57ed9fSAtsushi Murai       }
890af57ed9fSAtsushi Murai       if (FD_ISSET(modem, &rfds)) {	/* something to read from modem */
89153c9f6c0SAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED)
89253c9f6c0SAtsushi Murai 	  usleep(10000);
893af57ed9fSAtsushi Murai 	n = read(modem, rbuff, sizeof(rbuff));
894af57ed9fSAtsushi Murai 	if ((mode & MODE_DIRECT) && n <= 0) {
895af57ed9fSAtsushi Murai 	  DownConnection();
896af57ed9fSAtsushi Murai 	} else
897af57ed9fSAtsushi Murai           LogDumpBuff(LOG_ASYNC, "ReadFromModem", rbuff, n);
898af57ed9fSAtsushi Murai 
899af57ed9fSAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED) {
900af57ed9fSAtsushi Murai 	  /*
901af57ed9fSAtsushi Murai 	   *  In dedicated mode, we just discard input until LCP is started.
902af57ed9fSAtsushi Murai 	   */
903af57ed9fSAtsushi Murai 	  if (!(mode & MODE_DEDICATED)) {
904af57ed9fSAtsushi Murai 	    cp = HdlcDetect(rbuff, n);
905af57ed9fSAtsushi Murai 	    if (cp) {
906af57ed9fSAtsushi Murai 	      /*
907af57ed9fSAtsushi Murai 	       * LCP packet is detected. Turn ourselves into packet mode.
908af57ed9fSAtsushi Murai 	       */
909af57ed9fSAtsushi Murai 	      if (cp != rbuff) {
910af57ed9fSAtsushi Murai 	        write(1, rbuff, cp - rbuff);
911af57ed9fSAtsushi Murai 	        write(1, "\r\n", 2);
912af57ed9fSAtsushi Murai 	      }
913af57ed9fSAtsushi Murai 	      PacketMode();
914af57ed9fSAtsushi Murai #ifdef notdef
915af57ed9fSAtsushi Murai 	      AsyncInput(cp, n - (cp - rbuff));
916af57ed9fSAtsushi Murai #endif
917af57ed9fSAtsushi Murai 	    } else
918af57ed9fSAtsushi Murai 	      write(1, rbuff, n);
919af57ed9fSAtsushi Murai 	  }
920af57ed9fSAtsushi Murai 	} else {
921af57ed9fSAtsushi Murai 	  if (n > 0)
922af57ed9fSAtsushi Murai 	    AsyncInput(rbuff, n);
923af57ed9fSAtsushi Murai #ifdef notdef
924af57ed9fSAtsushi Murai 	  continue;			/* THIS LINE RESULT AS POOR PERFORMANCE */
925af57ed9fSAtsushi Murai #endif
926af57ed9fSAtsushi Murai 	}
927af57ed9fSAtsushi Murai       }
928af57ed9fSAtsushi Murai     }
92984b8a6ebSAtsushi Murai 
930780700e5SAndrey A. Chernov     if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {       /* something to read from tun */
931af57ed9fSAtsushi Murai       n = read(tun_in, rbuff, sizeof(rbuff));
932af57ed9fSAtsushi Murai       if (n < 0) {
933af57ed9fSAtsushi Murai 	perror("read from tun");
934af57ed9fSAtsushi Murai 	continue;
935af57ed9fSAtsushi Murai       }
936af57ed9fSAtsushi Murai       /*
937af57ed9fSAtsushi Murai        *  Process on-demand dialup. Output packets are queued within tunnel
938af57ed9fSAtsushi Murai        *  device until IPCP is opened.
939af57ed9fSAtsushi Murai        */
940af57ed9fSAtsushi Murai       if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO)) {
94184b8a6ebSAtsushi Murai 	pri = PacketCheck(rbuff, n, FL_DIAL);
942af57ed9fSAtsushi Murai 	if (pri >= 0) {
943a9f484e5SJordan K. Hubbard 	  if (mode & MODE_ALIAS) {
9443b92d2deSNate Williams 	    PacketAliasOut((struct ip *)rbuff);
945a9f484e5SJordan K. Hubbard 	    n = ntohs(((struct ip *)rbuff)->ip_len);
946a9f484e5SJordan K. Hubbard 	  }
947af57ed9fSAtsushi Murai 	  IpEnqueue(pri, rbuff, n);
94884b8a6ebSAtsushi Murai 	  dial_up = TRUE;		/* XXX */
949af57ed9fSAtsushi Murai 	}
950af57ed9fSAtsushi Murai 	continue;
951af57ed9fSAtsushi Murai       }
95284b8a6ebSAtsushi Murai       pri = PacketCheck(rbuff, n, FL_OUT);
953a9f484e5SJordan K. Hubbard       if (pri >= 0) {
954a9f484e5SJordan K. Hubbard         if (mode & MODE_ALIAS) {
9553b92d2deSNate Williams           PacketAliasOut((struct ip *)rbuff);
956a9f484e5SJordan K. Hubbard           n = ntohs(((struct ip *)rbuff)->ip_len);
957a9f484e5SJordan K. Hubbard         }
958af57ed9fSAtsushi Murai 	IpEnqueue(pri, rbuff, n);
959af57ed9fSAtsushi Murai       }
960af57ed9fSAtsushi Murai     }
961a9f484e5SJordan K. Hubbard   }
962af57ed9fSAtsushi Murai   logprintf("job done.\n");
963af57ed9fSAtsushi Murai }
964