xref: /freebsd/usr.sbin/ppp/main.c (revision 2a279fed14e3dfaf763520f24bee051a708cb892)
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  *
202a279fedSBrian Somers  * $Id: main.c,v 1.114 1997/12/28 21:55:04 brian 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  */
2675240ed1SBrian Somers #include <sys/param.h>
276a6b4bbbSBrian Somers #include <sys/time.h>
286a6b4bbbSBrian Somers #include <sys/select.h>
29af57ed9fSAtsushi Murai #include <sys/socket.h>
3075240ed1SBrian Somers #include <netinet/in.h>
31a9f484e5SJordan K. Hubbard #include <netinet/in_systm.h>
32a9f484e5SJordan K. Hubbard #include <netinet/ip.h>
3375240ed1SBrian Somers #include <arpa/inet.h>
3475240ed1SBrian Somers #include <netdb.h>
356a6b4bbbSBrian Somers #include <net/if.h>
36b6e82f33SBrian Somers #ifdef __FreeBSD__
376a6b4bbbSBrian Somers #include <net/if_var.h>
38b6e82f33SBrian Somers #endif
396a6b4bbbSBrian Somers #include <net/if_tun.h>
4075240ed1SBrian Somers 
4175240ed1SBrian Somers #include <errno.h>
4275240ed1SBrian Somers #include <fcntl.h>
4375240ed1SBrian Somers #include <paths.h>
4475240ed1SBrian Somers #include <signal.h>
4575240ed1SBrian Somers #include <stdio.h>
4675240ed1SBrian Somers #include <stdlib.h>
4775240ed1SBrian Somers #include <string.h>
4875240ed1SBrian Somers #include <sys/time.h>
4975240ed1SBrian Somers #include <sys/wait.h>
50683cef3cSBrian Somers #include <sysexits.h>
5175240ed1SBrian Somers #include <termios.h>
5275240ed1SBrian Somers #include <unistd.h>
5375240ed1SBrian Somers 
54b6e82f33SBrian Somers #include "command.h"
5575240ed1SBrian Somers #include "mbuf.h"
5675240ed1SBrian Somers #include "log.h"
5775240ed1SBrian Somers #include "defs.h"
585106c671SBrian Somers #include "id.h"
5975240ed1SBrian Somers #include "timer.h"
6075240ed1SBrian Somers #include "fsm.h"
61af57ed9fSAtsushi Murai #include "modem.h"
62af57ed9fSAtsushi Murai #include "os.h"
63af57ed9fSAtsushi Murai #include "hdlc.h"
64af57ed9fSAtsushi Murai #include "lcp.h"
650053cc58SBrian Somers #include "ccp.h"
66af57ed9fSAtsushi Murai #include "ipcp.h"
676ed9fb2fSBrian Somers #include "loadalias.h"
68af57ed9fSAtsushi Murai #include "vars.h"
6953c9f6c0SAtsushi Murai #include "auth.h"
7084b8a6ebSAtsushi Murai #include "filter.h"
71ed6a16c1SPoul-Henning Kamp #include "systems.h"
72ed6a16c1SPoul-Henning Kamp #include "ip.h"
73f5ff0f7cSBrian Somers #include "sig.h"
744ef16f24SBrian Somers #include "server.h"
75de451c68SBrian Somers #include "lcpproto.h"
7675240ed1SBrian Somers #include "main.h"
7775240ed1SBrian Somers #include "vjcomp.h"
7875240ed1SBrian Somers #include "async.h"
794562be74SBrian Somers #include "pathnames.h"
806a6b4bbbSBrian Somers #include "tun.h"
81b6e82f33SBrian Somers #include "route.h"
8253c9f6c0SAtsushi Murai 
8353c9f6c0SAtsushi Murai #ifndef O_NONBLOCK
8453c9f6c0SAtsushi Murai #ifdef O_NDELAY
8553c9f6c0SAtsushi Murai #define	O_NONBLOCK O_NDELAY
8653c9f6c0SAtsushi Murai #endif
8753c9f6c0SAtsushi Murai #endif
88af57ed9fSAtsushi Murai 
8975240ed1SBrian Somers int TermMode = 0;
9075240ed1SBrian Somers int tunno = 0;
91af57ed9fSAtsushi Murai 
92af57ed9fSAtsushi Murai static struct termios oldtio;	/* Original tty mode */
93af57ed9fSAtsushi Murai static struct termios comtio;	/* Command level tty mode */
946d14e2a8SJordan K. Hubbard static pid_t BGPid = 0;
9541c6c543SBrian Somers static char pid_filename[MAXPATHLEN];
9676c5241dSBrian Somers static int dial_up;
97af57ed9fSAtsushi Murai 
9875240ed1SBrian Somers static void DoLoop(void);
9975240ed1SBrian Somers static void TerminalStop(int);
100b6e82f33SBrian Somers static const char *ex_desc(int);
10175240ed1SBrian Somers 
102af57ed9fSAtsushi Murai static void
103368aee2bSBrian Somers TtyInit(int DontWantInt)
104af57ed9fSAtsushi Murai {
105af57ed9fSAtsushi Murai   struct termios newtio;
106af57ed9fSAtsushi Murai   int stat;
107af57ed9fSAtsushi Murai 
1082a279fedSBrian Somers   stat = fcntl(netfd, F_GETFL, 0);
109274e766cSBrian Somers   if (stat > 0) {
110af57ed9fSAtsushi Murai     stat |= O_NONBLOCK;
1112a279fedSBrian Somers     (void) fcntl(netfd, F_SETFL, stat);
112274e766cSBrian Somers   }
113af57ed9fSAtsushi Murai   newtio = oldtio;
114af57ed9fSAtsushi Murai   newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
115af57ed9fSAtsushi Murai   newtio.c_iflag = 0;
116af57ed9fSAtsushi Murai   newtio.c_oflag &= ~OPOST;
117af57ed9fSAtsushi Murai   newtio.c_cc[VEOF] = _POSIX_VDISABLE;
118368aee2bSBrian Somers   if (DontWantInt)
119af57ed9fSAtsushi Murai     newtio.c_cc[VINTR] = _POSIX_VDISABLE;
120af57ed9fSAtsushi Murai   newtio.c_cc[VMIN] = 1;
121af57ed9fSAtsushi Murai   newtio.c_cc[VTIME] = 0;
122af57ed9fSAtsushi Murai   newtio.c_cflag |= CS8;
1232a279fedSBrian Somers   tcsetattr(netfd, TCSANOW, &newtio);
124af57ed9fSAtsushi Murai   comtio = newtio;
125af57ed9fSAtsushi Murai }
126af57ed9fSAtsushi Murai 
127af57ed9fSAtsushi Murai /*
128af57ed9fSAtsushi Murai  *  Set tty into command mode. We allow canonical input and echo processing.
129af57ed9fSAtsushi Murai  */
130c3899f8dSAtsushi Murai void
131944f7098SBrian Somers TtyCommandMode(int prompt)
132af57ed9fSAtsushi Murai {
133af57ed9fSAtsushi Murai   struct termios newtio;
134af57ed9fSAtsushi Murai   int stat;
135af57ed9fSAtsushi Murai 
136af57ed9fSAtsushi Murai   if (!(mode & MODE_INTER))
137af57ed9fSAtsushi Murai     return;
1382a279fedSBrian Somers   tcgetattr(netfd, &newtio);
139c3899f8dSAtsushi Murai   newtio.c_lflag |= (ECHO | ISIG | ICANON);
140af57ed9fSAtsushi Murai   newtio.c_iflag = oldtio.c_iflag;
141af57ed9fSAtsushi Murai   newtio.c_oflag |= OPOST;
1422a279fedSBrian Somers   tcsetattr(netfd, TCSADRAIN, &newtio);
1432a279fedSBrian Somers   stat = fcntl(netfd, F_GETFL, 0);
144274e766cSBrian Somers   if (stat > 0) {
145af57ed9fSAtsushi Murai     stat |= O_NONBLOCK;
1462a279fedSBrian Somers     (void) fcntl(netfd, F_SETFL, stat);
147274e766cSBrian Somers   }
148af57ed9fSAtsushi Murai   TermMode = 0;
149944f7098SBrian Somers   if (prompt)
150944f7098SBrian Somers     Prompt();
151af57ed9fSAtsushi Murai }
152af57ed9fSAtsushi Murai 
153af57ed9fSAtsushi Murai /*
154af57ed9fSAtsushi Murai  * Set tty into terminal mode which is used while we invoke term command.
155af57ed9fSAtsushi Murai  */
156af57ed9fSAtsushi Murai void
157af57ed9fSAtsushi Murai TtyTermMode()
158af57ed9fSAtsushi Murai {
159af57ed9fSAtsushi Murai   int stat;
160af57ed9fSAtsushi Murai 
1612a279fedSBrian Somers   tcsetattr(netfd, TCSADRAIN, &comtio);
1622a279fedSBrian Somers   stat = fcntl(netfd, F_GETFL, 0);
163274e766cSBrian Somers   if (stat > 0) {
164af57ed9fSAtsushi Murai     stat &= ~O_NONBLOCK;
1652a279fedSBrian Somers     (void) fcntl(netfd, F_SETFL, stat);
166274e766cSBrian Somers   }
167af57ed9fSAtsushi Murai   TermMode = 1;
168af57ed9fSAtsushi Murai }
169af57ed9fSAtsushi Murai 
170af57ed9fSAtsushi Murai void
171c3899f8dSAtsushi Murai TtyOldMode()
172c3899f8dSAtsushi Murai {
173c3899f8dSAtsushi Murai   int stat;
174c3899f8dSAtsushi Murai 
1752a279fedSBrian Somers   stat = fcntl(netfd, F_GETFL, 0);
176274e766cSBrian Somers   if (stat > 0) {
177c3899f8dSAtsushi Murai     stat &= ~O_NONBLOCK;
1782a279fedSBrian Somers     (void) fcntl(netfd, F_SETFL, stat);
179274e766cSBrian Somers   }
1802a279fedSBrian Somers   tcsetattr(netfd, TCSADRAIN, &oldtio);
181c3899f8dSAtsushi Murai }
182c3899f8dSAtsushi Murai 
183c3899f8dSAtsushi Murai void
184944f7098SBrian Somers Cleanup(int excode)
185af57ed9fSAtsushi Murai {
186e7250038SBrian Somers   DropClient(1);
1878ea8442cSBrian Somers   ServerClose();
1880fe7ca31SBrian Somers   OsInterfaceDown(1);
1890fe7ca31SBrian Somers   HangupModem(1);
1909a571ec7SBrian Somers   nointr_sleep(1);
1916e4959f0SBrian Somers   DeleteIfRoutes(1);
1925106c671SBrian Somers   ID0unlink(pid_filename);
1936e4959f0SBrian Somers   if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
1946e4959f0SBrian Somers     char c = EX_ERRDEAD;
195944f7098SBrian Somers 
1966e4959f0SBrian Somers     if (write(BGFiledes[1], &c, 1) == 1)
197927145beSBrian Somers       LogPrintf(LogPHASE, "Parent notified of failure.\n");
1986e4959f0SBrian Somers     else
199927145beSBrian Somers       LogPrintf(LogPHASE, "Failed to notify parent of failure.\n");
2006e4959f0SBrian Somers     close(BGFiledes[1]);
2016e4959f0SBrian Somers   }
202927145beSBrian Somers   LogPrintf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
203c3899f8dSAtsushi Murai   TtyOldMode();
2045106c671SBrian Somers   LogClose();
205af57ed9fSAtsushi Murai 
206af57ed9fSAtsushi Murai   exit(excode);
207af57ed9fSAtsushi Murai }
208af57ed9fSAtsushi Murai 
209af57ed9fSAtsushi Murai static void
210944f7098SBrian Somers CloseConnection(int signo)
211af57ed9fSAtsushi Murai {
212368aee2bSBrian Somers   /* NOTE, these are manual, we've done a setsid() */
21312ef29a8SBrian Somers   pending_signal(SIGINT, SIG_IGN);
214873725ccSBrian Somers   LogPrintf(LogPHASE, "Caught signal %d, abort connection\n", signo);
215944f7098SBrian Somers   reconnectState = RECON_FALSE;
216944f7098SBrian Somers   reconnectCount = 0;
217368aee2bSBrian Somers   DownConnection();
21875240ed1SBrian Somers   dial_up = 0;
21912ef29a8SBrian Somers   pending_signal(SIGINT, CloseConnection);
2206d14e2a8SJordan K. Hubbard }
221af57ed9fSAtsushi Murai 
222af57ed9fSAtsushi Murai static void
223944f7098SBrian Somers CloseSession(int signo)
224af57ed9fSAtsushi Murai {
2256d14e2a8SJordan K. Hubbard   if (BGPid) {
2266d14e2a8SJordan K. Hubbard     kill(BGPid, SIGINT);
2276d14e2a8SJordan K. Hubbard     exit(EX_TERM);
2286d14e2a8SJordan K. Hubbard   }
229927145beSBrian Somers   LogPrintf(LogPHASE, "Signal %d, terminate.\n", signo);
23025aa96acSBrian Somers   reconnect(RECON_FALSE);
231af57ed9fSAtsushi Murai   LcpClose();
232af57ed9fSAtsushi Murai   Cleanup(EX_TERM);
233af57ed9fSAtsushi Murai }
234c3899f8dSAtsushi Murai 
235c3899f8dSAtsushi Murai static void
236b6e82f33SBrian Somers TerminalCont(int signo)
237c3899f8dSAtsushi Murai {
238f5ff0f7cSBrian Somers   pending_signal(SIGCONT, SIG_DFL);
239f5ff0f7cSBrian Somers   pending_signal(SIGTSTP, TerminalStop);
2402a279fedSBrian Somers   TtyCommandMode(getpgrp() == tcgetpgrp(netfd));
241c3899f8dSAtsushi Murai }
242c3899f8dSAtsushi Murai 
243c3899f8dSAtsushi Murai static void
244944f7098SBrian Somers TerminalStop(int signo)
245c3899f8dSAtsushi Murai {
246f5ff0f7cSBrian Somers   pending_signal(SIGCONT, TerminalCont);
247c3899f8dSAtsushi Murai   TtyOldMode();
248f5ff0f7cSBrian Somers   pending_signal(SIGTSTP, SIG_DFL);
249c3899f8dSAtsushi Murai   kill(getpid(), signo);
250c3899f8dSAtsushi Murai }
251c3899f8dSAtsushi Murai 
2524ef16f24SBrian Somers static void
253944f7098SBrian Somers SetUpServer(int signo)
2544ef16f24SBrian Somers {
2554ef16f24SBrian Somers   int res;
256944f7098SBrian Somers 
2578ea8442cSBrian Somers   VarHaveLocalAuthKey = 0;
2588ea8442cSBrian Somers   LocalAuthInit();
2594ef16f24SBrian Somers   if ((res = ServerTcpOpen(SERVER_PORT + tunno)) != 0)
260683cef3cSBrian Somers     LogPrintf(LogERROR, "SIGUSR1: Failed %d to open port %d\n",
261683cef3cSBrian Somers 	      res, SERVER_PORT + tunno);
2624ef16f24SBrian Somers }
2634ef16f24SBrian Somers 
2648ea8442cSBrian Somers static void
2658ea8442cSBrian Somers BringDownServer(int signo)
2668ea8442cSBrian Somers {
2678ea8442cSBrian Somers   VarHaveLocalAuthKey = 0;
2688ea8442cSBrian Somers   LocalAuthInit();
2698ea8442cSBrian Somers   ServerClose();
2708ea8442cSBrian Somers }
2718ea8442cSBrian Somers 
272b6e82f33SBrian Somers static const char *
2736efd9292SBrian Somers ex_desc(int ex)
2746efd9292SBrian Somers {
2756efd9292SBrian Somers   static char num[12];
276b6e82f33SBrian Somers   static const char *desc[] = {
277b6e82f33SBrian Somers     "normal", "start", "sock", "modem", "dial", "dead", "done",
278b6e82f33SBrian Somers     "reboot", "errdead", "hangup", "term", "nodial", "nologin"
279b6e82f33SBrian Somers   };
2806efd9292SBrian Somers 
28170ee81ffSBrian Somers   if (ex >= 0 && ex < sizeof desc / sizeof *desc)
2826efd9292SBrian Somers     return desc[ex];
2836efd9292SBrian Somers   snprintf(num, sizeof num, "%d", ex);
2846efd9292SBrian Somers   return num;
2856efd9292SBrian Somers }
286c3899f8dSAtsushi Murai 
28775240ed1SBrian Somers static void
288b6e82f33SBrian Somers Usage(void)
289af57ed9fSAtsushi Murai {
290680026d6SNate Williams   fprintf(stderr,
291b6e82f33SBrian Somers 	  "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]"
292b6e82f33SBrian Somers #ifndef NOALIAS
293b6e82f33SBrian Somers           " [ -alias ]"
294b6e82f33SBrian Somers #endif
295b6e82f33SBrian Somers           " [system]\n");
296af57ed9fSAtsushi Murai   exit(EX_START);
297af57ed9fSAtsushi Murai }
298af57ed9fSAtsushi Murai 
29939f94eddSBrian Somers static char *
300af57ed9fSAtsushi Murai ProcessArgs(int argc, char **argv)
301af57ed9fSAtsushi Murai {
302af57ed9fSAtsushi Murai   int optc;
303af57ed9fSAtsushi Murai   char *cp;
304af57ed9fSAtsushi Murai 
305af57ed9fSAtsushi Murai   optc = 0;
30612ef29a8SBrian Somers   mode = MODE_INTER;
307af57ed9fSAtsushi Murai   while (argc > 0 && **argv == '-') {
308af57ed9fSAtsushi Murai     cp = *argv + 1;
30912ef29a8SBrian Somers     if (strcmp(cp, "auto") == 0) {
310af57ed9fSAtsushi Murai       mode |= MODE_AUTO;
31112ef29a8SBrian Somers       mode &= ~MODE_INTER;
31212ef29a8SBrian Somers     } else if (strcmp(cp, "background") == 0) {
31312ef29a8SBrian Somers       mode |= MODE_BACKGROUND;
31412ef29a8SBrian Somers       mode &= ~MODE_INTER;
31512ef29a8SBrian Somers     } else if (strcmp(cp, "direct") == 0) {
316af57ed9fSAtsushi Murai       mode |= MODE_DIRECT;
31712ef29a8SBrian Somers       mode &= ~MODE_INTER;
31812ef29a8SBrian Somers     } else if (strcmp(cp, "dedicated") == 0) {
319af57ed9fSAtsushi Murai       mode |= MODE_DEDICATED;
32012ef29a8SBrian Somers       mode &= ~MODE_INTER;
32112ef29a8SBrian Somers     } else if (strcmp(cp, "ddial") == 0) {
32212ef29a8SBrian Somers       mode |= MODE_DDIAL;
32312ef29a8SBrian Somers       mode &= ~MODE_INTER;
324b6e82f33SBrian Somers #ifndef NOALIAS
32512ef29a8SBrian Somers     } else if (strcmp(cp, "alias") == 0) {
3266ed9fb2fSBrian Somers       if (loadAliasHandlers(&VarAliasHandlers) == 0)
327a9f484e5SJordan K. Hubbard 	mode |= MODE_ALIAS;
3286ed9fb2fSBrian Somers       else
329927145beSBrian Somers 	LogPrintf(LogWARN, "Cannot load alias library\n");
330a9f484e5SJordan K. Hubbard       optc--;			/* this option isn't exclusive */
331b6e82f33SBrian Somers #endif
332944f7098SBrian Somers     } else
333af57ed9fSAtsushi Murai       Usage();
334af57ed9fSAtsushi Murai     optc++;
335944f7098SBrian Somers     argv++;
336944f7098SBrian Somers     argc--;
337af57ed9fSAtsushi Murai   }
338af57ed9fSAtsushi Murai   if (argc > 1) {
339af57ed9fSAtsushi Murai     fprintf(stderr, "specify only one system label.\n");
340af57ed9fSAtsushi Murai     exit(EX_START);
341af57ed9fSAtsushi Murai   }
342af57ed9fSAtsushi Murai 
343af57ed9fSAtsushi Murai   if (optc > 1) {
344af57ed9fSAtsushi Murai     fprintf(stderr, "specify only one mode.\n");
345af57ed9fSAtsushi Murai     exit(EX_START);
346af57ed9fSAtsushi Murai   }
34739f94eddSBrian Somers 
34839f94eddSBrian Somers   return argc == 1 ? *argv : NULL;	/* Don't SetLabel yet ! */
349af57ed9fSAtsushi Murai }
350af57ed9fSAtsushi Murai 
351af57ed9fSAtsushi Murai static void
352b6e82f33SBrian Somers Greetings(void)
353af57ed9fSAtsushi Murai {
354927145beSBrian Somers   if (VarTerm) {
355927145beSBrian Somers     fprintf(VarTerm, "User Process PPP. Written by Toshiharu OHNO.\n");
356927145beSBrian Somers     fflush(VarTerm);
357927145beSBrian Somers   }
358af57ed9fSAtsushi Murai }
359af57ed9fSAtsushi Murai 
3604ef16f24SBrian Somers int
361944f7098SBrian Somers main(int argc, char **argv)
362af57ed9fSAtsushi Murai {
363aefd026aSBrian Somers   FILE *lockfile;
36439f94eddSBrian Somers   char *name, *label;
365e3b4c400SBrian Somers   int nfds;
366e3b4c400SBrian Somers 
367e3b4c400SBrian Somers   nfds = getdtablesize();
368e3b4c400SBrian Somers   if (nfds >= FD_SETSIZE)
369e3b4c400SBrian Somers     /*
370e3b4c400SBrian Somers      * If we've got loads of file descriptors, make sure they're all
371e3b4c400SBrian Somers      * closed.  If they aren't, we may end up with a seg fault when our
372e3b4c400SBrian Somers      * `fd_set's get too big when select()ing !
373e3b4c400SBrian Somers      */
374e3b4c400SBrian Somers     while (--nfds > 2)
375e3b4c400SBrian Somers       close(nfds);
376af57ed9fSAtsushi Murai 
3770706ff38SBrian Somers   VarTerm = 0;
37875240ed1SBrian Somers   name = strrchr(argv[0], '/');
379927145beSBrian Somers   LogOpen(name ? name + 1 : argv[0]);
380927145beSBrian Somers 
3812a279fedSBrian Somers   tcgetattr(STDIN_FILENO, &oldtio);	/* Save original tty mode */
3822a279fedSBrian Somers 
383944f7098SBrian Somers   argc--;
384944f7098SBrian Somers   argv++;
38539f94eddSBrian Somers   label = ProcessArgs(argc, argv);
38612ef29a8SBrian Somers   if (!(mode & MODE_DIRECT))
3870706ff38SBrian Somers     VarTerm = stdout;
38812ef29a8SBrian Somers 
3895106c671SBrian Somers   ID0init();
3904562be74SBrian Somers   if (ID0realuid() != 0) {
3914562be74SBrian Somers     char conf[200], *ptr;
3924562be74SBrian Somers 
3934562be74SBrian Somers     snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE);
3944562be74SBrian Somers     do {
3954562be74SBrian Somers       if (!access(conf, W_OK)) {
3964562be74SBrian Somers         LogPrintf(LogALERT, "ppp: Access violation: Please protect %s\n", conf);
3974562be74SBrian Somers         return -1;
3984562be74SBrian Somers       }
3994562be74SBrian Somers       ptr = conf + strlen(conf)-2;
4004562be74SBrian Somers       while (ptr > conf && *ptr != '/')
4014562be74SBrian Somers         *ptr-- = '\0';
4024562be74SBrian Somers     } while (ptr >= conf);
4034562be74SBrian Somers   }
4044562be74SBrian Somers 
40539f94eddSBrian Somers   if (!ValidSystem(label)) {
40612ef29a8SBrian Somers     fprintf(stderr, "You may not use ppp in this mode with this label\n");
407815624cfSBrian Somers     if (mode & MODE_DIRECT) {
408815624cfSBrian Somers       const char *l;
40939f94eddSBrian Somers       l = label ? label : "default";
410815624cfSBrian Somers       LogPrintf(LogWARN, "Label %s rejected -direct connection\n", l);
411815624cfSBrian Somers     }
412815624cfSBrian Somers     LogClose();
41312ef29a8SBrian Somers     return 1;
41412ef29a8SBrian Somers   }
41512ef29a8SBrian Somers 
416c7d4711fSBrian Somers   if (!GetShortHost())
417c7d4711fSBrian Somers     return 1;
418af57ed9fSAtsushi Murai   Greetings();
419af57ed9fSAtsushi Murai   IpcpDefAddress();
420af57ed9fSAtsushi Murai 
421082798e7SBrian Somers   if (mode & MODE_INTER)
422082798e7SBrian Somers     VarLocalAuth = LOCAL_AUTH;
423082798e7SBrian Somers 
424927145beSBrian Somers   if (SelectSystem("default", CONFFILE) < 0 && VarTerm)
425927145beSBrian Somers     fprintf(VarTerm, "Warning: No default entry is given in config file.\n");
426af57ed9fSAtsushi Murai 
427af57ed9fSAtsushi Murai   if (OpenTunnel(&tunno) < 0) {
428bcc332bdSBrian Somers     LogPrintf(LogWARN, "OpenTunnel: %s\n", strerror(errno));
4294ef16f24SBrian Somers     return EX_START;
430af57ed9fSAtsushi Murai   }
4312a279fedSBrian Somers   if (mode & MODE_INTER)
432927145beSBrian Somers     fprintf(VarTerm, "Interactive mode\n");
4332a279fedSBrian Somers   else if ((mode & MODE_OUTGOING_DAEMON) && !(mode & MODE_DEDICATED))
43439f94eddSBrian Somers     if (label == NULL) {
435927145beSBrian Somers       if (VarTerm)
436927145beSBrian Somers 	fprintf(VarTerm, "Destination system must be specified in"
4376efd9292SBrian Somers 		" auto, background or ddial mode.\n");
4384ef16f24SBrian Somers       return EX_START;
4396d14e2a8SJordan K. Hubbard     }
44012ef29a8SBrian Somers 
441873725ccSBrian Somers   pending_signal(SIGHUP, CloseSession);
442f5ff0f7cSBrian Somers   pending_signal(SIGTERM, CloseSession);
443873725ccSBrian Somers   pending_signal(SIGINT, CloseConnection);
444f5ff0f7cSBrian Somers   pending_signal(SIGQUIT, CloseSession);
44553c9f6c0SAtsushi Murai #ifdef SIGPIPE
446e0d3e233SAndrey A. Chernov   signal(SIGPIPE, SIG_IGN);
44753c9f6c0SAtsushi Murai #endif
44853c9f6c0SAtsushi Murai #ifdef SIGALRM
449f5ff0f7cSBrian Somers   pending_signal(SIGALRM, SIG_IGN);
45053c9f6c0SAtsushi Murai #endif
4514ef16f24SBrian Somers   if (mode & MODE_INTER) {
452c3899f8dSAtsushi Murai #ifdef SIGTSTP
453f5ff0f7cSBrian Somers     pending_signal(SIGTSTP, TerminalStop);
454c3899f8dSAtsushi Murai #endif
455c3899f8dSAtsushi Murai #ifdef SIGTTIN
456f5ff0f7cSBrian Somers     pending_signal(SIGTTIN, TerminalStop);
457c3899f8dSAtsushi Murai #endif
458c3899f8dSAtsushi Murai #ifdef SIGTTOU
459f5ff0f7cSBrian Somers     pending_signal(SIGTTOU, SIG_IGN);
460c3899f8dSAtsushi Murai #endif
461c3899f8dSAtsushi Murai   }
46212ef29a8SBrian Somers   if (!(mode & MODE_INTER)) {
4634ef16f24SBrian Somers #ifdef SIGUSR1
4644ef16f24SBrian Somers     pending_signal(SIGUSR1, SetUpServer);
4654ef16f24SBrian Somers #endif
4668ea8442cSBrian Somers #ifdef SIGUSR2
4678ea8442cSBrian Somers     pending_signal(SIGUSR2, BringDownServer);
4688ea8442cSBrian Somers #endif
46912ef29a8SBrian Somers   }
470af57ed9fSAtsushi Murai 
47139f94eddSBrian Somers   if (label) {
47239f94eddSBrian Somers     if (SelectSystem(label, CONFFILE) < 0) {
473e4450123SBrian Somers       LogPrintf(LogWARN, "Destination system %s not found in conf file.\n",
474e4450123SBrian Somers                 GetLabel());
475af57ed9fSAtsushi Murai       Cleanup(EX_START);
476af57ed9fSAtsushi Murai     }
47739f94eddSBrian Somers     /*
47839f94eddSBrian Somers      * We don't SetLabel() 'till now in case SelectSystem() has an
47939f94eddSBrian Somers      * embeded load "otherlabel" command.
48039f94eddSBrian Somers      */
48139f94eddSBrian Somers     SetLabel(label);
48212ef29a8SBrian Somers     if (mode & MODE_OUTGOING_DAEMON &&
48312ef29a8SBrian Somers 	DefHisAddress.ipaddr.s_addr == INADDR_ANY) {
484e4450123SBrian Somers       LogPrintf(LogWARN, "You must \"set ifaddr\" in label %s for"
48539f94eddSBrian Somers 		" auto, background or ddial mode.\n", label);
486af57ed9fSAtsushi Murai       Cleanup(EX_START);
487af57ed9fSAtsushi Murai     }
488af57ed9fSAtsushi Murai   }
4896efd9292SBrian Somers 
49012ef29a8SBrian Somers   if (mode & MODE_DAEMON) {
4916d14e2a8SJordan K. Hubbard     if (mode & MODE_BACKGROUND) {
4926d14e2a8SJordan K. Hubbard       if (pipe(BGFiledes)) {
493afc7fa2cSBrian Somers 	LogPrintf(LogERROR, "pipe: %s\n", strerror(errno));
4946d14e2a8SJordan K. Hubbard 	Cleanup(EX_SOCK);
4956d14e2a8SJordan K. Hubbard       }
4966d14e2a8SJordan K. Hubbard     }
497af57ed9fSAtsushi Murai 
498af57ed9fSAtsushi Murai     if (!(mode & MODE_DIRECT)) {
4996d14e2a8SJordan K. Hubbard       pid_t bgpid;
500a9c6b5dfSAtsushi Murai 
5016d14e2a8SJordan K. Hubbard       bgpid = fork();
5026d14e2a8SJordan K. Hubbard       if (bgpid == -1) {
503afc7fa2cSBrian Somers 	LogPrintf(LogERROR, "fork: %s\n", strerror(errno));
5046d14e2a8SJordan K. Hubbard 	Cleanup(EX_SOCK);
5056d14e2a8SJordan K. Hubbard       }
5066d14e2a8SJordan K. Hubbard       if (bgpid) {
5076d14e2a8SJordan K. Hubbard 	char c = EX_NORMAL;
508a9c6b5dfSAtsushi Murai 
5096d14e2a8SJordan K. Hubbard 	if (mode & MODE_BACKGROUND) {
5106d14e2a8SJordan K. Hubbard 	  /* Wait for our child to close its pipe before we exit. */
5116d14e2a8SJordan K. Hubbard 	  BGPid = bgpid;
5126e4959f0SBrian Somers 	  close(BGFiledes[1]);
5136efd9292SBrian Somers 	  if (read(BGFiledes[0], &c, 1) != 1) {
514927145beSBrian Somers 	    fprintf(VarTerm, "Child exit, no status.\n");
515927145beSBrian Somers 	    LogPrintf(LogPHASE, "Parent: Child exit, no status.\n");
5166efd9292SBrian Somers 	  } else if (c == EX_NORMAL) {
517927145beSBrian Somers 	    fprintf(VarTerm, "PPP enabled.\n");
518927145beSBrian Somers 	    LogPrintf(LogPHASE, "Parent: PPP enabled.\n");
5196efd9292SBrian Somers 	  } else {
520927145beSBrian Somers 	    fprintf(VarTerm, "Child failed (%s).\n", ex_desc((int) c));
521927145beSBrian Somers 	    LogPrintf(LogPHASE, "Parent: Child failed (%s).\n",
52280e37c72SBrian Somers 		      ex_desc((int) c));
5236efd9292SBrian Somers 	  }
5246e4959f0SBrian Somers 	  close(BGFiledes[0]);
5256d14e2a8SJordan K. Hubbard 	}
5264ef16f24SBrian Somers 	return c;
5276e4959f0SBrian Somers       } else if (mode & MODE_BACKGROUND)
5286e4959f0SBrian Somers 	close(BGFiledes[0]);
529aefd026aSBrian Somers     }
530aefd026aSBrian Somers 
531d656a4c5SBrian Somers     VarTerm = 0;		/* We know it's currently stdout */
5322a279fedSBrian Somers     close(STDOUT_FILENO);
5332a279fedSBrian Somers     close(STDERR_FILENO);
5340706ff38SBrian Somers 
535d656a4c5SBrian Somers     if (mode & MODE_DIRECT)
5362a279fedSBrian Somers       /* STDIN_FILENO gets used by OpenModem in DIRECT mode */
537368aee2bSBrian Somers       TtyInit(1);
53812ef29a8SBrian Somers     else if (mode & MODE_DAEMON) {
539d656a4c5SBrian Somers       setsid();
5402a279fedSBrian Somers       close(STDIN_FILENO);
541d656a4c5SBrian Somers     }
542af57ed9fSAtsushi Murai   } else {
5432a279fedSBrian Somers     close(STDIN_FILENO);
5442a279fedSBrian Somers     if ((netfd = open(_PATH_TTY, O_RDONLY)) < 0) {
5452a279fedSBrian Somers       fprintf(stderr, "Cannot open %s for intput !\n", _PATH_TTY);
5462a279fedSBrian Somers       return 2;
5472a279fedSBrian Somers     }
5482a279fedSBrian Somers     close(STDERR_FILENO);
549368aee2bSBrian Somers     TtyInit(0);
550c3899f8dSAtsushi Murai     TtyCommandMode(1);
551af57ed9fSAtsushi Murai   }
55235495becSBrian Somers 
55370ee81ffSBrian Somers   snprintf(pid_filename, sizeof pid_filename, "%stun%d.pid",
55435495becSBrian Somers            _PATH_VARRUN, tunno);
5555106c671SBrian Somers   lockfile = ID0fopen(pid_filename, "w");
5565106c671SBrian Somers   if (lockfile != NULL) {
55735495becSBrian Somers     fprintf(lockfile, "%d\n", (int) getpid());
55835495becSBrian Somers     fclose(lockfile);
55935495becSBrian Somers   } else
56035495becSBrian Somers     LogPrintf(LogALERT, "Warning: Can't create %s: %s\n",
56135495becSBrian Somers               pid_filename, strerror(errno));
56235495becSBrian Somers 
563927145beSBrian Somers   LogPrintf(LogPHASE, "PPP Started.\n");
564af57ed9fSAtsushi Murai 
565af57ed9fSAtsushi Murai 
566af57ed9fSAtsushi Murai   do
567af57ed9fSAtsushi Murai     DoLoop();
568af57ed9fSAtsushi Murai   while (mode & MODE_DEDICATED);
569af57ed9fSAtsushi Murai 
570af57ed9fSAtsushi Murai   Cleanup(EX_DONE);
5714ef16f24SBrian Somers   return 0;
572af57ed9fSAtsushi Murai }
573af57ed9fSAtsushi Murai 
574af57ed9fSAtsushi Murai /*
5756d14e2a8SJordan K. Hubbard  *  Turn into packet mode, where we speak PPP.
576af57ed9fSAtsushi Murai  */
577af57ed9fSAtsushi Murai void
578af57ed9fSAtsushi Murai PacketMode()
579af57ed9fSAtsushi Murai {
5809780ef31SBrian Somers   if (RawModem() < 0) {
581927145beSBrian Somers     LogPrintf(LogWARN, "PacketMode: Not connected.\n");
582af57ed9fSAtsushi Murai     return;
583af57ed9fSAtsushi Murai   }
584af57ed9fSAtsushi Murai   AsyncInit();
58503604f35SBrian Somers   VjInit(15);
586af57ed9fSAtsushi Murai   LcpInit();
587af57ed9fSAtsushi Murai   IpcpInit();
588af57ed9fSAtsushi Murai   CcpInit();
589af57ed9fSAtsushi Murai   LcpUp();
590af57ed9fSAtsushi Murai 
591af57ed9fSAtsushi Murai   LcpOpen(VarOpenMode);
59212ef29a8SBrian Somers   if (mode & MODE_INTER)
593c3899f8dSAtsushi Murai     TtyCommandMode(1);
594927145beSBrian Somers   if (VarTerm) {
595927145beSBrian Somers     fprintf(VarTerm, "Packet mode.\n");
596b0cdb3ceSJordan K. Hubbard     aft_cmd = 1;
597af57ed9fSAtsushi Murai   }
598af57ed9fSAtsushi Murai }
599af57ed9fSAtsushi Murai 
600af57ed9fSAtsushi Murai static void
601b6e82f33SBrian Somers ShowHelp(void)
602af57ed9fSAtsushi Murai {
603030d3ce6SBrian Somers   fprintf(stderr, "The following commands are available:\r\n");
604030d3ce6SBrian Somers   fprintf(stderr, " ~p\tEnter Packet mode\r\n");
605030d3ce6SBrian Somers   fprintf(stderr, " ~-\tDecrease log level\r\n");
606030d3ce6SBrian Somers   fprintf(stderr, " ~+\tIncrease log level\r\n");
607030d3ce6SBrian Somers   fprintf(stderr, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
608030d3ce6SBrian Somers   fprintf(stderr, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
609030d3ce6SBrian Somers   fprintf(stderr, " ~.\tTerminate program\r\n");
610030d3ce6SBrian Somers   fprintf(stderr, " ~?\tThis help\r\n");
611af57ed9fSAtsushi Murai }
612af57ed9fSAtsushi Murai 
613af57ed9fSAtsushi Murai static void
614b6e82f33SBrian Somers ReadTty(void)
615af57ed9fSAtsushi Murai {
616af57ed9fSAtsushi Murai   int n;
617af57ed9fSAtsushi Murai   char ch;
618af57ed9fSAtsushi Murai   static int ttystate;
61986e02934SBrian Somers   char linebuff[LINE_LEN];
620af57ed9fSAtsushi Murai 
621927145beSBrian Somers   LogPrintf(LogDEBUG, "termode = %d, netfd = %d, mode = %d\n",
622927145beSBrian Somers 	    TermMode, netfd, mode);
623af57ed9fSAtsushi Murai   if (!TermMode) {
62470ee81ffSBrian Somers     n = read(netfd, linebuff, sizeof linebuff - 1);
62553c9f6c0SAtsushi Murai     if (n > 0) {
626927145beSBrian Somers       aft_cmd = 1;
627a1e8f937SBrian Somers       if (linebuff[n-1] == '\n')
628a1e8f937SBrian Somers         linebuff[--n] = '\0';
62970ee81ffSBrian Somers       else
63070ee81ffSBrian Somers         linebuff[n] = '\0';
631d9181b05SBrian Somers       if (n)
632d9181b05SBrian Somers         DecodeCommand(linebuff, n, IsInteractive(0) ? NULL : "Client");
633a1e8f937SBrian Somers       Prompt();
634e7250038SBrian Somers     } else if (n <= 0) {
635e7250038SBrian Somers       LogPrintf(LogPHASE, "Client connection closed.\n");
636e7250038SBrian Somers       DropClient(0);
637e7250038SBrian Somers     }
638af57ed9fSAtsushi Murai     return;
639af57ed9fSAtsushi Murai   }
640af57ed9fSAtsushi Murai 
641af57ed9fSAtsushi Murai   /*
642af57ed9fSAtsushi Murai    * We are in terminal mode, decode special sequences
643af57ed9fSAtsushi Murai    */
6442a279fedSBrian Somers   n = read(netfd, &ch, 1);
645afc7fa2cSBrian Somers   LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
646af57ed9fSAtsushi Murai 
647af57ed9fSAtsushi Murai   if (n > 0) {
648af57ed9fSAtsushi Murai     switch (ttystate) {
649af57ed9fSAtsushi Murai     case 0:
650af57ed9fSAtsushi Murai       if (ch == '~')
651af57ed9fSAtsushi Murai 	ttystate++;
652af57ed9fSAtsushi Murai       else
653af57ed9fSAtsushi Murai 	write(modem, &ch, n);
654af57ed9fSAtsushi Murai       break;
655af57ed9fSAtsushi Murai     case 1:
656af57ed9fSAtsushi Murai       switch (ch) {
657af57ed9fSAtsushi Murai       case '?':
658af57ed9fSAtsushi Murai 	ShowHelp();
659af57ed9fSAtsushi Murai 	break;
660af57ed9fSAtsushi Murai       case 'p':
661944f7098SBrian Somers 
662af57ed9fSAtsushi Murai 	/*
663af57ed9fSAtsushi Murai 	 * XXX: Should check carrier.
664af57ed9fSAtsushi Murai 	 */
665af57ed9fSAtsushi Murai 	if (LcpFsm.state <= ST_CLOSED) {
666af57ed9fSAtsushi Murai 	  VarOpenMode = OPEN_ACTIVE;
667af57ed9fSAtsushi Murai 	  PacketMode();
668af57ed9fSAtsushi Murai 	}
669af57ed9fSAtsushi Murai 	break;
670af57ed9fSAtsushi Murai       case '.':
671af57ed9fSAtsushi Murai 	TermMode = 1;
672927145beSBrian Somers 	aft_cmd = 1;
673c3899f8dSAtsushi Murai 	TtyCommandMode(1);
674af57ed9fSAtsushi Murai 	break;
675927145beSBrian Somers       case 't':
676927145beSBrian Somers 	if (LogIsKept(LogDEBUG)) {
677927145beSBrian Somers 	  ShowTimers();
678927145beSBrian Somers 	  break;
679927145beSBrian Somers 	}
680927145beSBrian Somers       case 'm':
681927145beSBrian Somers 	if (LogIsKept(LogDEBUG)) {
682b6e82f33SBrian Somers 	  ShowMemMap(NULL);
683927145beSBrian Somers 	  break;
684927145beSBrian Somers 	}
685af57ed9fSAtsushi Murai       default:
686af57ed9fSAtsushi Murai 	if (write(modem, &ch, n) < 0)
687927145beSBrian Somers 	  LogPrintf(LogERROR, "error writing to modem.\n");
688af57ed9fSAtsushi Murai 	break;
689af57ed9fSAtsushi Murai       }
690af57ed9fSAtsushi Murai       ttystate = 0;
691af57ed9fSAtsushi Murai       break;
692af57ed9fSAtsushi Murai     }
693af57ed9fSAtsushi Murai   }
694af57ed9fSAtsushi Murai }
695af57ed9fSAtsushi Murai 
696af57ed9fSAtsushi Murai 
697af57ed9fSAtsushi Murai /*
698af57ed9fSAtsushi Murai  *  Here, we'll try to detect HDLC frame
699af57ed9fSAtsushi Murai  */
700af57ed9fSAtsushi Murai 
701b6e82f33SBrian Somers static const char *FrameHeaders[] = {
70253c9f6c0SAtsushi Murai   "\176\377\003\300\041",
70353c9f6c0SAtsushi Murai   "\176\377\175\043\300\041",
70453c9f6c0SAtsushi Murai   "\176\177\175\043\100\041",
70553c9f6c0SAtsushi Murai   "\176\175\337\175\043\300\041",
70653c9f6c0SAtsushi Murai   "\176\175\137\175\043\100\041",
707af57ed9fSAtsushi Murai   NULL,
708af57ed9fSAtsushi Murai };
709af57ed9fSAtsushi Murai 
710b6e82f33SBrian Somers static const u_char *
711944f7098SBrian Somers HdlcDetect(u_char * cp, int n)
712af57ed9fSAtsushi Murai {
713b6e82f33SBrian Somers   const char *ptr, *fp, **hp;
714af57ed9fSAtsushi Murai 
715af57ed9fSAtsushi Murai   cp[n] = '\0';			/* be sure to null terminated */
716af57ed9fSAtsushi Murai   ptr = NULL;
717af57ed9fSAtsushi Murai   for (hp = FrameHeaders; *hp; hp++) {
71853c9f6c0SAtsushi Murai     fp = *hp;
71953c9f6c0SAtsushi Murai     if (DEV_IS_SYNC)
72053c9f6c0SAtsushi Murai       fp++;
721ed6a16c1SPoul-Henning Kamp     ptr = strstr((char *) cp, fp);
722ed6a16c1SPoul-Henning Kamp     if (ptr)
723af57ed9fSAtsushi Murai       break;
724af57ed9fSAtsushi Murai   }
725b6e82f33SBrian Somers   return ((const u_char *) ptr);
726af57ed9fSAtsushi Murai }
727af57ed9fSAtsushi Murai 
728af57ed9fSAtsushi Murai static struct pppTimer RedialTimer;
729af57ed9fSAtsushi Murai 
730af57ed9fSAtsushi Murai static void
731b6e82f33SBrian Somers RedialTimeout(void *v)
732af57ed9fSAtsushi Murai {
733af57ed9fSAtsushi Murai   StopTimer(&RedialTimer);
734927145beSBrian Somers   LogPrintf(LogPHASE, "Redialing timer expired.\n");
735af57ed9fSAtsushi Murai }
736af57ed9fSAtsushi Murai 
737af57ed9fSAtsushi Murai static void
738944f7098SBrian Somers StartRedialTimer(int Timeout)
739af57ed9fSAtsushi Murai {
740af57ed9fSAtsushi Murai   StopTimer(&RedialTimer);
741a9c6b5dfSAtsushi Murai 
74243ea9d19SBrian Somers   if (Timeout) {
743af57ed9fSAtsushi Murai     RedialTimer.state = TIMER_STOPPED;
744a9c6b5dfSAtsushi Murai 
74543ea9d19SBrian Somers     if (Timeout > 0)
74643ea9d19SBrian Somers       RedialTimer.load = Timeout * SECTICKS;
747a9c6b5dfSAtsushi Murai     else
748a9c6b5dfSAtsushi Murai       RedialTimer.load = (random() % REDIAL_PERIOD) * SECTICKS;
749a9c6b5dfSAtsushi Murai 
750927145beSBrian Somers     LogPrintf(LogPHASE, "Enter pause (%d) for redialing.\n",
75143ea9d19SBrian Somers 	      RedialTimer.load / SECTICKS);
75243ea9d19SBrian Somers 
753af57ed9fSAtsushi Murai     RedialTimer.func = RedialTimeout;
754af57ed9fSAtsushi Murai     StartTimer(&RedialTimer);
755af57ed9fSAtsushi Murai   }
756a9c6b5dfSAtsushi Murai }
757af57ed9fSAtsushi Murai 
75858f264e1SBrian Somers #define IN_SIZE sizeof(struct sockaddr_in)
75958f264e1SBrian Somers #define UN_SIZE sizeof(struct sockaddr_in)
76058f264e1SBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
761af57ed9fSAtsushi Murai 
762af57ed9fSAtsushi Murai static void
763b6e82f33SBrian Somers DoLoop(void)
764af57ed9fSAtsushi Murai {
765af57ed9fSAtsushi Murai   fd_set rfds, wfds, efds;
766780700e5SAndrey A. Chernov   int pri, i, n, wfd, nfds;
76758f264e1SBrian Somers   char hisaddr[ADDRSZ];
76858f264e1SBrian Somers   struct sockaddr *sa = (struct sockaddr *)hisaddr;
76958f264e1SBrian Somers   struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr;
770af57ed9fSAtsushi Murai   struct timeval timeout, *tp;
77158f264e1SBrian Somers   int ssize = ADDRSZ;
772b6e82f33SBrian Somers   const u_char *cp;
773a9c6b5dfSAtsushi Murai   int tries;
77460e218e4SAtsushi Murai   int qlen;
775368aee2bSBrian Somers   int res;
7766a6b4bbbSBrian Somers   struct tun_data tun;
7776a6b4bbbSBrian Somers #define rbuff tun.data
778c3899f8dSAtsushi Murai 
7796efd9292SBrian Somers   if (mode & MODE_DIRECT) {
7800706ff38SBrian Somers     LogPrintf(LogDEBUG, "Opening modem\n");
7819780ef31SBrian Somers     if (OpenModem() < 0)
782bc240299SBrian Somers       return;
783927145beSBrian Somers     LogPrintf(LogPHASE, "Packet mode enabled\n");
784af57ed9fSAtsushi Murai     PacketMode();
785af57ed9fSAtsushi Murai   } else if (mode & MODE_DEDICATED) {
786780700e5SAndrey A. Chernov     if (modem < 0)
7879780ef31SBrian Somers       while (OpenModem() < 0)
7889a571ec7SBrian Somers 	nointr_sleep(VarReconnectTimer);
789af57ed9fSAtsushi Murai   }
790927145beSBrian Somers   fflush(VarTerm);
791af57ed9fSAtsushi Murai 
79284b8a6ebSAtsushi Murai   timeout.tv_sec = 0;
793af57ed9fSAtsushi Murai   timeout.tv_usec = 0;
79425aa96acSBrian Somers   reconnectState = RECON_UNKNOWN;
795af57ed9fSAtsushi Murai 
7966e4959f0SBrian Somers   if (mode & MODE_BACKGROUND)
79775240ed1SBrian Somers     dial_up = 1;		/* Bring the line up */
7986e4959f0SBrian Somers   else
79975240ed1SBrian Somers     dial_up = 0;		/* XXXX */
800a9c6b5dfSAtsushi Murai   tries = 0;
801af57ed9fSAtsushi Murai   for (;;) {
802780700e5SAndrey A. Chernov     nfds = 0;
803944f7098SBrian Somers     FD_ZERO(&rfds);
804944f7098SBrian Somers     FD_ZERO(&wfds);
805944f7098SBrian Somers     FD_ZERO(&efds);
80684b8a6ebSAtsushi Murai 
80784b8a6ebSAtsushi Murai     /*
808944f7098SBrian Somers      * If the link is down and we're in DDIAL mode, bring it back up.
809680026d6SNate Williams      */
810680026d6SNate Williams     if (mode & MODE_DDIAL && LcpFsm.state <= ST_CLOSED)
81175240ed1SBrian Somers       dial_up = 1;
812680026d6SNate Williams 
813680026d6SNate Williams     /*
814944f7098SBrian Somers      * If we lost carrier and want to re-establish the connection due to the
815944f7098SBrian Somers      * "set reconnect" value, we'd better bring the line back up.
81607030d97SBrian Somers      */
8176efd9292SBrian Somers     if (LcpFsm.state <= ST_CLOSED) {
81875240ed1SBrian Somers       if (!dial_up && reconnectState == RECON_TRUE) {
8196efd9292SBrian Somers 	if (++reconnectCount <= VarReconnectTries) {
820927145beSBrian Somers 	  LogPrintf(LogPHASE, "Connection lost, re-establish (%d/%d)\n",
8216efd9292SBrian Somers 		    reconnectCount, VarReconnectTries);
82207030d97SBrian Somers 	  StartRedialTimer(VarReconnectTimer);
82375240ed1SBrian Somers 	  dial_up = 1;
824298091daSBrian Somers 	} else {
8256efd9292SBrian Somers 	  if (VarReconnectTries)
826927145beSBrian Somers 	    LogPrintf(LogPHASE, "Connection lost, maximum (%d) times\n",
827298091daSBrian Somers 		      VarReconnectTries);
8286efd9292SBrian Somers 	  reconnectCount = 0;
8296efd9292SBrian Somers 	  if (mode & MODE_BACKGROUND)
8306efd9292SBrian Somers 	    Cleanup(EX_DEAD);
8316efd9292SBrian Somers 	}
83225aa96acSBrian Somers 	reconnectState = RECON_ENVOKED;
83312ef29a8SBrian Somers       } else if (mode & MODE_DEDICATED)
83412ef29a8SBrian Somers         if (VarOpenMode == OPEN_ACTIVE)
83512ef29a8SBrian Somers           PacketMode();
83607030d97SBrian Somers     }
83707030d97SBrian Somers 
83807030d97SBrian Somers     /*
839944f7098SBrian Somers      * If Ip packet for output is enqueued and require dial up, Just do it!
84084b8a6ebSAtsushi Murai      */
84107030d97SBrian Somers     if (dial_up && RedialTimer.state != TIMER_RUNNING) {
842927145beSBrian Somers       LogPrintf(LogDEBUG, "going to dial: modem = %d\n", modem);
8439780ef31SBrian Somers       if (OpenModem() < 0) {
8440706ff38SBrian Somers 	tries++;
845712ae387SBrian Somers 	if (!(mode & MODE_DDIAL) && VarDialTries)
8460706ff38SBrian Somers 	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u of %d)\n",
8470706ff38SBrian Somers 		    tries, VarDialTries);
8480706ff38SBrian Somers 	else
8490706ff38SBrian Somers 	  LogPrintf(LogCHAT, "Failed to open modem (attempt %u)\n", tries);
8500706ff38SBrian Somers 
851712ae387SBrian Somers 	if (!(mode & MODE_DDIAL) && VarDialTries && tries >= VarDialTries) {
8520706ff38SBrian Somers 	  if (mode & MODE_BACKGROUND)
8530706ff38SBrian Somers 	    Cleanup(EX_DIAL);	/* Can't get the modem */
85475240ed1SBrian Somers 	  dial_up = 0;
8550706ff38SBrian Somers 	  reconnectState = RECON_UNKNOWN;
8560706ff38SBrian Somers 	  reconnectCount = 0;
8570706ff38SBrian Somers 	  tries = 0;
8580706ff38SBrian Somers 	} else
85943ea9d19SBrian Somers 	  StartRedialTimer(VarRedialTimeout);
86084b8a6ebSAtsushi Murai       } else {
861944f7098SBrian Somers 	tries++;		/* Tries are per number, not per list of
862944f7098SBrian Somers 				 * numbers. */
863712ae387SBrian Somers 	if (!(mode & MODE_DDIAL) && VarDialTries)
864712ae387SBrian Somers 	  LogPrintf(LogCHAT, "Dial attempt %u of %d\n", tries, VarDialTries);
865c0139fb2SBrian Somers 	else
866927145beSBrian Somers 	  LogPrintf(LogCHAT, "Dial attempt %u\n", tries);
867712ae387SBrian Somers 
868368aee2bSBrian Somers 	if ((res = DialModem()) == EX_DONE) {
8699a571ec7SBrian Somers 	  nointr_sleep(1);		/* little pause to allow peer starts */
870b6e82f33SBrian Somers 	  ModemTimeout(NULL);
87184b8a6ebSAtsushi Murai 	  PacketMode();
87275240ed1SBrian Somers 	  dial_up = 0;
87325aa96acSBrian Somers 	  reconnectState = RECON_UNKNOWN;
874a9c6b5dfSAtsushi Murai 	  tries = 0;
87584b8a6ebSAtsushi Murai 	} else {
8764ed9958fSBrian Somers 	  if (mode & MODE_BACKGROUND) {
877368aee2bSBrian Somers 	    if (VarNextPhone == NULL || res == EX_SIG)
8784ed9958fSBrian Somers 	      Cleanup(EX_DIAL);	/* Tried all numbers - no luck */
8794ed9958fSBrian Somers 	    else
88043ea9d19SBrian Somers 	      /* Try all numbers in background mode */
88143ea9d19SBrian Somers 	      StartRedialTimer(VarRedialNextTimeout);
882368aee2bSBrian Somers 	  } else if (!(mode & MODE_DDIAL) &&
883368aee2bSBrian Somers 		     ((VarDialTries && tries >= VarDialTries) ||
884368aee2bSBrian Somers 		      res == EX_SIG)) {
885c0139fb2SBrian Somers 	    /* I give up !  Can't get through :( */
88643ea9d19SBrian Somers 	    StartRedialTimer(VarRedialTimeout);
88775240ed1SBrian Somers 	    dial_up = 0;
88825aa96acSBrian Somers 	    reconnectState = RECON_UNKNOWN;
88925aa96acSBrian Somers 	    reconnectCount = 0;
890a9c6b5dfSAtsushi Murai 	    tries = 0;
891c0139fb2SBrian Somers 	  } else if (VarNextPhone == NULL)
892c0139fb2SBrian Somers 	    /* Dial failed. Keep quite during redial wait period. */
89343ea9d19SBrian Somers 	    StartRedialTimer(VarRedialTimeout);
894c0139fb2SBrian Somers 	  else
89543ea9d19SBrian Somers 	    StartRedialTimer(VarRedialNextTimeout);
89684b8a6ebSAtsushi Murai 	}
89784b8a6ebSAtsushi Murai       }
89884b8a6ebSAtsushi Murai     }
89960e218e4SAtsushi Murai     qlen = ModemQlen();
90076bd0c0aSDoug Rabson 
90176bd0c0aSDoug Rabson     if (qlen == 0) {
90276bd0c0aSDoug Rabson       IpStartOutput();
90376bd0c0aSDoug Rabson       qlen = ModemQlen();
90476bd0c0aSDoug Rabson     }
905780700e5SAndrey A. Chernov     if (modem >= 0) {
906780700e5SAndrey A. Chernov       if (modem + 1 > nfds)
907780700e5SAndrey A. Chernov 	nfds = modem + 1;
90884b8a6ebSAtsushi Murai       FD_SET(modem, &rfds);
90984b8a6ebSAtsushi Murai       FD_SET(modem, &efds);
91060e218e4SAtsushi Murai       if (qlen > 0) {
91184b8a6ebSAtsushi Murai 	FD_SET(modem, &wfds);
91284b8a6ebSAtsushi Murai       }
91384b8a6ebSAtsushi Murai     }
914780700e5SAndrey A. Chernov     if (server >= 0) {
915780700e5SAndrey A. Chernov       if (server + 1 > nfds)
916780700e5SAndrey A. Chernov 	nfds = server + 1;
917780700e5SAndrey A. Chernov       FD_SET(server, &rfds);
918780700e5SAndrey A. Chernov     }
919af57ed9fSAtsushi Murai 
920b1cbb71cSBrian Somers #ifndef SIGALRM
921944f7098SBrian Somers     /*
922944f7098SBrian Somers      * *** IMPORTANT ***
923944f7098SBrian Somers      * CPU is serviced every TICKUNIT micro seconds. This value must be chosen
924b1cbb71cSBrian Somers      * with great care. If this values is too big, it results in loss of
925b1cbb71cSBrian Somers      * characters from the modem and poor response.  If this value is too
926b1cbb71cSBrian Somers      * small, ppp eats too much CPU time.
927af57ed9fSAtsushi Murai      */
928b1cbb71cSBrian Somers     usleep(TICKUNIT);
929af57ed9fSAtsushi Murai     TimerService();
930f5ff0f7cSBrian Somers #else
931f5ff0f7cSBrian Somers     handle_signals();
93253c9f6c0SAtsushi Murai #endif
93368d2b4d6SBruce Evans 
93468d2b4d6SBruce Evans     /* If there are aren't many packets queued, look for some more. */
935780700e5SAndrey A. Chernov     if (qlen < 20 && tun_in >= 0) {
936780700e5SAndrey A. Chernov       if (tun_in + 1 > nfds)
937780700e5SAndrey A. Chernov 	nfds = tun_in + 1;
93884b8a6ebSAtsushi Murai       FD_SET(tun_in, &rfds);
939780700e5SAndrey A. Chernov     }
940780700e5SAndrey A. Chernov     if (netfd >= 0) {
941780700e5SAndrey A. Chernov       if (netfd + 1 > nfds)
942780700e5SAndrey A. Chernov 	nfds = netfd + 1;
943af57ed9fSAtsushi Murai       FD_SET(netfd, &rfds);
944af57ed9fSAtsushi Murai       FD_SET(netfd, &efds);
945af57ed9fSAtsushi Murai     }
94653c9f6c0SAtsushi Murai #ifndef SIGALRM
947944f7098SBrian Somers 
948af57ed9fSAtsushi Murai     /*
949944f7098SBrian Somers      * Normally, select() will not block because modem is writable. In AUTO
950944f7098SBrian Somers      * mode, select will block until we find packet from tun
951af57ed9fSAtsushi Murai      */
952af57ed9fSAtsushi Murai     tp = (RedialTimer.state == TIMER_RUNNING) ? &timeout : NULL;
953780700e5SAndrey A. Chernov     i = select(nfds, &rfds, &wfds, &efds, tp);
95453c9f6c0SAtsushi Murai #else
955944f7098SBrian Somers 
95684b8a6ebSAtsushi Murai     /*
957944f7098SBrian Somers      * When SIGALRM timer is running, a select function will be return -1 and
958944f7098SBrian Somers      * EINTR after a Time Service signal hundler is done.  If the redial
959944f7098SBrian Somers      * timer is not running and we are trying to dial, poll with a 0 value
960944f7098SBrian Somers      * timer.
96184b8a6ebSAtsushi Murai      */
962a9c6b5dfSAtsushi Murai     tp = (dial_up && RedialTimer.state != TIMER_RUNNING) ? &timeout : NULL;
963780700e5SAndrey A. Chernov     i = select(nfds, &rfds, &wfds, &efds, tp);
96453c9f6c0SAtsushi Murai #endif
9656b0b88d8SBrian Somers 
966af57ed9fSAtsushi Murai     if (i == 0) {
967af57ed9fSAtsushi Murai       continue;
968af57ed9fSAtsushi Murai     }
969534fe541SBrian Somers     if (i < 0) {
970534fe541SBrian Somers       if (errno == EINTR) {
971f5ff0f7cSBrian Somers 	handle_signals();
972f5ff0f7cSBrian Somers 	continue;
97384b8a6ebSAtsushi Murai       }
974afc7fa2cSBrian Somers       LogPrintf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
975af57ed9fSAtsushi Murai       break;
976af57ed9fSAtsushi Murai     }
977780700e5SAndrey A. Chernov     if ((netfd >= 0 && FD_ISSET(netfd, &efds)) || (modem >= 0 && FD_ISSET(modem, &efds))) {
978927145beSBrian Somers       LogPrintf(LogALERT, "Exception detected.\n");
979af57ed9fSAtsushi Murai       break;
980af57ed9fSAtsushi Murai     }
981780700e5SAndrey A. Chernov     if (server >= 0 && FD_ISSET(server, &rfds)) {
98258f264e1SBrian Somers       wfd = accept(server, sa, &ssize);
983e0d3e233SAndrey A. Chernov       if (wfd < 0) {
984afc7fa2cSBrian Somers 	LogPrintf(LogERROR, "DoLoop: accept(): %s\n", strerror(errno));
985e0d3e233SAndrey A. Chernov 	continue;
986e0d3e233SAndrey A. Chernov       }
98758f264e1SBrian Somers       switch (sa->sa_family) {
98858f264e1SBrian Somers         case AF_LOCAL:
98958f264e1SBrian Somers           LogPrintf(LogPHASE, "Connected to local client.\n");
99058f264e1SBrian Somers           break;
99158f264e1SBrian Somers         case AF_INET:
9924401489aSBrian Somers           if (ntohs(sin->sin_port) < 1024) {
99358f264e1SBrian Somers             LogPrintf(LogALERT, "Rejected client connection from %s:%u"
99458f264e1SBrian Somers                       "(invalid port number) !\n",
9954401489aSBrian Somers                       inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
996af57ed9fSAtsushi Murai 	    close(wfd);
997af57ed9fSAtsushi Murai 	    continue;
99858f264e1SBrian Somers           }
99958f264e1SBrian Somers           LogPrintf(LogPHASE, "Connected to client from %s:%u\n",
100058f264e1SBrian Somers                     inet_ntoa(sin->sin_addr), sin->sin_port);
100158f264e1SBrian Somers           break;
100258f264e1SBrian Somers         default:
100358f264e1SBrian Somers 	  write(wfd, "Unrecognised access !\n", 22);
100458f264e1SBrian Somers 	  close(wfd);
100558f264e1SBrian Somers 	  continue;
100658f264e1SBrian Somers       }
100758f264e1SBrian Somers       if (netfd >= 0) {
100858f264e1SBrian Somers 	write(wfd, "Connection already in use.\n", 27);
100958f264e1SBrian Somers 	close(wfd);
101058f264e1SBrian Somers 	continue;
101158f264e1SBrian Somers       }
1012af57ed9fSAtsushi Murai       netfd = wfd;
1013927145beSBrian Somers       VarTerm = fdopen(netfd, "a+");
10148ea8442cSBrian Somers       LocalAuthInit();
1015af57ed9fSAtsushi Murai       Greetings();
1016a1e8f937SBrian Somers       IsInteractive(1);
1017274e766cSBrian Somers       Prompt();
1018af57ed9fSAtsushi Murai     }
10190053cc58SBrian Somers     if (netfd >= 0 && FD_ISSET(netfd, &rfds))
1020af57ed9fSAtsushi Murai       /* something to read from tty */
1021af57ed9fSAtsushi Murai       ReadTty();
10220053cc58SBrian Somers     if (modem >= 0 && FD_ISSET(modem, &wfds)) {
10230053cc58SBrian Somers       /* ready to write into modem */
1024af57ed9fSAtsushi Murai       ModemStartOutput(modem);
10250053cc58SBrian Somers       if (modem < 0)
10260053cc58SBrian Somers         dial_up = 1;
1027af57ed9fSAtsushi Murai     }
10280053cc58SBrian Somers     if (modem >= 0 && FD_ISSET(modem, &rfds)) {
10290053cc58SBrian Somers       /* something to read from modem */
103053c9f6c0SAtsushi Murai       if (LcpFsm.state <= ST_CLOSED)
10319a571ec7SBrian Somers 	nointr_usleep(10000);
103270ee81ffSBrian Somers       n = read(modem, rbuff, sizeof rbuff);
1033af57ed9fSAtsushi Murai       if ((mode & MODE_DIRECT) && n <= 0) {
1034af57ed9fSAtsushi Murai 	DownConnection();
1035af57ed9fSAtsushi Murai       } else
1036927145beSBrian Somers 	LogDumpBuff(LogASYNC, "ReadFromModem", rbuff, n);
1037af57ed9fSAtsushi Murai 
1038af57ed9fSAtsushi Murai       if (LcpFsm.state <= ST_CLOSED) {
1039af57ed9fSAtsushi Murai 	/*
1040af57ed9fSAtsushi Murai 	 * In dedicated mode, we just discard input until LCP is started.
1041af57ed9fSAtsushi Murai 	 */
1042af57ed9fSAtsushi Murai 	if (!(mode & MODE_DEDICATED)) {
1043af57ed9fSAtsushi Murai 	  cp = HdlcDetect(rbuff, n);
1044af57ed9fSAtsushi Murai 	  if (cp) {
1045af57ed9fSAtsushi Murai 	    /*
1046af57ed9fSAtsushi Murai 	     * LCP packet is detected. Turn ourselves into packet mode.
1047af57ed9fSAtsushi Murai 	     */
1048af57ed9fSAtsushi Murai 	    if (cp != rbuff) {
1049927145beSBrian Somers 	      write(modem, rbuff, cp - rbuff);
1050927145beSBrian Somers 	      write(modem, "\r\n", 2);
1051af57ed9fSAtsushi Murai 	    }
1052af57ed9fSAtsushi Murai 	    PacketMode();
1053af57ed9fSAtsushi Murai 	  } else
1054927145beSBrian Somers 	    write(fileno(VarTerm), rbuff, n);
1055af57ed9fSAtsushi Murai 	}
1056af57ed9fSAtsushi Murai       } else {
1057af57ed9fSAtsushi Murai 	if (n > 0)
1058af57ed9fSAtsushi Murai 	  AsyncInput(rbuff, n);
1059af57ed9fSAtsushi Murai       }
1060af57ed9fSAtsushi Murai     }
1061944f7098SBrian Somers     if (tun_in >= 0 && FD_ISSET(tun_in, &rfds)) {	/* something to read
1062944f7098SBrian Somers 							 * from tun */
106370ee81ffSBrian Somers       n = read(tun_in, &tun, sizeof tun);
1064af57ed9fSAtsushi Murai       if (n < 0) {
1065afc7fa2cSBrian Somers 	LogPrintf(LogERROR, "read from tun: %s\n", strerror(errno));
1066af57ed9fSAtsushi Murai 	continue;
1067af57ed9fSAtsushi Murai       }
106870ee81ffSBrian Somers       n -= sizeof tun - sizeof tun.data;
10696a6b4bbbSBrian Somers       if (n <= 0) {
10706a6b4bbbSBrian Somers 	LogPrintf(LogERROR, "read from tun: Only %d bytes read\n", n);
10716a6b4bbbSBrian Somers 	continue;
10726a6b4bbbSBrian Somers       }
10736a6b4bbbSBrian Somers       if (!tun_check_header(tun, AF_INET))
10746a6b4bbbSBrian Somers           continue;
1075de451c68SBrian Somers       if (((struct ip *) rbuff)->ip_dst.s_addr == IpcpInfo.want_ipaddr.s_addr) {
1076de451c68SBrian Somers 	/* we've been asked to send something addressed *to* us :( */
1077de451c68SBrian Somers 	if (VarLoopback) {
1078de451c68SBrian Somers 	  pri = PacketCheck(rbuff, n, FL_IN);
1079de451c68SBrian Somers 	  if (pri >= 0) {
1080de451c68SBrian Somers 	    struct mbuf *bp;
1081944f7098SBrian Somers 
1082b6e82f33SBrian Somers #ifndef NOALIAS
1083de451c68SBrian Somers 	    if (mode & MODE_ALIAS) {
1084de451c68SBrian Somers 	      VarPacketAliasIn(rbuff, sizeof rbuff);
1085de451c68SBrian Somers 	      n = ntohs(((struct ip *) rbuff)->ip_len);
1086de451c68SBrian Somers 	    }
1087b6e82f33SBrian Somers #endif
1088de451c68SBrian Somers 	    bp = mballoc(n, MB_IPIN);
108975240ed1SBrian Somers 	    memcpy(MBUF_CTOP(bp), rbuff, n);
1090de451c68SBrian Somers 	    IpInput(bp);
1091de451c68SBrian Somers 	    LogPrintf(LogDEBUG, "Looped back packet addressed to myself\n");
1092de451c68SBrian Somers 	  }
1093de451c68SBrian Somers 	  continue;
1094de451c68SBrian Somers 	} else
1095de451c68SBrian Somers 	  LogPrintf(LogDEBUG, "Oops - forwarding packet addressed to myself\n");
1096de451c68SBrian Somers       }
1097de451c68SBrian Somers 
1098af57ed9fSAtsushi Murai       /*
1099af57ed9fSAtsushi Murai        * Process on-demand dialup. Output packets are queued within tunnel
1100af57ed9fSAtsushi Murai        * device until IPCP is opened.
1101af57ed9fSAtsushi Murai        */
1102c60f92caSBrian Somers       if (LcpFsm.state <= ST_CLOSED && (mode & MODE_AUTO) &&
1103c60f92caSBrian Somers 	  (pri = PacketCheck(rbuff, n, FL_DIAL)) >= 0)
1104c60f92caSBrian Somers         dial_up = 1;
1105c60f92caSBrian Somers 
110684b8a6ebSAtsushi Murai       pri = PacketCheck(rbuff, n, FL_OUT);
1107a9f484e5SJordan K. Hubbard       if (pri >= 0) {
1108b6e82f33SBrian Somers #ifndef NOALIAS
1109a9f484e5SJordan K. Hubbard 	if (mode & MODE_ALIAS) {
11106ed9fb2fSBrian Somers 	  VarPacketAliasOut(rbuff, sizeof rbuff);
1111a9f484e5SJordan K. Hubbard 	  n = ntohs(((struct ip *) rbuff)->ip_len);
1112a9f484e5SJordan K. Hubbard 	}
1113b6e82f33SBrian Somers #endif
1114af57ed9fSAtsushi Murai 	IpEnqueue(pri, rbuff, n);
1115af57ed9fSAtsushi Murai       }
1116af57ed9fSAtsushi Murai     }
1117a9f484e5SJordan K. Hubbard   }
1118927145beSBrian Somers   LogPrintf(LogDEBUG, "Job (DoLoop) done.\n");
1119af57ed9fSAtsushi Murai }
1120